X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/1c79356b52d46aa6b508fb032f5ae709b1f2897b..5eebf7385fedb1517b66b53c28e5aa6bb0a2be50:/bsd/kern/kern_synch.c diff --git a/bsd/kern/kern_synch.c b/bsd/kern/kern_synch.c index ef076878d..97b35818c 100644 --- a/bsd/kern/kern_synch.c +++ b/bsd/kern/kern_synch.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -48,24 +49,25 @@ #include #include -_sleep_continue() +#if KTRACE +#include +#include +#endif + +static void +_sleep_continue(void) { register struct proc *p; - register thread_t thread = current_thread(); - thread_act_t th_act; + register thread_t self = current_act(); struct uthread * ut; int sig, catch; int error = 0; - th_act = current_act(); - ut = get_bsdthread_info(th_act); + ut = get_bsdthread_info(self); catch = ut->uu_pri & PCATCH; p = current_proc(); -#if FIXME /* [ */ - thread->wait_mesg = NULL; -#endif /* FIXME ] */ - switch (get_thread_waitresult(thread)) { + switch (get_thread_waitresult(self)) { case THREAD_TIMED_OUT: error = EWOULDBLOCK; break; @@ -80,8 +82,7 @@ _sleep_continue() /* else fall through */ case THREAD_INTERRUPTED: if (catch) { - unix_master(); - if (thread_should_abort(current_thread())) { + if (thread_should_abort(self)) { error = EINTR; } else if (SHOULDissignal(p,ut)) { if (sig = CURSIG(p)) { @@ -90,31 +91,26 @@ _sleep_continue() else error = ERESTART; } - if (thread_should_abort(current_thread())) { + if (thread_should_abort(self)) { error = EINTR; } } - unix_release(); } else error = EINTR; break; } - if ((error == EINTR) || (error == ERESTART)) { -#ifdef BSD_USE_APC - thread_apc_set(th_act, bsd_ast); -#else - thread_ast_set(th_act, AST_BSD); - ast_on(AST_BSD); -#endif - } + if (error == EINTR || error == ERESTART) + act_set_astbsd(self); + if (ut->uu_timo) thread_cancel_timer(); -#if 0 - /* We should never get here without funnel, so we should not grab again */ - thread_funnel_set(kernel_flock, TRUE); -#endif /* 0 */ +#if KTRACE + if (KTRPOINT(p, KTR_CSW)) + ktrcsw(p->p_tracep, 0, 0, -1); +#endif + unix_syscall_return((*ut->uu_continuation)(error)); } @@ -132,43 +128,41 @@ _sleep_continue() * sleeping has gone away. */ -#if FIXME -static __inline__ -#endif -int -_sleep(chan, pri, wmsg, timo, continuation) - caddr_t chan; - int pri; - char *wmsg; - int timo; - int (*continuation)(); +static int +_sleep( + caddr_t chan, + int pri, + char *wmsg, + u_int64_t abstime, + int (*continuation)(int)) { register struct proc *p; - register thread_t thread = current_thread(); - thread_act_t th_act; + register thread_t self = current_act(); struct uthread * ut; int sig, catch = pri & PCATCH; int sigttblock = pri & PTTYBLOCK; + int wait_result; int error = 0; spl_t s; s = splhigh(); - th_act = current_act(); - ut = get_bsdthread_info(th_act); + ut = get_bsdthread_info(self); p = current_proc(); #if KTRACE if (KTRPOINT(p, KTR_CSW)) - ktrcsw(p->p_tracep, 1, 0); + ktrcsw(p->p_tracep, 1, 0, -1); #endif p->p_priority = pri & PRIMASK; - if (chan) - assert_wait(chan, (catch) ? THREAD_ABORTSAFE : THREAD_UNINT); - - if (timo) - thread_set_timer(timo, NSEC_PER_SEC / hz); + if (chan != NULL) + assert_wait_prim(chan, NULL, abstime, + (catch) ? THREAD_ABORTSAFE : THREAD_UNINT); + else + if (abstime != 0) + thread_set_timer_deadline(abstime); + /* * We start our timeout * before calling CURSIG, as we could stop there, and a wakeup @@ -179,19 +173,19 @@ _sleep(chan, pri, wmsg, timo, continuation) * stopped, p->p_wchan will be 0 upon return from CURSIG. */ if (catch) { - unix_master(); if (SHOULDissignal(p,ut)) { if (sig = CURSIG(p)) { - clear_wait(thread, THREAD_INTERRUPTED); + if (clear_wait(self, THREAD_INTERRUPTED) == KERN_FAILURE) + goto block; /* if SIGTTOU or SIGTTIN then block till SIGCONT */ if (sigttblock && ((sig == SIGTTOU) || (sig == SIGTTIN))) { p->p_flag |= P_TTYSLEEP; /* reset signal bits */ - clear_sigbits(p, sig); + clear_procsiglist(p, sig); assert_wait(&p->p_siglist, THREAD_ABORTSAFE); /* assert wait can block and SIGCONT should be checked */ if (p->p_flag & P_TTYSLEEP) - thread_block(0); + thread_block(THREAD_CONTINUE_NULL); /* return with success */ error = 0; goto out; @@ -200,43 +194,37 @@ _sleep(chan, pri, wmsg, timo, continuation) error = EINTR; else error = ERESTART; - unix_release(); goto out; } } - if (thread_should_abort(current_thread())) { - clear_wait(thread, THREAD_INTERRUPTED); + if (thread_should_abort(self)) { + if (clear_wait(self, THREAD_INTERRUPTED) == KERN_FAILURE) + goto block; error = EINTR; - unix_release(); goto out; } - if (get_thread_waitevent(thread) == 0) { /*already happened */ - unix_release(); + if (get_thread_waitresult(self) != THREAD_WAITING) { + /*already happened */ goto out; } - unix_release(); } -#if FIXME /* [ */ - thread->wait_mesg = wmsg; -#endif /* FIXME ] */ +block: + splx(s); p->p_stats->p_ru.ru_nvcsw++; - if (continuation != (int (*)()) 0 ) { + if ((thread_continue_t)continuation != THREAD_CONTINUE_NULL ) { ut->uu_continuation = continuation; ut->uu_pri = pri; - ut->uu_timo = timo; - thread_block(_sleep_continue); + ut->uu_timo = abstime? 1: 0; + (void) thread_block(_sleep_continue); /* NOTREACHED */ } - thread_block(0); + wait_result = thread_block(THREAD_CONTINUE_NULL); -#if FIXME /* [ */ - thread->wait_mesg = NULL; -#endif /* FIXME ] */ - switch (get_thread_waitresult(thread)) { + switch (wait_result) { case THREAD_TIMED_OUT: error = EWOULDBLOCK; break; @@ -251,8 +239,7 @@ _sleep(chan, pri, wmsg, timo, continuation) /* else fall through */ case THREAD_INTERRUPTED: if (catch) { - unix_master(); - if (thread_should_abort(current_thread())) { + if (thread_should_abort(self)) { error = EINTR; } else if (SHOULDissignal(p,ut)) { if (sig = CURSIG(p)) { @@ -261,60 +248,73 @@ _sleep(chan, pri, wmsg, timo, continuation) else error = ERESTART; } - if (thread_should_abort(current_thread())) { + if (thread_should_abort(self)) { error = EINTR; } } - unix_release(); } else error = EINTR; break; } out: - if ((error == EINTR) || (error == ERESTART)) { -#ifdef BSD_USE_APC - thread_apc_set(th_act, bsd_ast); -#else - thread_ast_set(th_act, AST_BSD); - ast_on(AST_BSD); -#endif - } - if (timo) + if (error == EINTR || error == ERESTART) + act_set_astbsd(self); + if (abstime) thread_cancel_timer(); (void) splx(s); +#if KTRACE + if (KTRPOINT(p, KTR_CSW)) + ktrcsw(p->p_tracep, 0, 0, -1); +#endif return (error); } -int sleep(chan, pri) - void *chan; - int pri; +int +sleep( + void *chan, + int pri) { + return _sleep((caddr_t)chan, pri, (char *)NULL, 0, (int (*)(int))0); +} - return (_sleep((caddr_t)chan, pri, (char *)NULL, 0, (void (*)())0 )); - +int +tsleep( + void *chan, + int pri, + char *wmsg, + int timo) +{ + u_int64_t abstime = 0; + + if (timo) + clock_interval_to_deadline(timo, NSEC_PER_SEC / hz, &abstime); + return _sleep((caddr_t)chan, pri, wmsg, abstime, (int (*)(int))0); } -int tsleep(chan, pri, wmsg, timo) - void *chan; - int pri; - char * wmsg; - int timo; +int +tsleep0( + void *chan, + int pri, + char *wmsg, + int timo, + int (*continuation)(int)) { - return(_sleep((caddr_t)chan, pri, wmsg, timo, (void (*)())0 )); + u_int64_t abstime = 0; + + if (timo) + clock_interval_to_deadline(timo, NSEC_PER_SEC / hz, &abstime); + return _sleep((caddr_t)chan, pri, wmsg, abstime, continuation); } -int tsleep0(chan, pri, wmsg, timo, continuation) - void *chan; - int pri; - char * wmsg; - int timo; - int (*continuation)(); +int +tsleep1( + void *chan, + int pri, + char *wmsg, + u_int64_t abstime, + int (*continuation)(int)) { -#if defined (__i386__) - return(_sleep((caddr_t)chan, pri, wmsg, timo, (void (*)())0 )); -#else - return(_sleep((caddr_t)chan, pri, wmsg, timo, continuation)); -#endif + return _sleep((caddr_t)chan, pri, wmsg, abstime, continuation); } /* @@ -324,7 +324,7 @@ void wakeup(chan) register void *chan; { - thread_wakeup_prim((caddr_t)chan,FALSE, THREAD_AWAKENED); + thread_wakeup_prim((caddr_t)chan, FALSE, THREAD_AWAKENED); } /* @@ -333,6 +333,7 @@ wakeup(chan) * Be very sure that the first process is really * the right one to wakeup. */ +void wakeup_one(chan) register caddr_t chan; { @@ -348,16 +349,29 @@ void resetpriority(p) register struct proc *p; { - int newpri; -#if FIXME - if (p->p_nice < 0) - newpri = BASEPRI_USER + - (p->p_nice * (MAXPRI_USER - BASEPRI_USER)) / PRIO_MIN; - else - newpri = BASEPRI_USER - - (p->p_nice * BASEPRI_USER) / PRIO_MAX; - - (void)task_priority(p->task, newpri, TRUE); -#endif /* FIXME */ + (void)task_importance(p->task, -p->p_nice); } +struct loadavg averunnable = + { {0, 0, 0}, FSCALE }; /* load average, of runnable procs */ +/* + * Constants for averages over 1, 5, and 15 minutes + * when sampling at 5 second intervals. + */ +static fixpt_t cexp[3] = { + (fixpt_t)(0.9200444146293232 * FSCALE), /* exp(-1/12) */ + (fixpt_t)(0.9834714538216174 * FSCALE), /* exp(-1/60) */ + (fixpt_t)(0.9944598480048967 * FSCALE), /* exp(-1/180) */ +}; + +void +compute_averunnable( + register int nrun) +{ + register int i; + struct loadavg *avg = &averunnable; + + for (i = 0; i < 3; i++) + avg->ldavg[i] = (cexp[i] * avg->ldavg[i] + + nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT; +}