加入了基於簡單優先順序的任務排程,看著好像跟時間片輪轉沒什麼區別
阿新 • • 發佈:2019-01-06
int k_reenter = -1; // Descriptor typedef struct descriptor { short limit_low; short base_low; char base_mid; char access_right; char limit_high; char base_high; }descriptor, *Descriptor; typedef struct gate { short offset_low; short selector; char dw_count; char access_right; short offset_high; }gate, *Gate; // start process data struct typedef struct tss { int backlink; int esp0; int ss0; int esp1; int ss1; int esp2; int ss2; int cr3; int eip; int eflags; int eax; int ecx; int edx; int ebx; int esp; int ebp; int esi; int edi; int es; int cs; int ss; int ds; int fs; int gs; int ldt_sel; short trap; short iobase; }tss, *Tss; typedef struct proc_stack { int gs; int fs; int es; int ds; int edi; int esi; int ebp; int kernel_esp; int ebx; int edx; int ecx; int eax; int retaddr; int eip; int cs; int eflags; int esp; int ss; }proc_stack; typedef struct process { proc_stack procstack; short ldt_selector; descriptor ldt[0x10]; int pid; char name[32]; unsigned int ticks; unsigned int priority; }process, *Process; // end process data struct void print_s(char *str, char color, int j); void halt(void); void delay(int count); void load_gdtr(int limit, int addr); void load_idtr(int limit, int addr); void asm_inthandler_all(void); void asm_inthandler_0xd(void); void asm_inthandler_0x20(void); void asm_inthandler_0x21(void); void ud2(void); void testa(void); void testb(void); void testc(void); void testd(void); void teste(void); void testf(void); void testg(void); void testh(void); void set_descriptor(Descriptor sd, unsigned int limit, int base, int attrib); void set_gate(Gate gd, int offset, int selector, int attrib); // S:copy from multiboot2 os example. #define COLUMNS 80 #define LINES 24 #define ATTRIBUTE 7 #define VIDEO 0xb8000 static int xpos; static int ypos; static volatile unsigned char *video; static void cls (void); static void itoa (char *buf, int base, int d); static void putchar (int c); void printf (const char *format, ...); void out(int port, int value); int in(int port); void sti(void); void cli(void); void init_8259a(void); void init_8254(void); int mycount = 0; char *func_stack = (char *)0x800000; process p_proc[8]; Process p_proc_ready, myproc; tss tss0; Tss mytss = &tss0; typedef void (*task_f)(void); typedef struct s_task { task_f initial_eip; int stacksize; char name[0x20]; }task, *Task; task task_table[8] = {{testa, 0x400, "testa"}, \ {testb, 0x400, "testb"}, \ {testc, 0x400, "testc"}, \ {testd, 0x400, "testd"}, \ {teste, 0x400, "teste"}, \ {testf, 0x400, "testf"}, \ {testg, 0x400, "testg"}, \ {testh, 0x400, "testh"}}; void goto_ring3(void); void ltr(int tr); void init_tss(Tss mytss, Descriptor mygdt); void init_proc_table(Process myproc, Task mytask, Descriptor mygdt); void schedule(Process p); int kernel_main(int eax, int ebx) { cls(); Process myproc; myproc = p_proc; Descriptor mygdt = (Descriptor) 0x7c00; Gate myidt = (Gate) 0x0; set_descriptor(mygdt + 0, 0, 0, 0); //0 * 8 set_descriptor(mygdt + 1, 0xffffffff, 0x0, 0xc09a); //1 * 8 set_descriptor(mygdt + 2, 0xffffffff, 0x0, 0xc092); //2 * 8 load_idtr(256 * 8 - 1, (int) myidt); load_gdtr(256 * 8 - 1, (int) mygdt); Task p_task = task_table; init_proc_table(myproc, p_task, mygdt); int i; for(i = 0; i < 256; i++) { set_gate(myidt + i, (int) asm_inthandler_all, 0x8, 0x8e); } set_gate(myidt + 0xd, (int) asm_inthandler_0xd, 0x8, 0x8e); set_gate(myidt + 0x20, (int) asm_inthandler_0x20, 1 * 8, 0x8e); set_gate(myidt + 0x21, (int) asm_inthandler_0x21, 1 * 8, 0x8e); // set_gate(myidt + 0x80, (int) system_interrupt, 1 * 8, 0xee); init_tss(mytss, mygdt); init_8259a(); init_8254(); out(0x21, 0xf8); out(0xa1, 0xff); p_proc_ready = p_proc; goto_ring3(); while(1) { print_s("Sys!", 0xf, 17); } return 0; } void print_s(char *str, char color, int j) { int i = 0; while(*str) { while(*str == '\n') { str++; i = 0; j++; } if(!(*str)) { return; } *(video + i + j * 80 * 2) = *str++; *(video + i + 1 + j * 80 * 2) = color; i += 2; } return; } /* Clear the screen and initialize VIDEO, XPOS and YPOS. */ static void cls (void) { int i; video = (unsigned char *) VIDEO; for (i = 0; i < COLUMNS * LINES * 2; i++) *(video + i) = 0; xpos = 0; ypos = 0; return; } /* Convert the integer D to a string and save the string in BUF. If BASE is equal to 'd', interpret that D is decimal, and if BASE is equal to 'x', interpret that D is hexadecimal. */ static void itoa (char *buf, int base, int d) { char *p = buf; char *p1, *p2; unsigned long ud = d; int divisor = 10; /* If %d is specified and D is minus, put `-' in the head. */ if (base == 'd' && d < 0) { *p++ = '-'; buf++; ud = -d; } else if (base == 'x') divisor = 16; /* Divide UD by DIVISOR until UD == 0. */ do { int remainder = ud % divisor; *p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10; } while (ud /= divisor); /* Terminate BUF. */ *p = 0; /* Reverse BUF. */ p1 = buf; p2 = p - 1; while (p1 < p2) { char tmp = *p1; *p1 = *p2; *p2 = tmp; p1++; p2--; } } /* Put the character C on the screen. */ static void putchar (int c) { if (c == '\n' || c == '\r') { newline: xpos = 0; ypos++; if (ypos >= LINES) ypos = 0; return; } *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF; *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE; xpos++; if (xpos >= COLUMNS) goto newline; } /* Format a string and print it on the screen, just like the libc function printf. */ void printf (const char *format, ...) { char **arg = (char **) &format; int c; char buf[20]; arg++; while ((c = *format++) != 0) { if (c != '%') putchar (c); else { char *p, *p2; int pad0 = 0, pad = 0; c = *format++; if (c == '0') { pad0 = 1; c = *format++; } if (c >= '0' && c <= '9') { pad = c - '0'; c = *format++; } switch (c) { case 'd': case 'u': case 'x': itoa (buf, c, *((int *) arg++)); p = buf; goto string; break; case 's': p = *arg++; if (! p) p = "(null)"; string: for (p2 = p; *p2; p2++); for (; p2 < p + pad; p2++) putchar (pad0 ? '0' : ' '); while (*p) putchar (*p++); break; default: putchar (*((int *) arg++)); break; } } } } void *memcpy(void *dest, void *source, int count) { int i; void *temp = dest; for(i = 0; i < count; i++) { *((char *)dest++) = *((char *)source++); } return temp; } void set_descriptor(Descriptor sd, unsigned int limit, int base, int attrib) { if(limit > 0xfffff) { attrib |= 0x8000; limit /= 0x1000; } sd->limit_low = limit & 0xffff; sd->base_low = base & 0xffff; sd->base_mid = (base >> 16) & 0xff; sd->access_right = attrib & 0xff; sd->limit_high = ((limit >> 16) & 0x0f) | ((attrib >> 8) & 0xf0); sd->base_high = (base >> 24) & 0xff; return; } void set_gate(Gate gd, int offset, int selector, int attrib) { gd->offset_low = offset & 0xffff; gd->selector = selector; gd->dw_count = (attrib >> 8) & 0xff; gd->access_right = attrib & 0xff; gd->offset_high = (offset >> 16) & 0xffff; return; } void inthandler_all(int *esp) { printf("Exception! 0x%x", esp); while(1) { halt(); } return; } void inthandler_0xd(int *esp) { printf("general protection! 0x%x", esp); while(1) { halt(); } return; } void inthandler_0x21(int *esp) { out(0x20, 0x61); int key = in(0x60); char buf[0x40]; print_s("keyboard interrupt!", 0xf, 21); print_s(" ", 0xf, 22); itoa(buf, 10, key); print_s(buf, 0xf, 22); return; } int ia = 0; void testa(void) { char buf[0x20]; while (1) { print_s("testa", 0x9, 0); itoa(buf, 10, ia++); print_s(buf, 0x9, 1); // delay(0xfffff); } return; } int ib = 0; void testb(void) { char buf[0x20]; while (1) { print_s("testb", 0xd, 2); itoa(buf, 10, ib++); print_s(buf, 0xd, 3); // delay(0xfff); } return; } int ic = 0; void testc(void) { char buf[0x20]; while (1) { print_s("testc", 0xf, 4); itoa(buf, 10, ic++); print_s(buf, 0xf, 5); // delay(0x888); } return; } int id = 0; void testd(void) { char buf[0x20]; while (1) { print_s("testd", 0xe, 6); itoa(buf, 10, id++); print_s(buf, 0xe, 7); // delay(0x88); } return; } int ie = 0; void teste(void) { char buf[0x20]; while (1) { print_s("teste", 0x4, 8); itoa(buf, 10, ie++); print_s(buf, 0x4, 9); // delay(0xffff); } return; } int iff = 0; void testf(void) { char buf[0x20]; while (1) { print_s("testf", 0x8, 10); itoa(buf, 10, iff++); print_s(buf, 0x8, 11); // delay(0xf); } return; } int ig = 0; void testg(void) { char buf[0x20]; while (1) { print_s("testg", 0x6, 12); itoa(buf, 10, ig++); print_s(buf, 0x6, 13); // delay(0xaaaaa); } return; } int ih = 0; void testh(void) { char buf[0x20]; while (1) { print_s("testh", 0x7, 14); itoa(buf, 10, ih++); print_s(buf, 0x7, 15); // delay(0xccc); } return; } void init_8254(void) { out(0x43, 0x36); out(0x40, 0x9c); out(0x40, 0x2e); return; } void init_proc_table(Process myproc, Task mytask, Descriptor mygdt) { int i; for(i = 0; i < 8; i++) { myproc->ticks = myproc->priority = 2 + i; myproc->pid = i; myproc->ldt_selector = (3 + i) * 8; set_descriptor(mygdt + (3 + i), 8 * 0x10 - 1, (int)myproc->ldt, 0xc0e2); set_descriptor(myproc->ldt + 0, 0xffffffff, 0x0, 0xc0fa); //0 * 8 + 7 set_descriptor(myproc->ldt + 1, 0xffffffff, 0x0, 0xc0f2); //1 * 8 + 7 myproc->procstack.gs = 0xf; myproc->procstack.fs = 0xf; myproc->procstack.es = 0xf; myproc->procstack.ds = 0xf; myproc->procstack.edi = 0x0; myproc->procstack.esi = 0x0; myproc->procstack.ebp = 0x0; myproc->procstack.kernel_esp = 0; myproc->procstack.ebx = 0x0; myproc->procstack.edx = 0x0; myproc->procstack.ecx = 0x0; myproc->procstack.eax = 0x0; myproc->procstack.retaddr = 0x0; myproc->procstack.eip = (int)mytask->initial_eip; myproc->procstack.cs = 0x7; myproc->procstack.eflags = 0x202; myproc->procstack.esp = (int)func_stack; myproc->procstack.ss = 0xf; myproc++; mytask++; func_stack -= 0x400; } return; } void init_tss(Tss mytss, Descriptor mygdt) { set_descriptor(mygdt + 20, sizeof(tss0), (int)mytss, 0xc0e9); //20 * 8 mytss->backlink = 0; mytss->esp0 = 0; mytss->ss0 = 2 * 8; mytss->esp1= 0; mytss->ss1 = 0; mytss->esp2 = 0; mytss->ss2 = 0; mytss->cr3 = 0; mytss->eflags = 0; mytss->eax = 0; mytss->ecx = 0; mytss->edx = 0; mytss->esp = 0; mytss->ebp = 0; mytss->esi = 0; mytss->edi = 0; mytss->es = 0xf; mytss->cs = 0x7; mytss->ss = 0xf; mytss->ds = 0xf; mytss->fs = 0xf; mytss->gs = 0xf; mytss->ldt_sel = 0; mytss->trap = 0; mytss->iobase = sizeof(tss); ltr(20 * 8); return; } void inthandler_0x20(int *esp) { char buf[0x40]; print_s("timer interrupt!", 0xc, 23); itoa(buf, 10, mycount++); print_s(buf, 0xc, 24); p_proc_ready->ticks--; if(p_proc_ready->ticks > 0) return; schedule(p_proc); return; } void schedule(Process p) { // p_proc_ready++; // 時間片輪轉法 // if(p_proc_ready >= p_proc + 8) // p_proc_ready = p_proc; int myticks = 0; // 簡單優先順序法 while(!myticks) { for(p = p_proc; p < p_proc + 8; p++) { if(p->ticks > myticks) { myticks = p->ticks; p_proc_ready = p; } } if(!myticks) { for(p = p_proc; p < p_proc + 8; p++) { p->ticks = p->priority; } } } return; }