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/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) 1982, 1986, 1990, 1991, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  * (c) UNIX System Laboratories, Inc.
    5  * All or some portions of this file are derived from material licensed
    6  * to the University of California by American Telephone and Telegraph
    7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
    8  * the permission of UNIX System Laboratories, Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the University of
   21  *      California, Berkeley and its contributors.
   22  * 4. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  *      @(#)kern_synch.c        8.9 (Berkeley) 5/19/95
   39  * $FreeBSD: releng/5.0/sys/kern/kern_synch.c 107719 2002-12-10 02:33:45Z julian $
   40  */
   41 
   42 #include "opt_ddb.h"
   43 #include "opt_ktrace.h"
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/condvar.h>
   48 #include <sys/kernel.h>
   49 #include <sys/ktr.h>
   50 #include <sys/lock.h>
   51 #include <sys/mutex.h>
   52 #include <sys/proc.h>
   53 #include <sys/resourcevar.h>
   54 #include <sys/sched.h>
   55 #include <sys/signalvar.h>
   56 #include <sys/smp.h>
   57 #include <sys/sx.h>
   58 #include <sys/sysctl.h>
   59 #include <sys/sysproto.h>
   60 #include <sys/vmmeter.h>
   61 #ifdef DDB
   62 #include <ddb/ddb.h>
   63 #endif
   64 #ifdef KTRACE
   65 #include <sys/uio.h>
   66 #include <sys/ktrace.h>
   67 #endif
   68 
   69 #include <machine/cpu.h>
   70 
   71 static void sched_setup(void *dummy);
   72 SYSINIT(sched_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, sched_setup, NULL)
   73 
   74 int     hogticks;
   75 int     lbolt;
   76 
   77 static struct callout loadav_callout;
   78 static struct callout lbolt_callout;
   79 
   80 struct loadavg averunnable =
   81         { {0, 0, 0}, FSCALE };  /* load average, of runnable procs */
   82 /*
   83  * Constants for averages over 1, 5, and 15 minutes
   84  * when sampling at 5 second intervals.
   85  */
   86 static fixpt_t cexp[3] = {
   87         0.9200444146293232 * FSCALE,    /* exp(-1/12) */
   88         0.9834714538216174 * FSCALE,    /* exp(-1/60) */
   89         0.9944598480048967 * FSCALE,    /* exp(-1/180) */
   90 };
   91 
   92 /* kernel uses `FSCALE', userland (SHOULD) use kern.fscale */
   93 static int      fscale __unused = FSCALE;
   94 SYSCTL_INT(_kern, OID_AUTO, fscale, CTLFLAG_RD, 0, FSCALE, "");
   95 
   96 static void     endtsleep(void *);
   97 static void     loadav(void *arg);
   98 static void     lboltcb(void *arg);
   99 
  100 /*
  101  * We're only looking at 7 bits of the address; everything is
  102  * aligned to 4, lots of things are aligned to greater powers
  103  * of 2.  Shift right by 8, i.e. drop the bottom 256 worth.
  104  */
  105 #define TABLESIZE       128
  106 static TAILQ_HEAD(slpquehead, thread) slpque[TABLESIZE];
  107 #define LOOKUP(x)       (((intptr_t)(x) >> 8) & (TABLESIZE - 1))
  108 
  109 void
  110 sleepinit(void)
  111 {
  112         int i;
  113 
  114         hogticks = (hz / 10) * 2;       /* Default only. */
  115         for (i = 0; i < TABLESIZE; i++)
  116                 TAILQ_INIT(&slpque[i]);
  117 }
  118 
  119 /*
  120  * General sleep call.  Suspends the current process until a wakeup is
  121  * performed on the specified identifier.  The process will then be made
  122  * runnable with the specified priority.  Sleeps at most timo/hz seconds
  123  * (0 means no timeout).  If pri includes PCATCH flag, signals are checked
  124  * before and after sleeping, else signals are not checked.  Returns 0 if
  125  * awakened, EWOULDBLOCK if the timeout expires.  If PCATCH is set and a
  126  * signal needs to be delivered, ERESTART is returned if the current system
  127  * call should be restarted if possible, and EINTR is returned if the system
  128  * call should be interrupted by the signal (return EINTR).
  129  *
  130  * The mutex argument is exited before the caller is suspended, and
  131  * entered before msleep returns.  If priority includes the PDROP
  132  * flag the mutex is not entered before returning.
  133  */
  134 
  135 int
  136 msleep(ident, mtx, priority, wmesg, timo)
  137         void *ident;
  138         struct mtx *mtx;
  139         int priority, timo;
  140         const char *wmesg;
  141 {
  142         struct thread *td = curthread;
  143         struct proc *p = td->td_proc;
  144         int sig, catch = priority & PCATCH;
  145         int rval = 0;
  146         WITNESS_SAVE_DECL(mtx);
  147 
  148 #ifdef KTRACE
  149         if (KTRPOINT(td, KTR_CSW))
  150                 ktrcsw(1, 0);
  151 #endif
  152         WITNESS_SLEEP(0, &mtx->mtx_object);
  153         KASSERT(timo != 0 || mtx_owned(&Giant) || mtx != NULL,
  154             ("sleeping without a mutex"));
  155         /*
  156          * If we are capable of async syscalls and there isn't already
  157          * another one ready to return, start a new thread
  158          * and queue it as ready to run. Note that there is danger here
  159          * because we need to make sure that we don't sleep allocating
  160          * the thread (recursion here might be bad).
  161          * Hence the TDF_INMSLEEP flag.
  162          */
  163         if (p->p_flag & P_KSES) {
  164                 /*
  165                  * Just don't bother if we are exiting
  166                  * and not the exiting thread or thread was marked as
  167                  * interrupted.
  168                  */
  169                 if (catch &&
  170                     (((p->p_flag & P_WEXIT) && (p->p_singlethread != td)) ||
  171                      (td->td_flags & TDF_INTERRUPT))) {
  172                         td->td_flags &= ~TDF_INTERRUPT;
  173                         return (EINTR);
  174                 }
  175                 mtx_lock_spin(&sched_lock);
  176                 if ((td->td_flags & (TDF_UNBOUND|TDF_INMSLEEP)) ==
  177                     TDF_UNBOUND) {
  178                         /*
  179                          * Arrange for an upcall to be readied.
  180                          * it will not actually happen until all
  181                          * pending in-kernel work for this KSEGRP
  182                          * has been done.
  183                          */
  184                         /* Don't recurse here! */
  185                         td->td_flags |= TDF_INMSLEEP;
  186                         thread_schedule_upcall(td, td->td_kse);
  187                         td->td_flags &= ~TDF_INMSLEEP;
  188                 }
  189         } else {
  190                 mtx_lock_spin(&sched_lock);
  191         }
  192         if (cold ) {
  193                 /*
  194                  * During autoconfiguration, just give interrupts
  195                  * a chance, then just return.
  196                  * Don't run any other procs or panic below,
  197                  * in case this is the idle process and already asleep.
  198                  */
  199                 if (mtx != NULL && priority & PDROP)
  200                         mtx_unlock(mtx);
  201                 mtx_unlock_spin(&sched_lock);
  202                 return (0);
  203         }
  204 
  205         DROP_GIANT();
  206 
  207         if (mtx != NULL) {
  208                 mtx_assert(mtx, MA_OWNED | MA_NOTRECURSED);
  209                 WITNESS_SAVE(&mtx->mtx_object, mtx);
  210                 mtx_unlock(mtx);
  211                 if (priority & PDROP)
  212                         mtx = NULL;
  213         }
  214 
  215         KASSERT(p != NULL, ("msleep1"));
  216         KASSERT(ident != NULL && TD_IS_RUNNING(td), ("msleep"));
  217 
  218         CTR5(KTR_PROC, "msleep: thread %p (pid %d, %s) on %s (%p)",
  219             td, p->p_pid, p->p_comm, wmesg, ident);
  220 
  221         td->td_wchan = ident;
  222         td->td_wmesg = wmesg;
  223         TAILQ_INSERT_TAIL(&slpque[LOOKUP(ident)], td, td_slpq);
  224         TD_SET_ON_SLEEPQ(td);
  225         if (timo)
  226                 callout_reset(&td->td_slpcallout, timo, endtsleep, td);
  227         /*
  228          * We put ourselves on the sleep queue and start our timeout
  229          * before calling thread_suspend_check, as we could stop there, and
  230          * a wakeup or a SIGCONT (or both) could occur while we were stopped.
  231          * without resuming us, thus we must be ready for sleep
  232          * when cursig is called.  If the wakeup happens while we're
  233          * stopped, td->td_wchan will be 0 upon return from cursig.
  234          */
  235         if (catch) {
  236                 CTR3(KTR_PROC, "msleep caught: thread %p (pid %d, %s)", td,
  237                     p->p_pid, p->p_comm);
  238                 td->td_flags |= TDF_SINTR;
  239                 mtx_unlock_spin(&sched_lock);
  240                 PROC_LOCK(p);
  241                 sig = cursig(td);
  242                 if (sig == 0 && thread_suspend_check(1))
  243                         sig = SIGSTOP;
  244                 mtx_lock_spin(&sched_lock);
  245                 PROC_UNLOCK(p);
  246                 if (sig != 0) {
  247                         if (TD_ON_SLEEPQ(td))
  248                                 unsleep(td);
  249                 } else if (!TD_ON_SLEEPQ(td))
  250                         catch = 0;
  251         } else
  252                 sig = 0;
  253 
  254         /*
  255          * Let the scheduler know we're about to voluntarily go to sleep.
  256          */
  257         sched_sleep(td, priority & PRIMASK);
  258 
  259         if (TD_ON_SLEEPQ(td)) {
  260                 p->p_stats->p_ru.ru_nvcsw++;
  261                 TD_SET_SLEEPING(td);
  262                 mi_switch();
  263         }
  264         /*
  265          * We're awake from voluntary sleep.
  266          */
  267         CTR3(KTR_PROC, "msleep resume: thread %p (pid %d, %s)", td, p->p_pid,
  268             p->p_comm);
  269         KASSERT(TD_IS_RUNNING(td), ("running but not TDS_RUNNING"));
  270         td->td_flags &= ~TDF_SINTR;
  271         if (td->td_flags & TDF_TIMEOUT) {
  272                 td->td_flags &= ~TDF_TIMEOUT;
  273                 if (sig == 0)
  274                         rval = EWOULDBLOCK;
  275         } else if (td->td_flags & TDF_TIMOFAIL) {
  276                 td->td_flags &= ~TDF_TIMOFAIL;
  277         } else if (timo && callout_stop(&td->td_slpcallout) == 0) {
  278                 /*
  279                  * This isn't supposed to be pretty.  If we are here, then
  280                  * the endtsleep() callout is currently executing on another
  281                  * CPU and is either spinning on the sched_lock or will be
  282                  * soon.  If we don't synchronize here, there is a chance
  283                  * that this process may msleep() again before the callout
  284                  * has a chance to run and the callout may end up waking up
  285                  * the wrong msleep().  Yuck.
  286                  */
  287                 TD_SET_SLEEPING(td);
  288                 p->p_stats->p_ru.ru_nivcsw++;
  289                 mi_switch();
  290                 td->td_flags &= ~TDF_TIMOFAIL;
  291         } 
  292         if ((td->td_flags & TDF_INTERRUPT) && (priority & PCATCH) &&
  293             (rval == 0)) {
  294                 td->td_flags &= ~TDF_INTERRUPT;
  295                 rval = EINTR;
  296         }
  297         mtx_unlock_spin(&sched_lock);
  298 
  299         if (rval == 0 && catch) {
  300                 PROC_LOCK(p);
  301                 /* XXX: shouldn't we always be calling cursig() */
  302                 if (sig != 0 || (sig = cursig(td))) {
  303                         if (SIGISMEMBER(p->p_sigacts->ps_sigintr, sig))
  304                                 rval = EINTR;
  305                         else
  306                                 rval = ERESTART;
  307                 }
  308                 PROC_UNLOCK(p);
  309         }
  310 #ifdef KTRACE
  311         if (KTRPOINT(td, KTR_CSW))
  312                 ktrcsw(0, 0);
  313 #endif
  314         PICKUP_GIANT();
  315         if (mtx != NULL) {
  316                 mtx_lock(mtx);
  317                 WITNESS_RESTORE(&mtx->mtx_object, mtx);
  318         }
  319         return (rval);
  320 }
  321 
  322 /*
  323  * Implement timeout for msleep()
  324  *
  325  * If process hasn't been awakened (wchan non-zero),
  326  * set timeout flag and undo the sleep.  If proc
  327  * is stopped, just unsleep so it will remain stopped.
  328  * MP-safe, called without the Giant mutex.
  329  */
  330 static void
  331 endtsleep(arg)
  332         void *arg;
  333 {
  334         register struct thread *td = arg;
  335 
  336         CTR3(KTR_PROC, "endtsleep: thread %p (pid %d, %s)",
  337             td, td->td_proc->p_pid, td->td_proc->p_comm);
  338         mtx_lock_spin(&sched_lock);
  339         /*
  340          * This is the other half of the synchronization with msleep()
  341          * described above.  If the TDS_TIMEOUT flag is set, we lost the
  342          * race and just need to put the process back on the runqueue.
  343          */
  344         if (TD_ON_SLEEPQ(td)) {
  345                 TAILQ_REMOVE(&slpque[LOOKUP(td->td_wchan)], td, td_slpq);
  346                 TD_CLR_ON_SLEEPQ(td);
  347                 td->td_flags |= TDF_TIMEOUT;
  348         } else {
  349                 td->td_flags |= TDF_TIMOFAIL;
  350         }
  351         TD_CLR_SLEEPING(td);
  352         setrunnable(td);
  353         mtx_unlock_spin(&sched_lock);
  354 }
  355 
  356 /*
  357  * Abort a thread, as if an interrupt had occured.  Only abort
  358  * interruptable waits (unfortunatly it isn't only safe to abort others).
  359  * This is about identical to cv_abort().
  360  * Think about merging them?
  361  * Also, whatever the signal code does...
  362  */
  363 void
  364 abortsleep(struct thread *td)
  365 {
  366 
  367         mtx_assert(&sched_lock, MA_OWNED);
  368         /*
  369          * If the TDF_TIMEOUT flag is set, just leave. A
  370          * timeout is scheduled anyhow.
  371          */
  372         if ((td->td_flags & (TDF_TIMEOUT | TDF_SINTR)) == TDF_SINTR) {
  373                 if (TD_ON_SLEEPQ(td)) {
  374                         unsleep(td);
  375                         TD_CLR_SLEEPING(td);
  376                         setrunnable(td);
  377                 }
  378         }
  379 }
  380 
  381 /*
  382  * Remove a process from its wait queue
  383  */
  384 void
  385 unsleep(struct thread *td)
  386 {
  387 
  388         mtx_lock_spin(&sched_lock);
  389         if (TD_ON_SLEEPQ(td)) {
  390                 TAILQ_REMOVE(&slpque[LOOKUP(td->td_wchan)], td, td_slpq);
  391                 TD_CLR_ON_SLEEPQ(td);
  392         }
  393         mtx_unlock_spin(&sched_lock);
  394 }
  395 
  396 /*
  397  * Make all processes sleeping on the specified identifier runnable.
  398  */
  399 void
  400 wakeup(ident)
  401         register void *ident;
  402 {
  403         register struct slpquehead *qp;
  404         register struct thread *td;
  405         struct thread *ntd;
  406         struct proc *p;
  407 
  408         mtx_lock_spin(&sched_lock);
  409         qp = &slpque[LOOKUP(ident)];
  410 restart:
  411         for (td = TAILQ_FIRST(qp); td != NULL; td = ntd) {
  412                 ntd = TAILQ_NEXT(td, td_slpq);
  413                 if (td->td_wchan == ident) {
  414                         unsleep(td);
  415                         TD_CLR_SLEEPING(td);
  416                         setrunnable(td);
  417                         p = td->td_proc;
  418                         CTR3(KTR_PROC,"wakeup: thread %p (pid %d, %s)",
  419                             td, p->p_pid, p->p_comm);
  420                         goto restart;
  421                 }
  422         }
  423         mtx_unlock_spin(&sched_lock);
  424 }
  425 
  426 /*
  427  * Make a process sleeping on the specified identifier runnable.
  428  * May wake more than one process if a target process is currently
  429  * swapped out.
  430  */
  431 void
  432 wakeup_one(ident)
  433         register void *ident;
  434 {
  435         register struct slpquehead *qp;
  436         register struct thread *td;
  437         register struct proc *p;
  438         struct thread *ntd;
  439 
  440         mtx_lock_spin(&sched_lock);
  441         qp = &slpque[LOOKUP(ident)];
  442         for (td = TAILQ_FIRST(qp); td != NULL; td = ntd) {
  443                 ntd = TAILQ_NEXT(td, td_slpq);
  444                 if (td->td_wchan == ident) {
  445                         unsleep(td);
  446                         TD_CLR_SLEEPING(td);
  447                         setrunnable(td);
  448                         p = td->td_proc;
  449                         CTR3(KTR_PROC,"wakeup1: thread %p (pid %d, %s)",
  450                             td, p->p_pid, p->p_comm);
  451                         break;
  452                 }
  453         }
  454         mtx_unlock_spin(&sched_lock);
  455 }
  456 
  457 /*
  458  * The machine independent parts of mi_switch().
  459  */
  460 void
  461 mi_switch(void)
  462 {
  463         struct bintime new_switchtime;
  464         struct thread *td = curthread;  /* XXX */
  465         struct proc *p = td->td_proc;   /* XXX */
  466         struct kse *ke = td->td_kse;
  467         u_int sched_nest;
  468 
  469         mtx_assert(&sched_lock, MA_OWNED | MA_NOTRECURSED);
  470 
  471         KASSERT(!TD_ON_RUNQ(td), ("mi_switch: called by old code"));
  472 #ifdef INVARIANTS
  473         if (!TD_ON_LOCK(td) &&
  474             !TD_ON_RUNQ(td) &&
  475             !TD_IS_RUNNING(td))
  476                 mtx_assert(&Giant, MA_NOTOWNED);
  477 #endif
  478         KASSERT(td->td_critnest == 1,
  479             ("mi_switch: switch in a critical section"));
  480 
  481         /*
  482          * Compute the amount of time during which the current
  483          * process was running, and add that to its total so far.
  484          */
  485         binuptime(&new_switchtime);
  486         bintime_add(&p->p_runtime, &new_switchtime);
  487         bintime_sub(&p->p_runtime, PCPU_PTR(switchtime));
  488 
  489 #ifdef DDB
  490         /*
  491          * Don't perform context switches from the debugger.
  492          */
  493         if (db_active) {
  494                 mtx_unlock_spin(&sched_lock);
  495                 db_error("Context switches not allowed in the debugger.");
  496         }
  497 #endif
  498 
  499         /*
  500          * Check if the process exceeds its cpu resource allocation.  If
  501          * over max, arrange to kill the process in ast().
  502          */
  503         if (p->p_cpulimit != RLIM_INFINITY &&
  504             p->p_runtime.sec > p->p_cpulimit) {
  505                 p->p_sflag |= PS_XCPU;
  506                 ke->ke_flags |= KEF_ASTPENDING;
  507         }
  508 
  509         /*
  510          * Finish up stats for outgoing thread.
  511          */
  512         cnt.v_swtch++;
  513         PCPU_SET(switchtime, new_switchtime);
  514         CTR3(KTR_PROC, "mi_switch: old thread %p (pid %d, %s)", td, p->p_pid,
  515             p->p_comm);
  516 
  517         sched_nest = sched_lock.mtx_recurse;
  518         sched_switchout(td);
  519 
  520         cpu_switch();           /* SHAZAM!!*/
  521 
  522         sched_lock.mtx_recurse = sched_nest;
  523         sched_lock.mtx_lock = (uintptr_t)td;
  524         sched_switchin(td);
  525 
  526         /* 
  527          * Start setting up stats etc. for the incoming thread.
  528          * Similar code in fork_exit() is returned to by cpu_switch()
  529          * in the case of a new thread/process.
  530          */
  531         CTR3(KTR_PROC, "mi_switch: new thread %p (pid %d, %s)", td, p->p_pid,
  532             p->p_comm);
  533         if (PCPU_GET(switchtime.sec) == 0)
  534                 binuptime(PCPU_PTR(switchtime));
  535         PCPU_SET(switchticks, ticks);
  536 
  537         /*
  538          * Call the switchin function while still holding the scheduler lock
  539          * (used by the idlezero code and the general page-zeroing code)
  540          */
  541         if (td->td_switchin)
  542                 td->td_switchin();
  543 
  544         /* 
  545          * If the last thread was exiting, finish cleaning it up.
  546          */
  547         if ((td = PCPU_GET(deadthread))) {
  548                 PCPU_SET(deadthread, NULL);
  549                 thread_stash(td);
  550         }
  551 }
  552 
  553 /*
  554  * Change process state to be runnable,
  555  * placing it on the run queue if it is in memory,
  556  * and awakening the swapper if it isn't in memory.
  557  */
  558 void
  559 setrunnable(struct thread *td)
  560 {
  561         struct proc *p = td->td_proc;
  562 
  563         mtx_assert(&sched_lock, MA_OWNED);
  564         switch (p->p_state) {
  565         case PRS_ZOMBIE:
  566                 panic("setrunnable(1)");
  567         default:
  568                 break;
  569         }
  570         switch (td->td_state) {
  571         case TDS_RUNNING:
  572         case TDS_RUNQ:
  573                 return;
  574         case TDS_INHIBITED:
  575                 /*
  576                  * If we are only inhibited because we are swapped out
  577                  * then arange to swap in this process. Otherwise just return.
  578                  */
  579                 if (td->td_inhibitors != TDI_SWAPPED)
  580                         return;
  581         case TDS_CAN_RUN:
  582                 break;
  583         default:
  584                 printf("state is 0x%x", td->td_state);
  585                 panic("setrunnable(2)");
  586         }
  587         if ((p->p_sflag & PS_INMEM) == 0) {
  588                 if ((p->p_sflag & PS_SWAPPINGIN) == 0) {
  589                         p->p_sflag |= PS_SWAPINREQ;
  590                         wakeup(&proc0);
  591                 }
  592         } else
  593                 sched_wakeup(td);
  594 }
  595 
  596 /*
  597  * Compute a tenex style load average of a quantity on
  598  * 1, 5 and 15 minute intervals.
  599  * XXXKSE   Needs complete rewrite when correct info is available.
  600  * Completely Bogus.. only works with 1:1 (but compiles ok now :-)
  601  */
  602 static void
  603 loadav(void *arg)
  604 {
  605         int i, nrun;
  606         struct loadavg *avg;
  607         struct proc *p;
  608         struct thread *td;
  609 
  610         avg = &averunnable;
  611         sx_slock(&allproc_lock);
  612         nrun = 0;
  613         FOREACH_PROC_IN_SYSTEM(p) {
  614                 FOREACH_THREAD_IN_PROC(p, td) {
  615                         switch (td->td_state) {
  616                         case TDS_RUNQ:
  617                         case TDS_RUNNING:
  618                                 if ((p->p_flag & P_NOLOAD) != 0)
  619                                         goto nextproc;
  620                                 nrun++; /* XXXKSE */
  621                         default:
  622                                 break;
  623                         }
  624 nextproc:
  625                         continue;
  626                 }
  627         }
  628         sx_sunlock(&allproc_lock);
  629         for (i = 0; i < 3; i++)
  630                 avg->ldavg[i] = (cexp[i] * avg->ldavg[i] +
  631                     nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT;
  632 
  633         /*
  634          * Schedule the next update to occur after 5 seconds, but add a
  635          * random variation to avoid synchronisation with processes that
  636          * run at regular intervals.
  637          */
  638         callout_reset(&loadav_callout, hz * 4 + (int)(random() % (hz * 2 + 1)),
  639             loadav, NULL);
  640 }
  641 
  642 static void
  643 lboltcb(void *arg)
  644 {
  645         wakeup(&lbolt);
  646         callout_reset(&lbolt_callout, hz, lboltcb, NULL);
  647 }
  648 
  649 /* ARGSUSED */
  650 static void
  651 sched_setup(dummy)
  652         void *dummy;
  653 {
  654         callout_init(&loadav_callout, 0);
  655         callout_init(&lbolt_callout, 1);
  656 
  657         /* Kick off timeout driven events by calling first time. */
  658         loadav(NULL);
  659         lboltcb(NULL);
  660 }
  661 
  662 /*
  663  * General purpose yield system call
  664  */
  665 int
  666 yield(struct thread *td, struct yield_args *uap)
  667 {
  668         struct ksegrp *kg = td->td_ksegrp;
  669 
  670         mtx_assert(&Giant, MA_NOTOWNED);
  671         mtx_lock_spin(&sched_lock);
  672         kg->kg_proc->p_stats->p_ru.ru_nvcsw++;
  673         sched_prio(td, PRI_MAX_TIMESHARE);
  674         mi_switch();
  675         mtx_unlock_spin(&sched_lock);
  676         td->td_retval[0] = 0;
  677 
  678         return (0);
  679 }
  680 

Cache object: 8a0705e48f450b5a177d6944767f219d


[ 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.