X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/14b86eca7f36eedde35cb47b41afc36f9097ea7c..8fdcd1575a97862975fa019f09c00453a2a7d8bb:/lunaix-os/kernel/sched.c diff --git a/lunaix-os/kernel/sched.c b/lunaix-os/kernel/sched.c index 8f65087..1a9743d 100644 --- a/lunaix-os/kernel/sched.c +++ b/lunaix-os/kernel/sched.c @@ -1,12 +1,15 @@ #include #include + #include #include + #include +#include #include #include #include - +#include #include #include #include @@ -18,8 +21,6 @@ volatile struct proc_info* __current; struct proc_info dummy; -extern void __proc_table; - struct scheduler sched_ctx; LOG_MODULE("SCHED") @@ -28,11 +29,14 @@ void sched_init() { size_t pg_size = ROUNDUP(sizeof(struct proc_info) * MAX_PROCESS, 0x1000); - assert_msg(vmm_alloc_pages( - KERNEL_PID, &__proc_table, pg_size, PG_PREM_RW, PP_FGPERSIST), - "Fail to allocate proc table"); - sched_ctx = (struct scheduler){ ._procs = (struct proc_info*)&__proc_table, + for (size_t i = 0; i <= pg_size; i += 4096) { + uintptr_t pa = pmm_alloc_page(KERNEL_PID, PP_FGPERSIST); + vmm_set_mapping( + PD_REFERENCED, PROC_START + i, pa, PG_PREM_RW, VMAP_NULL); + } + + sched_ctx = (struct scheduler){ ._procs = (struct proc_info*)PROC_START, .ptable_len = 0, .procs_index = 0 }; } @@ -45,22 +49,13 @@ run(struct proc_info* proc) } proc->state = PROC_RUNNING; - // FIXME: 这里还是得再考虑一下。 + // XXX: 我们需要这一步吗? // tss_update_esp(__current->intr_ctx.esp); - if (__current->page_table != proc->page_table) { - __current = proc; - cpu_lcr3(__current->page_table); - // from now on, the we are in the kstack of another process - } else { - __current = proc; - } - apic_done_servicing(); asm volatile("pushl %0\n" - "jmp soft_iret\n" ::"r"(&__current->intr_ctx) - : "memory"); + "jmp switch_to\n" ::"r"(proc)); // kernel/asm/x86/interrupt.S } void @@ -70,6 +65,8 @@ schedule() return; } + // 上下文切换相当的敏感!我们不希望任何的中断打乱栈的顺序…… + cpu_disable_interrupt(); struct proc_info* next; int prev_ptr = sched_ctx.procs_index; int ptr = prev_ptr; @@ -97,6 +94,7 @@ __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds) if (!seconds) { return 0; } + if (__current->timer) { return __current->timer->counter / timer_context()->running_frequency; } @@ -119,31 +117,60 @@ __DEFINE_LXSYSCALL(void, yield) schedule(); } +pid_t +_wait(pid_t wpid, int* status, int options); + __DEFINE_LXSYSCALL1(pid_t, wait, int*, status) +{ + return _wait(-1, status, 0); +} + +__DEFINE_LXSYSCALL3(pid_t, waitpid, pid_t, pid, int*, status, int, options) +{ + return _wait(pid, status, options); +} + +pid_t +_wait(pid_t wpid, int* status, int options) { pid_t cur = __current->pid; + int status_flags = 0; struct proc_info *proc, *n; if (llist_empty(&__current->children)) { return -1; } + + wpid = wpid ? wpid : -__current->pgid; + cpu_enable_interrupt(); repeat: llist_for_each(proc, n, &__current->children, siblings) { - if (proc->state == PROC_TERMNAT) { - goto done; + if (!~wpid || proc->pid == wpid || proc->pgid == -wpid) { + if (proc->state == PROC_TERMNAT && !options) { + status_flags |= PROCTERM; + goto done; + } + if (proc->state == PROC_STOPPED && (options & WUNTRACED)) { + status_flags |= PROCSTOP; + goto done; + } } } - // FIXME: 除了循环,也许有更高效的办法…… - // (在这里进行schedule,需要重写context switch!) + if ((options & WNOHANG)) { + return 0; + } + // 放弃当前的运行机会 + sched_yield(); goto repeat; done: - *status = proc->exit_code; + cpu_disable_interrupt(); + *status = (proc->exit_code & 0xffff) | status_flags; return destroy_process(proc->pid); } -pid_t -alloc_pid() +struct proc_info* +alloc_process() { pid_t i = 0; for (; @@ -154,28 +181,36 @@ alloc_pid() if (i == MAX_PROCESS) { panick("Panic in Ponyville shimmer!"); } - return i; + + if (i == sched_ctx.ptable_len) { + sched_ctx.ptable_len++; + } + + struct proc_info* proc = &sched_ctx._procs[i]; + memset(proc, 0, sizeof(*proc)); + + proc->state = PROC_CREATED; + proc->pid = i; + proc->created = clock_systime(); + proc->pgid = proc->pid; + + llist_init_head(&proc->mm.regions); + llist_init_head(&proc->children); + llist_init_head(&proc->grp_member); + + return proc; } void -push_process(struct proc_info* process) +commit_process(struct proc_info* process) { - int index = process->pid; - if (index < 0 || index > sched_ctx.ptable_len) { - __current->k_status = LXINVLDPID; - return; - } + assert(process == &sched_ctx._procs[process->pid]); - if (index == sched_ctx.ptable_len) { - sched_ctx.ptable_len++; + if (process->state != PROC_CREATED) { + __current->k_status = LXINVL; + return; } - sched_ctx._procs[index] = *process; - - process = &sched_ctx._procs[index]; - - // make sure the address is in the range of process table - llist_init_head(&process->children); // every process is the child of first process (pid=1) if (process->parent) { llist_append(&process->parent->children, &process->siblings); @@ -202,19 +237,17 @@ destroy_process(pid_t pid) proc->state = PROC_DESTROY; llist_delete(&proc->siblings); - if (proc->mm.regions) { - struct mm_region *pos, *n; - llist_for_each(pos, n, &proc->mm.regions->head, head) - { - lxfree(pos); - } + struct mm_region *pos, *n; + llist_for_each(pos, n, &proc->mm.regions.head, head) + { + lxfree(pos); } - vmm_mount_pd(PD_MOUNT_2, proc->page_table); + vmm_mount_pd(PD_MOUNT_1, proc->page_table); - __del_pagetable(pid, PD_MOUNT_2); + __del_pagetable(pid, PD_MOUNT_1); - vmm_unmount_pd(PD_MOUNT_2); + vmm_unmount_pd(PD_MOUNT_1); return pid; }