рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ, рд╣рдордиреЗ рд╕реАрдЦрд╛ рдХрд┐ рд╡рд░реНрдЪреБрдЕрд▓ рдПрдбреНрд░реЗрд╕ рд╕реНрдкреЗрд╕ рдХреЗ рд╕рд╛рде рдХреИрд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛ рдЬрд╛рдПред рдЖрдЬ рд╣рдо рдорд▓реНрдЯреАрдЯрд╛рд╕реНрдХрд┐рдВрдЧ рд╕рдорд░реНрдерди рдЬреЛрдбрд╝реЗрдВрдЧреЗред
рд╕рд╛рдордЧреНрд░реА рдХреА рддрд╛рд▓рд┐рдХрд╛
рдмрд┐рд▓реНрдб рд╕рд┐рд╕реНрдЯрдо (рдореЗрдХ, рдЬреАрд╕реАрд╕реА, рдЧреИрд╕)ред рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдмреВрдЯ (рдорд▓реНрдЯреАрдмреВрдЯ)ред рд▓реЙрдиреНрдЪ (qemu)ред рд╕реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА (strcpy, memcpy, strext)ред
рд╕реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА (рд╕реНрдкреНрд░рд┐рдВрдЯрдл, рд╕реНрдЯреНрд░реИрдЪреА, рд╕реНрдЯреНрд░реИрдореНрдк, рд╕реНрдЯреНрд░реЗрдЯреЛрдХ, рд╡рд╛_рд▓рд┐рд╕реНрдЯ ...)ред рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рдХрд░реНрдиреЗрд▓ рдореЛрдб рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЛрдб рдореЗрдВ рдмрдирд╛рдирд╛ред
рдХрд░реНрдиреЗрд▓ рд╕рд┐рд╕реНрдЯрдо рд▓реЙрдЧред рд╡реАрдбрд┐рдпреЛ рдореЗрдореЛрд░реА рдЯрд░реНрдорд┐рдирд▓ рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ (kprintf, kpanic, kassert)ред
рдбрд╛рдпрдиреЗрдорд┐рдХ рдореЗрдореЛрд░реА, рд╣реАрдк (kmalloc, kfree)ред
рдореЗрдореЛрд░реА рдФрд░ рдЗрдВрдЯрд░рдкреНрдЯ рд╣реИрдВрдбрд▓рд┐рдВрдЧ (GDT, IDT, PIC, syscall) рдХрд╛ рд╕рдВрдЧрдардиред рдЕрдкрд╡рд╛рджред
рд╡рд░реНрдЪреБрдЕрд▓ рдореЗрдореЛрд░реА (рдкреЗрдЬ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдФрд░ рдкреЗрдЬ рдЯреЗрдмрд▓)ред
рдкреНрд░рдХреНрд░рд┐рдпрд╛ред рд╕рдордпрдмрджреНрдзрдХред рдорд▓реНрдЯреАрдЯрд╛рд╕реНрдХрд┐рдВрдЧред рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ (рдорд╛рд░, рдирд┐рдХрд╛рд╕, рдкреАрдПрд╕)редрдХрд░реНрдиреЗрд▓ рдХреА рдлрд╝рд╛рдЗрд▓ рдкреНрд░рдгрд╛рд▓реА (initrd), рдпреЛрдЧрд┐рдиреА, рдФрд░ рдЗрд╕рдХреЗ рдЖрдВрддрд░рд┐рдХред рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ (рдирд┐рд╖реНрдкрд╛рджрди)ред
рдЪрд░рд┐рддреНрд░ рдбрд┐рд╡рд╛рдЗрд╕ рдбреНрд░рд╛рдЗрд╡рд░ред рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ (ioctl, fopen, fread, fwrite)ред рд╕реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА (fopen, fclose, fprintf, fscanf)ред
рдХрд░реНрдиреЗрд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреВрд░реНрдг рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рд░реВрдк рдореЗрдВ рд╢реЗрд▓ред
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реБрд░рдХреНрд╖рд╛ рдореЛрдб (рд░рд┐рдВрдЧ 3)ред рдЯрд╛рд╕реНрдХ рд╕реНрдЯреЗрдЯрд╕ рд╕реЗрдЧрдореЗрдВрдЯ (tss)ред
рдорд▓реНрдЯреАрдЯрд╛рд╕реНрдХрд┐рдВрдЧ
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдХреЛ рдпрд╛рдж рд╣реИ, рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдЕрдкрдирд╛ рдкрддрд╛ рд╕реНрдерд╛рди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдкреГрд╖реНрдареЛрдВ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЗрд╕рд▓рд┐рдП, рд╣рдореЗрдВ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреА рд╕реНрдореГрддрд┐ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:
struct task_mem_t { void* pages; u_int pages_count; void* page_dir; void* page_table; };
рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдХрд┐рд╕реА рддрд░рд╣ рдПрдХ рджреВрд╕рд░реЗ рдХреЗ рд╕рд╛рде рд╕реВрдЪрдирд╛ рдХрд╛ рдЖрджрд╛рди-рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рд╕рдВрджреЗрд╢ рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддреЗ рд╣реИрдВ:
struct message_t { u_short type; u_int len; u8 data[IPC_MSG_DATA_BUFF_SIZE]; };
рдЙрд╕рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдПрдХ рдкрд░рд┐рдкрддреНрд░ рд╕реВрдЪреА рдХреЗ рдПрдХ рддрддреНрд╡ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдпрд╣рд╛рдБ рдЪрдХреНрд░реАрдп рд╕реВрдЪреА рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЕрдиреБрд╕реВрдЪрдХ рдореЗрдВ рдЖрдкрдХреЛ рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдп рд╕реЗ рдЕрдЧрд▓реЗ рдХрд╛ рдЪрдпрди рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдЬрдм рддрдХ рдХрд┐ рд╕реВрдЪреА рдЦрд╛рд▓реА рди рд╣реЛред
рдЗрд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рд╣рдо рдкрддрд┐рдд рдорд╛рдорд▓реЗ рдХреЛ рд╣рдЯрд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рд╣рдо рддрд░реНрдХ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рддреЗ рд╣реИрдВред
struct task_t { struct clist_head_t list_head; u_short tid; char name[8]; struct gp_registers_t gp_registers; struct op_registers_t op_registers; struct flags_t flags; u_int time; bool reschedule; u_short status; int msg_count_in; struct message_t msg_buff[TASK_MSG_BUFF_SIZE]; void* kstack; void* ustack; struct task_mem_t task_mem; } attribute(packed);
рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЛрдЯрд╛ рдЖрд╡рдВрдЯрд┐рдд рдХрд░реЗрдВрдЧреЗ, рдЯрд╛рдЗрдорд░ рдХреА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд╡реНрдпрд╡рдзрд╛рди рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╢реЗрдбреНрдпреВрд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
#define TASK_QUOTA 3
рдЗрд╕рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдПрдХ рдирдИ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ред
рдЬрдмрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╡рд┐рд╢реЗрд╖рд╛рдзрд┐рдХрд╛рд░ рд╕реНрддрд░ рдирд╣реАрдВ рд╣реИрдВ, рд╣рдо рдХрд░реНрдиреЗрд▓ рдЪрдпрдирдХрд░реНрддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред
рд╣рдореЗрдВ рднрд╡рд┐рд╖реНрдп рдХреЗ рд▓рд┐рдП 2 рд╕реНрдЯреИрдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдореЛрдб рдХреЗ рд▓рд┐рдП рдФрд░ рдПрдХ рдХрд░реНрдиреЗрд▓ рдХреЗ рд▓рд┐рдПред
рд╣рдо рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рдХреЛ TASK_UNINTERRUPTABLE рдХреЗ рд░реВрдк рдореЗрдВ рд╕реЗрдЯ рдХрд░реЗрдВрдЧреЗ рддрд╛рдХрд┐ рдХрд╛рд░реНрдп рдХреЛ рдкреВрд░реНрдг рдЖрд░рдВрдн рд╕реЗ рдкрд╣рд▓реЗ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рди рд╣реЛред
extern bool task_create(u_short tid, void* address, struct task_mem_t *task_mem) { struct task_t* task; struct clist_head_t* entry; entry = clist_insert_entry_after(&task_list, task_list.head); task = (struct task_t*)entry->data; task->kstack = malloc(TASK_KSTACK_SIZE); task->ustack = malloc(TASK_USTACK_SIZE); task->tid = tid; task->name[0] = '\0'; task->status = TASK_UNINTERRUPTABLE; task->msg_count_in = 0; task->time = 0; memcpy(&task->task_mem, task_mem, sizeof(struct task_mem_t)); *(u32*)(&task->flags) = asm_get_eflags() | 0x200; memset(&task->gp_registers, 0, sizeof(struct gp_registers_t)); task->op_registers.cs = GDT_KCODE_SELECTOR; task->op_registers.ds = GDT_KDATA_SELECTOR; task->op_registers.ss = GDT_KSTACK_SELECTOR; task->op_registers.eip = (size_t)address; task->op_registers.cr3 = (size_t)task_mem->page_dir; task->op_registers.k_esp = (u32)task->kstack + TASK_KSTACK_SIZE; task->op_registers.u_esp = (u32)task->ustack + TASK_USTACK_SIZE; printf(MSG_SCHED_TID_CREATE, tid, (u_int)address, task->kstack, task->ustack); return true; }
рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреА рд╕реНрдерд┐рддрд┐ TASK_KILLING рд╣реЛрдиреЗ рдкрд░ рд╢реЗрдбреНрдпреВрд▓рд░ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рд╣рдЯрд╛рддреЗ рд╕рдордп, рд╣рдореЗрдВ рдХреЗрд╡рд▓ рд╕реНрдЯреИрдХреНрд╕, рдбреЗрдЯрд╛ рдФрд░ рдХреЛрдб рдЕрдиреБрднрд╛рдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЖрд╡рдВрдЯрд┐рдд рдкреГрд╖реНрдареЛрдВ рдХреЛ рдореБрдХреНрдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкреГрд╖реНрдареЛрдВ рдХреА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЛ рднреА рдирд╖реНрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдПрдХ рдЕрдЪреНрдЫреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реНрдЯреИрдХ рдХреЗ рд▓рд┐рдП, рдЖрдк рдореЗрдореЛрд░реА рдореИрдиреЗрдЬрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрд╡рдВрдЯрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, рдбрд┐рдмрдЧрд┐рдВрдЧ рдХрд░рддреЗ рд╕рдордп рд╣рдо рдЗрд╕реЗ рдХрд░реНрдиреЗрд▓ рдХреЗ рдвреЗрд░ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рд╣рдореЗрд╢рд╛ рдкреГрд╖реНрда рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рдореЗрдВ рд╣реЛрддрд╛ рд╣реИред
extern void task_delete(struct task_t* task) { printf(MSG_SCHED_TID_DELETE, (u_int)task->tid); assert(task != null); free(task->kstack); free(task->ustack); task->kstack = null; task->ustack = null; if (task->task_mem.pages_count > 0) { mm_phys_free_pages(task->task_mem.pages, task->task_mem.pages_count); task->task_mem.pages = null; task->task_mem.pages_count = 0; } if (task->task_mem.page_dir != null) { mmu_destroy_user_page_directory(task->task_mem.page_dir, task->task_mem.page_table); } clist_delete_entry(&task_list, (struct clist_head_t*)task); }
рдЕрдм рдЖрдкрдХреЛ рдЦреБрдж рд╢реЗрдбреНрдпреВрд▓рд░ рд▓рд┐рдЦрдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИред
рдкрд╣рд▓реЗ рд╣рдореЗрдВ рдпрд╣ рд╕рдордЭрдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдп рдЪрд▓ рд░рд╣рд╛ рд╣реИ рдпрд╛ рдпрд╣ рдкрд╣рд▓рд╛ рд░рди рд╣реИред
рдпрджрд┐ рдХрд╛рд░реНрдп рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдЙрд╕рдХрд╛ рдХреЛрдЯрд╛ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдпрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред
рдпрджрд┐ рдРрд╕рд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рд╕рдХреНрд╖рдо рдмрд╛рдзрд╛ рдзреНрд╡рдЬ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдХреЗ рдЗрд╕рдХреЗ рд░рд╛рдЬреНрдп рдХреЛ рдмрдЪрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЙрд╕рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рд╕реНрдерд┐рддрд┐ TASK_RUNNING рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдЕрдЧрд▓рд╛ рдХрд╛рд░реНрдп рдЦреЛрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЗрд╕рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ TASK_KILLING рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдп рдкреВрд░рд╛ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдЕрдЧрд▓реЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рд╕реНрдЯреИрдХ рдлреНрд░реЗрдо рддреИрдпрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдХрд░рддреЗ рд╣реИрдВред
extern void sched_schedule(size_t* ret_addr, size_t* reg_addr) { struct task_t* next_task = null; if (current_task != null) { current_task->time += 1; if (current_task->time < TASK_QUOTA && !current_task->reschedule) { return; } current_task->time = 0; current_task->reschedule = false; current_task->op_registers.eip = *ret_addr; current_task->op_registers.cs = *(u16*)((size_t)ret_addr + 4); *(u32*)(¤t_task->flags) = *(u32*)((size_t)ret_addr + 6) | 0x200; current_task->op_registers.u_esp = (size_t)ret_addr + 12; current_task->gp_registers.esp = current_task->op_registers.u_esp; memcpy(¤t_task->gp_registers, (void*)reg_addr, sizeof(struct gp_registers_t)); } if (current_task) { next_task = task_get_next_by_status(TASK_RUNNING, current_task); } else { next_task = task_get_by_status(TASK_RUNNING); tss_set_kernel_stack(next_task->kstack); } assert(next_task != null); if (current_task && current_task->status == TASK_KILLING) { task_delete(current_task); } else { struct task_t* task; task = task_find_by_status(TASK_KILLING); if (task) { task_delete(task); } } next_task->op_registers.u_esp -= 4; *(u32*)(next_task->op_registers.u_esp) = (*(u16*)(&next_task->flags)) | 0x200; next_task->op_registers.u_esp -= 4; *(u32*)(next_task->op_registers.u_esp) = next_task->op_registers.cs; next_task->op_registers.u_esp -= 4; *(u32*)(next_task->op_registers.u_esp) = next_task->op_registers.eip; next_task->gp_registers.esp = next_task->op_registers.u_esp; next_task->op_registers.u_esp -= sizeof(struct gp_registers_t); memcpy((void*)next_task->op_registers.u_esp, (void*)&next_task->gp_registers, sizeof(struct gp_registers_t)); current_task = next_task; printf(MSG_SCHED_NEXT, next_task->tid, next_task->op_registers.u_esp, *ret_addr, next_task->op_registers.eip); asm_switch_ucontext(next_task->op_registers.u_esp, next_task->op_registers.cr3); }
рдпрд╣ рдПрдХ рдХрд╛рд░реНрдп рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪрд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд░рд╣рддрд╛ рд╣реИред
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рдирдИ рдкреГрд╖реНрда рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдФрд░ рд╕рднреА рд╕рд╛рдорд╛рдиреНрдп рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдЭрдВрдбреЗ рднреА рд╢рд╛рдорд┐рд▓ рд╣реИрдВред
рдЖрдкрдХреЛ рдЕрдЧрд▓реЗ рдХрд╛рд░реНрдп рдХреЗ рдвреЗрд░ рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЗрд╕рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдмрд╛рдзрд╛ рд╕реЗ рд╡рд╛рдкрд╕реА рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдордиреЗ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╕реНрдЯреИрдХ рдлреНрд░реЗрдо рдХрд╛ рдЧрдарди рдХрд┐рдпрд╛ рд╣реИред
рдЗрд╕ рддрдереНрдп рдХреЗ рд▓рд┐рдП рдХрд┐ рдмрд╛рдж рдореЗрдВ рд╣рдореЗрдВ рд╡рд┐рд╢реЗрд╖рд╛рдзрд┐рдХрд╛рд░ рд╕реНрддрд░реЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред
/* * Switch context (to kernel ring) * void asm_switch_kcontext(u32 esp, u32 cr3) */ asm_switch_kcontext: mov 4(%esp),%ebp # ebp = esp mov 8(%esp),%eax # eax = cr3 mov %cr0,%ebx # ebx = cr0 and $0x7FFFFFFF,%ebx # unset PG bit mov %ebx,%cr0 mov %eax,%cr3 or $0x80000001,%ebx # set PE & PG bits mov %ebx,%cr0 mov %ebp,%esp popal sti iretl
рд╣рдо рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рдмреАрдЪ рд╕рдмрд╕реЗ рд╕рд░рд▓ рд╕рдВрджреЗрд╢ рддрдВрддреНрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред
рдЬрдм рд╣рдо рдХрд┐рд╕реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕рдВрджреЗрд╢ рднреЗрдЬрддреЗ рд╣реИрдВ, рддреЛ рдЙрд╕реЗ рдЬрдореЗ рд╣реБрдП рд╣реЛрдиреЗ рдкрд░ рдЙрд╕реЗ рдкрд┐рдШрд▓рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕рдВрджреЗрд╢реЛрдВ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣рд╛ рд╣реИред
рд▓реЗрдХрд┐рди рдЬрдм рд╣рдореЗрдВ рдХреЛрдИ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдЦрд╛рд▓реА рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рд╕рдВрджреЗрд╢ рдХрддрд╛рд░ рдЦрд╛рд▓реА рд╣реИред
рдЙрд╕рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рд╢реЗрдбреНрдпреВрд▓рд░ рдкрд░ рдирд┐рдпрдВрддреНрд░рдг рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
extern void ksend(u_short tid, struct message_t* msg) { struct task_t* task; task = task_get_by_id(tid); task_pack_message(task, msg); if (task->status == TASK_INTERRUPTABLE) { task->status = TASK_RUNNING; } } extern void kreceive(u_short tid, struct message_t* msg) { struct task_t* task_before; struct task_t* task_after; task_before = sched_get_current_task(); assert(tid == task_before->tid); assert(task_before->status == TASK_RUNNING); if (task_before->msg_count_in == 0) { task_before->status = TASK_INTERRUPTABLE; } sched_yield(); task_after = sched_get_current_task(); assert(task_after == task_before); assert(tid == task_after->tid); assert(task_after->status == TASK_RUNNING); task_extract_message(task_after, msg); assert(msg != null); }
рдЕрдм рдЖрдкрдХреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реЗ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рд╡рд╣рд╛рдВ рд╣рдо рд╕рдВрджреЗрд╢ рднреЗрдЬрдиреЗ рдФрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдлреЗрдВрдХреЗрдВрдЧреЗред
extern size_t ih_syscall(u_int* function) { size_t params_addr = ((size_t)function + sizeof(u_int)); size_t result = 0; struct task_t *current = sched_get_current_task(); printf(MSG_SYSCALL, *function, current->tid); asm_lock(); switch (*function) { case SYSCALL_KSEND: { u_short tid = *(u_int*)params_addr; ksend(tid, *(struct message_t**)(params_addr + 4)); break; } case SYSCALL_KRECEIVE: { u_short tid = *(u_int*)params_addr; kreceive(tid, *(struct message_t**)(params_addr + 4)); break; } case SYSCALL_KILL: { u_short tid = *(u_int*)params_addr; struct task_t* task = task_find_by_id(tid); if (task != null) { assert(task->tid == tid); task->status = TASK_KILLING; task->reschedule = true; result = true; } else { result = false; } break; } case SYSCALL_EXIT: { int errno = *(int*)params_addr; u_int tid = current->tid; printf(MSG_TASK_FINISHED, tid, errno); current->status = TASK_KILLING; sched_yield(); break; } case SYSCALL_TASK_LIST: { result = (size_t)task_get_task_list(); break; } default: unreachable(); } printf(MSG_SYSCALL_RET, *function); asm_unlock(); return result; }
рд╣рдорд╛рд░реЗ рд╕реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рдХрд░реНрдиреЗрд▓ рд╡реНрдпрд╡рдзрд╛рди рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рд╣рдо рд╡рд┐рд╢реЗрд╖ рдЗрдВрдЯреЗрд▓ рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╡рд┐рд╢реЗрд╖рд╛рдзрд┐рдХрд╛рд░ рдХреЗ рд╕реНрддрд░ рдирд╣реАрдВ рд╣реИрдВред рдПрдХ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рд╕рд┐рд╕реНрдЯрдо рдлрд╝рдВрдХреНрд╢рди рдХреА рд╕рдВрдЦреНрдпрд╛ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рддрд░реНрдХ рдкрд╛рд╕ рдХрд░реЗрдВрдЧреЗред
/* * Call kernel * void asm_syscall(unsigned int function, ...) */ asm_syscall: push %ebx push %ebp mov %esp,%ebp mov %ebp,%ebx add $8,%ebx # skip registers add $4,%ebx # skip return address push %ebx # &function int $0x80 mov %ebp,%esp pop %ebp pop %ebx ret
рдпрд╣ рд╕реБрд░рдХреНрд╖рд╛ рдХреЗ рдЫрд▓реНрд▓реЗ рдХреЗ рд╕рдорд░реНрдерди рдХреЗ рдмрд┐рдирд╛ рд╕рдмрд╕реЗ рд╕рд░рд▓ рдорд▓реНрдЯреАрдЯрд╛рд╕реНрдХрд┐рдВрдЧ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред рдЕрдм
рд╡реАрдбрд┐рдпреЛ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдЦреЛрд▓реЗрдВ рдФрд░ рдХреНрд░рдо рдореЗрдВ рд╕рдм рдХреБрдЫ рджреЗрдЦреЗрдВ!
рд╕рдВрджрд░реНрдн
рд╡реАрдбрд┐рдпреЛ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдореЗрдВ рд╡рд┐рд╡рд░рдг рдФрд░ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдгред
рдЧрд┐рдЯ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб (рдЖрдкрдХреЛ рд╕рдмрдХ 7 рд╢рд╛рдЦрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ)ред
рд╕рдВрджрд░реНрдн
1. рдЬреЗрдореНрд╕ рдореЛрд▓реЙрдпред рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдЦрд┐рд▓реМрдирд╛ рдпреВрдирд┐рдХреНрд╕-рдХреНрд▓реЛрди рдУрдПрд╕ рд░реЛрд▓ рдХрд░реЗрдВред
2. рджрд╛рдБрддред рдбреЙрд╕, рд╡рд┐рдВрдбреЛрдЬ, рдпреВрдирд┐рдХреНрд╕ рдХреЗ рд▓рд┐рдП рдЕрд╕реЗрдВрдмрд▓рд░
3. рдХрд▓рд╛рд╢реНрдирд┐рдХреЛрд╡ред рдЕрд╕реЗрдВрдмрд▓рд░ рдЖрд╕рд╛рди рд╣реИ!
4. рддрд╛рдирдирдмрд╛рдоред рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдоред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдФрд░ рд╡рд┐рдХрд╛рд╕ред
5. рд░реЙрдмрд░реНрдЯ рд▓рд╡ред рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рд╡рд┐рдХрд╛рд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рд╡рд┐рд╡рд░рдгред