The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/kern/kern_synch.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /* 
   26  * Mach Operating System
   27  * Copyright (c) 1987 Carnegie-Mellon University
   28  * All rights reserved.  The CMU software License Agreement specifies
   29  * the terms and conditions for use and redistribution.
   30  */
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/proc.h>
   35 #include <sys/user.h>
   36 #include <sys/file.h>
   37 #include <sys/vnode.h>
   38 #include <sys/kernel.h>
   39 #include <sys/buf.h>
   40 
   41 #include <machine/spl.h>
   42 
   43 #include <kern/queue.h>
   44 #include <sys/lock.h>
   45 #include <kern/thread.h>
   46 #include <kern/sched_prim.h>
   47 #include <kern/ast.h>
   48 
   49 #include <kern/cpu_number.h>
   50 #include <vm/vm_kern.h>
   51 
   52 #include <kern/task.h>
   53 #include <mach/time_value.h>
   54 
   55 #if KTRACE
   56 #include <sys/uio.h>
   57 #include <sys/ktrace.h>
   58 #endif 
   59 
   60 static void
   61 _sleep_continue(void)
   62 {
   63         register struct proc *p;
   64         register thread_t self = current_act();
   65         struct uthread * ut;
   66         int sig, catch;
   67         int error = 0;
   68 
   69         ut = get_bsdthread_info(self);
   70         catch = ut->uu_pri & PCATCH;
   71         p = current_proc();
   72 
   73         switch (get_thread_waitresult(self)) {
   74                 case THREAD_TIMED_OUT:
   75                         error = EWOULDBLOCK;
   76                         break;
   77                 case THREAD_AWAKENED:
   78                         /*
   79                          * Posix implies any signal should be delivered
   80                          * first, regardless of whether awakened due
   81                          * to receiving event.
   82                          */
   83                         if (!catch)
   84                                 break;
   85                         /* else fall through */
   86                 case THREAD_INTERRUPTED:
   87                         if (catch) {
   88                                 if (thread_should_abort(self)) {
   89                                         error = EINTR;
   90                                 } else if (SHOULDissignal(p,ut)) {
   91                                         if (sig = CURSIG(p)) {
   92                                                 if (p->p_sigacts->ps_sigintr & sigmask(sig))
   93                                                         error = EINTR;
   94                                                 else
   95                                                         error = ERESTART;
   96                                         }
   97                                         if (thread_should_abort(self)) {
   98                                                 error = EINTR;
   99                                         }
  100                                 }
  101                         }  else
  102                                 error = EINTR;
  103                         break;
  104         }
  105 
  106         if (error == EINTR || error == ERESTART)
  107                 act_set_astbsd(self);
  108 
  109         if (ut->uu_timo)
  110                 thread_cancel_timer();
  111 
  112 #if KTRACE
  113         if (KTRPOINT(p, KTR_CSW))
  114                 ktrcsw(p->p_tracep, 0, 0, -1);
  115 #endif
  116 
  117         unix_syscall_return((*ut->uu_continuation)(error));
  118 }
  119 
  120 /*
  121  * Give up the processor till a wakeup occurs
  122  * on chan, at which time the process
  123  * enters the scheduling queue at priority pri.
  124  * The most important effect of pri is that when
  125  * pri<=PZERO a signal cannot disturb the sleep;
  126  * if pri>PZERO signals will be processed.
  127  * If pri&PCATCH is set, signals will cause sleep
  128  * to return 1, rather than longjmp.
  129  * Callers of this routine must be prepared for
  130  * premature return, and check that the reason for
  131  * sleeping has gone away.
  132  */
  133 
  134 static int
  135 _sleep(
  136         caddr_t         chan,
  137         int                     pri,
  138         char            *wmsg,
  139         u_int64_t       abstime,
  140         int                     (*continuation)(int))
  141 {
  142         register struct proc *p;
  143         register thread_t self = current_act();
  144         struct uthread * ut;
  145         int sig, catch = pri & PCATCH;
  146         int sigttblock = pri & PTTYBLOCK;
  147         int wait_result;
  148         int error = 0;
  149         spl_t   s;
  150 
  151         s = splhigh();
  152 
  153         ut = get_bsdthread_info(self);
  154         
  155         p = current_proc();
  156 #if KTRACE
  157         if (KTRPOINT(p, KTR_CSW))
  158                 ktrcsw(p->p_tracep, 1, 0, -1);
  159 #endif  
  160         p->p_priority = pri & PRIMASK;
  161                 
  162         if (chan != NULL)
  163                 assert_wait_prim(chan, NULL, abstime,
  164                                                         (catch) ? THREAD_ABORTSAFE : THREAD_UNINT);
  165         else
  166         if (abstime != 0)
  167                 thread_set_timer_deadline(abstime);
  168 
  169         /*
  170          * We start our timeout
  171          * before calling CURSIG, as we could stop there, and a wakeup
  172          * or a SIGCONT (or both) could occur while we were stopped.
  173          * A SIGCONT would cause us to be marked as SSLEEP
  174          * without resuming us, thus we must be ready for sleep
  175          * when CURSIG is called.  If the wakeup happens while we're
  176          * stopped, p->p_wchan will be 0 upon return from CURSIG.
  177          */
  178         if (catch) {
  179                 if (SHOULDissignal(p,ut)) {
  180                         if (sig = CURSIG(p)) {
  181                                 if (clear_wait(self, THREAD_INTERRUPTED) == KERN_FAILURE)
  182                                         goto block;
  183                                 /* if SIGTTOU or SIGTTIN then block till SIGCONT */
  184                                 if (sigttblock && ((sig == SIGTTOU) || (sig == SIGTTIN))) {
  185                                         p->p_flag |= P_TTYSLEEP;
  186                                         /* reset signal bits */
  187                                         clear_procsiglist(p, sig);
  188                                         assert_wait(&p->p_siglist, THREAD_ABORTSAFE);
  189                                         /* assert wait can block and SIGCONT should be checked */
  190                                         if (p->p_flag & P_TTYSLEEP)
  191                                                 thread_block(THREAD_CONTINUE_NULL);
  192                                         /* return with success */
  193                                         error = 0;
  194                                         goto out;
  195                                 }
  196                                 if (p->p_sigacts->ps_sigintr & sigmask(sig))
  197                                         error = EINTR;
  198                                 else
  199                                         error = ERESTART;
  200                                 goto out;
  201                         }
  202                 }
  203                 if (thread_should_abort(self)) {
  204                         if (clear_wait(self, THREAD_INTERRUPTED) == KERN_FAILURE)
  205                                 goto block;
  206                         error = EINTR;
  207                         goto out;
  208                 }
  209                 if (get_thread_waitresult(self) != THREAD_WAITING) {
  210                         /*already happened */
  211                         goto out;
  212                 }
  213         }
  214 
  215 block:
  216 
  217         splx(s);
  218         p->p_stats->p_ru.ru_nvcsw++;
  219 
  220         if ((thread_continue_t)continuation != THREAD_CONTINUE_NULL ) {
  221           ut->uu_continuation = continuation;
  222           ut->uu_pri = pri;
  223           ut->uu_timo = abstime? 1: 0;
  224           (void) thread_block(_sleep_continue);
  225           /* NOTREACHED */
  226         }
  227 
  228         wait_result = thread_block(THREAD_CONTINUE_NULL);
  229 
  230         switch (wait_result) {
  231                 case THREAD_TIMED_OUT:
  232                         error = EWOULDBLOCK;
  233                         break;
  234                 case THREAD_AWAKENED:
  235                         /*
  236                          * Posix implies any signal should be delivered
  237                          * first, regardless of whether awakened due
  238                          * to receiving event.
  239                          */
  240                         if (!catch)
  241                                 break;
  242                         /* else fall through */
  243                 case THREAD_INTERRUPTED:
  244                         if (catch) {
  245                                 if (thread_should_abort(self)) {
  246                                         error = EINTR;
  247                                 } else if (SHOULDissignal(p,ut)) {
  248                                         if (sig = CURSIG(p)) {
  249                                                 if (p->p_sigacts->ps_sigintr & sigmask(sig))
  250                                                         error = EINTR;
  251                                                 else
  252                                                         error = ERESTART;
  253                                         }
  254                                         if (thread_should_abort(self)) {
  255                                                 error = EINTR;
  256                                         }
  257                                 }
  258                         }  else
  259                                 error = EINTR;
  260                         break;
  261         }
  262 out:
  263         if (error == EINTR || error == ERESTART)
  264                 act_set_astbsd(self);
  265         if (abstime)
  266                 thread_cancel_timer();
  267         (void) splx(s);
  268 #if KTRACE
  269         if (KTRPOINT(p, KTR_CSW))
  270                 ktrcsw(p->p_tracep, 0, 0, -1);
  271 #endif
  272         return (error);
  273 }
  274 
  275 int
  276 sleep(
  277         void    *chan,
  278         int             pri)
  279 {
  280         return _sleep((caddr_t)chan, pri, (char *)NULL, 0, (int (*)(int))0);
  281 }
  282 
  283 int
  284 tsleep(
  285         void    *chan,
  286         int             pri,
  287         char    *wmsg,
  288         int             timo)
  289 {
  290         u_int64_t       abstime = 0;
  291 
  292         if (timo)
  293                 clock_interval_to_deadline(timo, NSEC_PER_SEC / hz, &abstime);
  294         return _sleep((caddr_t)chan, pri, wmsg, abstime, (int (*)(int))0);
  295 }
  296 
  297 int
  298 tsleep0(
  299         void    *chan,
  300         int             pri,
  301         char    *wmsg,
  302         int             timo,
  303         int             (*continuation)(int))
  304 {                       
  305         u_int64_t       abstime = 0;
  306 
  307         if (timo)
  308                 clock_interval_to_deadline(timo, NSEC_PER_SEC / hz, &abstime);
  309         return _sleep((caddr_t)chan, pri, wmsg, abstime, continuation);
  310 }
  311 
  312 int
  313 tsleep1(
  314         void            *chan,
  315         int                     pri,
  316         char            *wmsg,
  317         u_int64_t       abstime,
  318         int                     (*continuation)(int))
  319 {                       
  320         return _sleep((caddr_t)chan, pri, wmsg, abstime, continuation);
  321 }
  322 
  323 /*
  324  * Wake up all processes sleeping on chan.
  325  */
  326 void
  327 wakeup(chan)
  328         register void *chan;
  329 {
  330         thread_wakeup_prim((caddr_t)chan, FALSE, THREAD_AWAKENED);
  331 }
  332 
  333 /*
  334  * Wake up the first process sleeping on chan.
  335  *
  336  * Be very sure that the first process is really
  337  * the right one to wakeup.
  338  */
  339 void
  340 wakeup_one(chan)
  341         register caddr_t chan;
  342 {
  343         thread_wakeup_prim((caddr_t)chan, TRUE, THREAD_AWAKENED);
  344 }
  345 
  346 /*
  347  * Compute the priority of a process when running in user mode.
  348  * Arrange to reschedule if the resulting priority is better
  349  * than that of the current process.
  350  */
  351 void
  352 resetpriority(p)
  353         register struct proc *p;
  354 {
  355         (void)task_importance(p->task, -p->p_nice);
  356 }
  357 
  358 struct loadavg averunnable =
  359         { {0, 0, 0}, FSCALE };          /* load average, of runnable procs */
  360 /*
  361  * Constants for averages over 1, 5, and 15 minutes
  362  * when sampling at 5 second intervals.
  363  */
  364 static fixpt_t cexp[3] = {
  365     (fixpt_t)(0.9200444146293232 * FSCALE),    /* exp(-1/12) */
  366     (fixpt_t)(0.9834714538216174 * FSCALE),    /* exp(-1/60) */
  367     (fixpt_t)(0.9944598480048967 * FSCALE),    /* exp(-1/180) */
  368 };
  369 
  370 void
  371 compute_averunnable(
  372         register int    nrun)
  373 {
  374         register int            i;
  375         struct loadavg          *avg = &averunnable;
  376 
  377     for (i = 0; i < 3; i++)
  378         avg->ldavg[i] = (cexp[i] * avg->ldavg[i] +
  379             nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT;
  380 }

Cache object: 328149cdfee1165b06d2644a4ee4e826


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.