📄 kern_synch.c
字号:
p->p_flag |= P_SINTR; if (sig = CURSIG(p)) { if (p->p_wchan) unsleep(p); p->p_stat = SRUN; goto resume; } if (p->p_wchan == 0) { catch = 0; goto resume; } } else sig = 0; p->p_stat = SSLEEP; p->p_stats->p_ru.ru_nvcsw++; mi_switch();resume: curpriority = p->p_usrpri; splx(s); p->p_flag &= ~P_SINTR; if (p->p_flag & P_TIMEOUT) { p->p_flag &= ~P_TIMEOUT; if (sig == 0) {#ifdef KTRACE if (KTRPOINT(p, KTR_CSW)) ktrcsw(p->p_tracep, 0, 0);#endif return (EWOULDBLOCK); } } else if (timo) untimeout(endtsleep, (void *)p); if (catch && (sig != 0 || (sig = CURSIG(p)))) {#ifdef KTRACE if (KTRPOINT(p, KTR_CSW)) ktrcsw(p->p_tracep, 0, 0);#endif if (p->p_sigacts->ps_sigintr & sigmask(sig)) return (EINTR); return (ERESTART); }#ifdef KTRACE if (KTRPOINT(p, KTR_CSW)) ktrcsw(p->p_tracep, 0, 0);#endif return (0);}/* * Implement timeout for tsleep. * If process hasn't been awakened (wchan non-zero), * set timeout flag and undo the sleep. If proc * is stopped, just unsleep so it will remain stopped. */voidendtsleep(arg) void *arg;{ register struct proc *p; int s; p = (struct proc *)arg; s = splhigh(); if (p->p_wchan) { if (p->p_stat == SSLEEP) setrunnable(p); else unsleep(p); p->p_flag |= P_TIMEOUT; } splx(s);}/* * Short-term, non-interruptable sleep. */voidsleep(ident, priority) void *ident; int priority;{ register struct proc *p = curproc; register struct slpque *qp; register s; extern int cold;#ifdef DIAGNOSTIC if (priority > PZERO) { printf("sleep called with priority %d > PZERO, wchan: %x\n", priority, ident); panic("old sleep"); }#endif s = splhigh(); if (cold || panicstr) { /* * After a panic, or during autoconfiguration, * just give interrupts a chance, then just return; * don't run any other procs or panic below, * in case this is the idle process and already asleep. */ splx(safepri); splx(s); return; }#ifdef DIAGNOSTIC if (ident == NULL || p->p_stat != SRUN || p->p_back) panic("sleep");#endif p->p_wchan = ident; p->p_wmesg = NULL; p->p_slptime = 0; p->p_priority = priority; qp = &slpque[LOOKUP(ident)]; if (qp->sq_head == 0) qp->sq_head = p; else *qp->sq_tailp = p; *(qp->sq_tailp = &p->p_forw) = 0; p->p_stat = SSLEEP; p->p_stats->p_ru.ru_nvcsw++;#ifdef KTRACE if (KTRPOINT(p, KTR_CSW)) ktrcsw(p->p_tracep, 1, 0);#endif mi_switch();#ifdef KTRACE if (KTRPOINT(p, KTR_CSW)) ktrcsw(p->p_tracep, 0, 0);#endif curpriority = p->p_usrpri; splx(s);}/* * Remove a process from its wait queue */voidunsleep(p) register struct proc *p;{ register struct slpque *qp; register struct proc **hp; int s; s = splhigh(); if (p->p_wchan) { hp = &(qp = &slpque[LOOKUP(p->p_wchan)])->sq_head; while (*hp != p) hp = &(*hp)->p_forw; *hp = p->p_forw; if (qp->sq_tailp == &p->p_forw) qp->sq_tailp = hp; p->p_wchan = 0; } splx(s);}/* * Make all processes sleeping on the specified identifier runnable. */voidwakeup(ident) register void *ident;{ register struct slpque *qp; register struct proc *p, **q; int s; s = splhigh(); qp = &slpque[LOOKUP(ident)];restart: for (q = &qp->sq_head; p = *q; ) {#ifdef DIAGNOSTIC if (p->p_back || p->p_stat != SSLEEP && p->p_stat != SSTOP) panic("wakeup");#endif if (p->p_wchan == ident) { p->p_wchan = 0; *q = p->p_forw; if (qp->sq_tailp == &p->p_forw) qp->sq_tailp = q; if (p->p_stat == SSLEEP) { /* OPTIMIZED EXPANSION OF setrunnable(p); */ if (p->p_slptime > 1) updatepri(p); p->p_slptime = 0; p->p_stat = SRUN; if (p->p_flag & P_INMEM) setrunqueue(p); /* * Since curpriority is a user priority, * p->p_priority is always better than * curpriority. */ if ((p->p_flag & P_INMEM) == 0) wakeup((caddr_t)&proc0); else need_resched(); /* END INLINE EXPANSION */ goto restart; } } else q = &p->p_forw; } splx(s);}/* * The machine independent parts of mi_switch(). * Must be called at splstatclock() or higher. */voidmi_switch(){ register struct proc *p = curproc; /* XXX */ register struct rlimit *rlim; register long s, u; struct timeval tv; /* * Compute the amount of time during which the current * process was running, and add that to its total so far. */ microtime(&tv); u = p->p_rtime.tv_usec + (tv.tv_usec - runtime.tv_usec); s = p->p_rtime.tv_sec + (tv.tv_sec - runtime.tv_sec); if (u < 0) { u += 1000000; s--; } else if (u >= 1000000) { u -= 1000000; s++; } p->p_rtime.tv_usec = u; p->p_rtime.tv_sec = s; /* * Check if the process exceeds its cpu resource allocation. * If over max, kill it. In any case, if it has run for more * than 10 minutes, reduce priority to give others a chance. */ rlim = &p->p_rlimit[RLIMIT_CPU]; if (s >= rlim->rlim_cur) { if (s >= rlim->rlim_max) psignal(p, SIGKILL); else { psignal(p, SIGXCPU); if (rlim->rlim_cur < rlim->rlim_max) rlim->rlim_cur += 5; } } if (s > 10 * 60 && p->p_ucred->cr_uid && p->p_nice == NZERO) { p->p_nice = NZERO + 4; resetpriority(p); } /* * Pick a new current process and record its start time. */ cnt.v_swtch++; cpu_switch(p); microtime(&runtime);}/* * Initialize the (doubly-linked) run queues * to be empty. */rqinit(){ register int i; for (i = 0; i < NQS; i++) qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i];}/* * Change process state to be runnable, * placing it on the run queue if it is in memory, * and awakening the swapper if it isn't in memory. */voidsetrunnable(p) register struct proc *p;{ register int s; s = splhigh(); switch (p->p_stat) { case 0: case SRUN: case SZOMB: default: panic("setrunnable"); case SSTOP: case SSLEEP: unsleep(p); /* e.g. when sending signals */ break; case SIDL: break; } p->p_stat = SRUN; if (p->p_flag & P_INMEM) setrunqueue(p); splx(s); if (p->p_slptime > 1) updatepri(p); p->p_slptime = 0; if ((p->p_flag & P_INMEM) == 0) wakeup((caddr_t)&proc0); else if (p->p_priority < curpriority) need_resched();}/* * Compute the priority of a process when running in user mode. * Arrange to reschedule if the resulting priority is better * than that of the current process. */voidresetpriority(p) register struct proc *p;{ register unsigned int newpriority; newpriority = PUSER + p->p_estcpu / 4 + 2 * p->p_nice; newpriority = min(newpriority, MAXPRI); p->p_usrpri = newpriority; if (newpriority < curpriority) need_resched();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -