X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/474a5dd282586c31abfefc7953f148acdc226731..bc34fd00d2e81fbc890bb2060ed6693454a230bf:/lunaix-os/kernel/sched.c diff --git a/lunaix-os/kernel/sched.c b/lunaix-os/kernel/sched.c index 50f5f67..f8f00d4 100644 --- a/lunaix-os/kernel/sched.c +++ b/lunaix-os/kernel/sched.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -44,10 +45,7 @@ sched_init() void run(struct proc_info* proc) { - if (!(__current->state & ~PROC_RUNNING)) { - __current->state = PROC_STOPPED; - } - proc->state = PROC_RUNNING; + proc->state = PS_RUNNING; /* 将tss.esp0设置为上次调度前的esp值。 @@ -62,7 +60,53 @@ run(struct proc_info* proc) apic_done_servicing(); asm volatile("pushl %0\n" - "jmp switch_to\n" ::"r"(proc)); // kernel/asm/x86/interrupt.S + "jmp switch_to\n" ::"r"(proc) + : "memory"); // kernel/asm/x86/interrupt.S +} + +int +can_schedule(struct proc_info* proc) +{ + if (__SIGTEST(proc->sig_pending, _SIGCONT)) { + __SIGCLEAR(proc->sig_pending, _SIGSTOP); + } else if (__SIGTEST(proc->sig_pending, _SIGSTOP)) { + // 如果进程受到SIGSTOP,则该进程不给予调度。 + return 0; + } + + return 1; +} + +void +check_sleepers() +{ + struct proc_info* leader = &sched_ctx._procs[0]; + struct proc_info *pos, *n; + time_t now = clock_systime(); + llist_for_each(pos, n, &leader->sleep.sleepers, sleep.sleepers) + { + if (PROC_TERMINATED(pos->state)) { + goto del; + } + + time_t wtime = pos->sleep.wakeup_time; + time_t atime = pos->sleep.alarm_time; + + if (wtime && now >= wtime) { + pos->sleep.wakeup_time = 0; + pos->state = PS_STOPPED; + } + + if (atime && now >= atime) { + pos->sleep.alarm_time = 0; + __SIGSET(pos->sig_pending, _SIGALRM); + } + + if (!wtime && !atime) { + del: + llist_delete(&pos->sleep.sleepers); + } + } } void @@ -77,46 +121,74 @@ schedule() struct proc_info* next; int prev_ptr = sched_ctx.procs_index; int ptr = prev_ptr; + + if (!(__current->state & ~PS_RUNNING)) { + __current->state = PS_STOPPED; + } + + check_sleepers(); + // round-robin scheduler +redo: do { ptr = (ptr + 1) % sched_ctx.ptable_len; next = &sched_ctx._procs[ptr]; - } while (next->state != PROC_STOPPED && ptr != prev_ptr); + } while (next->state != PS_STOPPED && ptr != prev_ptr); sched_ctx.procs_index = ptr; + if (!can_schedule(next)) { + // 如果该进程不给予调度,则尝试重新选择 + goto redo; + } + run(next); } -static void -proc_timer_callback(struct proc_info* proc) +void +sched_yieldk() { - proc->timer = NULL; - proc->state = PROC_STOPPED; + cpu_int(LUNAIX_SCHED); } __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds) { - // FIXME: sleep的实现或许需要改一下。专门绑一个计时器好像没有必要…… if (!seconds) { return 0; } - if (__current->timer) { - return __current->timer->counter / timer_context()->running_frequency; + if (__current->sleep.wakeup_time) { + return (__current->sleep.wakeup_time - clock_systime()) / 1000U; } - struct lx_timer* timer = - timer_run_second(seconds, proc_timer_callback, __current, 0); - __current->timer = timer; + __current->sleep.wakeup_time = clock_systime() + seconds * 1000; + llist_append(&sched_ctx._procs[0].sleep.sleepers, + &__current->sleep.sleepers); + __current->intr_ctx.registers.eax = seconds; - __current->state = PROC_BLOCKED; + __current->state = PS_BLOCKED; schedule(); } +__DEFINE_LXSYSCALL1(unsigned int, alarm, unsigned int, seconds) +{ + time_t prev_ddl = __current->sleep.alarm_time; + time_t now = clock_systime(); + + __current->sleep.alarm_time = seconds ? now + seconds * 1000 : 0; + + if (llist_empty(&__current->sleep.sleepers)) { + llist_append(&sched_ctx._procs[0].sleep.sleepers, + &__current->sleep.sleepers); + } + + return prev_ddl ? (prev_ddl - now) / 1000 : 0; +} + __DEFINE_LXSYSCALL1(void, exit, int, status) { terminate_proc(status); + schedule(); } __DEFINE_LXSYSCALL(void, yield) @@ -137,6 +209,11 @@ __DEFINE_LXSYSCALL3(pid_t, waitpid, pid_t, pid, int*, status, int, options) return _wait(pid, status, options); } +__DEFINE_LXSYSCALL(int, geterrno) +{ + return __current->k_status; +} + pid_t _wait(pid_t wpid, int* status, int options) { @@ -148,17 +225,16 @@ _wait(pid_t wpid, int* status, int options) } wpid = wpid ? wpid : -__current->pgid; - cpu_enable_interrupt(); repeat: llist_for_each(proc, n, &__current->children, siblings) { if (!~wpid || proc->pid == wpid || proc->pgid == -wpid) { - if (proc->state == PROC_TERMNAT && !options) { - status_flags |= PROCTERM; + if (proc->state == PS_TERMNAT && !options) { + status_flags |= PEXITTERM; goto done; } - if (proc->state == PROC_STOPPED && (options & WUNTRACED)) { - status_flags |= PROCSTOP; + if (proc->state == PS_STOPPED && (options & WUNTRACED)) { + status_flags |= PEXITSTOP; goto done; } } @@ -167,12 +243,14 @@ repeat: return 0; } // 放弃当前的运行机会 - sched_yield(); + sched_yieldk(); goto repeat; done: - cpu_disable_interrupt(); - *status = (proc->exit_code & 0xffff) | status_flags; + status_flags |= PEXITSIG * (proc->sig_inprogress != 0); + if (status) { + *status = proc->exit_code | status_flags; + } return destroy_process(proc->pid); } @@ -180,8 +258,7 @@ struct proc_info* alloc_process() { pid_t i = 0; - for (; - i < sched_ctx.ptable_len && sched_ctx._procs[i].state != PROC_DESTROY; + for (; i < sched_ctx.ptable_len && sched_ctx._procs[i].state != PS_DESTROY; i++) ; @@ -196,14 +273,16 @@ alloc_process() struct proc_info* proc = &sched_ctx._procs[i]; memset(proc, 0, sizeof(*proc)); - proc->state = PROC_CREATED; + proc->state = PS_CREATED; proc->pid = i; proc->created = clock_systime(); proc->pgid = proc->pid; + proc->fdtable = vzalloc(sizeof(struct v_fdtable)); - llist_init_head(&proc->mm.regions); + llist_init_head(&proc->mm.regions.head); llist_init_head(&proc->children); llist_init_head(&proc->grp_member); + llist_init_head(&proc->sleep.sleepers); return proc; } @@ -213,19 +292,19 @@ commit_process(struct proc_info* process) { assert(process == &sched_ctx._procs[process->pid]); - if (process->state != PROC_CREATED) { - __current->k_status = LXINVL; + if (process->state != PS_CREATED) { + __current->k_status = EINVAL; return; } // every process is the child of first process (pid=1) - if (process->parent) { - llist_append(&process->parent->children, &process->siblings); - } else { - process->parent = &sched_ctx._procs[0]; + if (!process->parent) { + process->parent = &sched_ctx._procs[1]; } - process->state = PROC_STOPPED; + llist_append(&process->parent->children, &process->siblings); + + process->state = PS_STOPPED; } // from @@ -237,17 +316,25 @@ destroy_process(pid_t pid) { int index = pid; if (index <= 0 || index > sched_ctx.ptable_len) { - __current->k_status = LXINVLDPID; + __current->k_status = EINVAL; return; } struct proc_info* proc = &sched_ctx._procs[index]; - proc->state = PROC_DESTROY; + proc->state = PS_DESTROY; llist_delete(&proc->siblings); + for (size_t i = 0; i < VFS_MAX_FD; i++) { + struct v_fd* fd = proc->fdtable->fds[i]; + if (fd) + vfs_close(fd->file); + } + + vfree(proc->fdtable); + struct mm_region *pos, *n; llist_for_each(pos, n, &proc->mm.regions.head, head) { - lxfree(pos); + vfree(pos); } vmm_mount_pd(PD_MOUNT_1, proc->page_table); @@ -262,12 +349,10 @@ destroy_process(pid_t pid) void terminate_proc(int exit_code) { - __current->state = PROC_TERMNAT; + __current->state = PS_TERMNAT; __current->exit_code = exit_code; - __SET_SIGNAL(__current->parent->sig_pending, _SIGCHLD); - - schedule(); + __SIGSET(__current->parent->sig_pending, _SIGCHLD); } struct proc_info* @@ -292,5 +377,5 @@ orphaned_proc(pid_t pid) // 如果其父进程的状态是terminated 或 destroy中的一种 // 或者其父进程是在该进程之后创建的,那么该进程为孤儿进程 - return (parent->state & PROC_TERMMASK) || parent->created > proc->created; + return PROC_TERMINATED(parent->state) || parent->created > proc->created; } \ No newline at end of file