kern_synch.c revision 34489
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 * $Id: kern_synch.c,v 1.49 1998/03/08 09:56:59 julian Exp $ 40 */ 41 42#include "opt_ktrace.h" 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/proc.h> 47#include <sys/kernel.h> 48#include <sys/signalvar.h> 49#include <sys/resourcevar.h> 50#include <sys/vmmeter.h> 51#include <sys/sysctl.h> 52#include <vm/vm.h> 53#include <vm/vm_extern.h> 54#ifdef KTRACE 55#include <sys/ktrace.h> 56#endif 57 58#include <machine/cpu.h> 59#include <machine/limits.h> /* for UCHAR_MAX = typeof(p_priority)_MAX */ 60 61static void rqinit __P((void *)); 62SYSINIT(runqueue, SI_SUB_RUN_QUEUE, SI_ORDER_FIRST, rqinit, NULL) 63 64u_char curpriority; /* usrpri of curproc */ 65int lbolt; /* once a second sleep address */ 66 67static void endtsleep __P((void *)); 68static void roundrobin __P((void *arg)); 69static void schedcpu __P((void *arg)); 70static void updatepri __P((struct proc *p)); 71 72#define MAXIMUM_SCHEDULE_QUANTUM (1000000) /* arbitrary limit */ 73#ifndef DEFAULT_SCHEDULE_QUANTUM 74#define DEFAULT_SCHEDULE_QUANTUM 10 75#endif 76static int quantum = DEFAULT_SCHEDULE_QUANTUM; /* default value */ 77 78static int 79sysctl_kern_quantum SYSCTL_HANDLER_ARGS 80{ 81 int error; 82 int new_val = quantum; 83 84 new_val = quantum; 85 error = sysctl_handle_int(oidp, &new_val, 0, req); 86 if (error == 0) { 87 if ((new_val > 0) && (new_val < MAXIMUM_SCHEDULE_QUANTUM)) { 88 quantum = new_val; 89 } else { 90 error = EINVAL; 91 } 92 } 93 return (error); 94} 95 96SYSCTL_PROC(_kern, OID_AUTO, quantum, CTLTYPE_INT|CTLFLAG_RW, 97 0, sizeof quantum, sysctl_kern_quantum, "I", ""); 98 99/* maybe_resched: Decide if you need to reschedule or not 100 * taking the priorities and schedulers into account. 101 */ 102static void maybe_resched(struct proc *chk) 103{ 104 struct proc *p = curproc; /* XXX */ 105 106 /* If the current scheduler is the idle scheduler or 107 * the priority of the new one is higher then reschedule. 108 */ 109 if (p == 0 || 110 RTP_PRIO_BASE(p->p_rtprio.type) == RTP_PRIO_IDLE || 111 (chk->p_priority < curpriority && 112 RTP_PRIO_BASE(p->p_rtprio.type) == RTP_PRIO_BASE(chk->p_rtprio.type)) ) 113 need_resched(); 114} 115 116#define ROUNDROBIN_INTERVAL (hz / quantum) 117int roundrobin_interval(void) 118{ 119 return ROUNDROBIN_INTERVAL; 120} 121 122/* 123 * Force switch among equal priority processes every 100ms. 124 */ 125/* ARGSUSED */ 126static void 127roundrobin(arg) 128 void *arg; 129{ 130 struct proc *p = curproc; /* XXX */ 131 132 if (p == 0 || RTP_PRIO_NEED_RR(p->p_rtprio.type)) 133 need_resched(); 134 135 timeout(roundrobin, NULL, ROUNDROBIN_INTERVAL); 136} 137 138/* 139 * Constants for digital decay and forget: 140 * 90% of (p_estcpu) usage in 5 * loadav time 141 * 95% of (p_pctcpu) usage in 60 seconds (load insensitive) 142 * Note that, as ps(1) mentions, this can let percentages 143 * total over 100% (I've seen 137.9% for 3 processes). 144 * 145 * Note that statclock() updates p_estcpu and p_cpticks asynchronously. 146 * 147 * We wish to decay away 90% of p_estcpu in (5 * loadavg) seconds. 148 * That is, the system wants to compute a value of decay such 149 * that the following for loop: 150 * for (i = 0; i < (5 * loadavg); i++) 151 * p_estcpu *= decay; 152 * will compute 153 * p_estcpu *= 0.1; 154 * for all values of loadavg: 155 * 156 * Mathematically this loop can be expressed by saying: 157 * decay ** (5 * loadavg) ~= .1 158 * 159 * The system computes decay as: 160 * decay = (2 * loadavg) / (2 * loadavg + 1) 161 * 162 * We wish to prove that the system's computation of decay 163 * will always fulfill the equation: 164 * decay ** (5 * loadavg) ~= .1 165 * 166 * If we compute b as: 167 * b = 2 * loadavg 168 * then 169 * decay = b / (b + 1) 170 * 171 * We now need to prove two things: 172 * 1) Given factor ** (5 * loadavg) ~= .1, prove factor == b/(b+1) 173 * 2) Given b/(b+1) ** power ~= .1, prove power == (5 * loadavg) 174 * 175 * Facts: 176 * For x close to zero, exp(x) =~ 1 + x, since 177 * exp(x) = 0! + x**1/1! + x**2/2! + ... . 178 * therefore exp(-1/b) =~ 1 - (1/b) = (b-1)/b. 179 * For x close to zero, ln(1+x) =~ x, since 180 * ln(1+x) = x - x**2/2 + x**3/3 - ... -1 < x < 1 181 * therefore ln(b/(b+1)) = ln(1 - 1/(b+1)) =~ -1/(b+1). 182 * ln(.1) =~ -2.30 183 * 184 * Proof of (1): 185 * Solve (factor)**(power) =~ .1 given power (5*loadav): 186 * solving for factor, 187 * ln(factor) =~ (-2.30/5*loadav), or 188 * factor =~ exp(-1/((5/2.30)*loadav)) =~ exp(-1/(2*loadav)) = 189 * exp(-1/b) =~ (b-1)/b =~ b/(b+1). QED 190 * 191 * Proof of (2): 192 * Solve (factor)**(power) =~ .1 given factor == (b/(b+1)): 193 * solving for power, 194 * power*ln(b/(b+1)) =~ -2.30, or 195 * power =~ 2.3 * (b + 1) = 4.6*loadav + 2.3 =~ 5*loadav. QED 196 * 197 * Actual power values for the implemented algorithm are as follows: 198 * loadav: 1 2 3 4 199 * power: 5.68 10.32 14.94 19.55 200 */ 201 202/* calculations for digital decay to forget 90% of usage in 5*loadav sec */ 203#define loadfactor(loadav) (2 * (loadav)) 204#define decay_cpu(loadfac, cpu) (((loadfac) * (cpu)) / ((loadfac) + FSCALE)) 205 206/* decay 95% of `p_pctcpu' in 60 seconds; see CCPU_SHIFT before changing */ 207static fixpt_t ccpu = 0.95122942450071400909 * FSCALE; /* exp(-1/20) */ 208 209/* 210 * If `ccpu' is not equal to `exp(-1/20)' and you still want to use the 211 * faster/more-accurate formula, you'll have to estimate CCPU_SHIFT below 212 * and possibly adjust FSHIFT in "param.h" so that (FSHIFT >= CCPU_SHIFT). 213 * 214 * To estimate CCPU_SHIFT for exp(-1/20), the following formula was used: 215 * 1 - exp(-1/20) ~= 0.0487 ~= 0.0488 == 1 (fixed pt, *11* bits). 216 * 217 * If you don't want to bother with the faster/more-accurate formula, you 218 * can set CCPU_SHIFT to (FSHIFT + 1) which will use a slower/less-accurate 219 * (more general) method of calculating the %age of CPU used by a process. 220 */ 221#define CCPU_SHIFT 11 222 223/* 224 * Recompute process priorities, every hz ticks. 225 */ 226/* ARGSUSED */ 227static void 228schedcpu(arg) 229 void *arg; 230{ 231 register fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); 232 register struct proc *p; 233 register int s; 234 register unsigned int newcpu; 235 236 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 237 /* 238 * Increment time in/out of memory and sleep time 239 * (if sleeping). We ignore overflow; with 16-bit int's 240 * (remember them?) overflow takes 45 days. 241 */ 242 p->p_swtime++; 243 if (p->p_stat == SSLEEP || p->p_stat == SSTOP) 244 p->p_slptime++; 245 p->p_pctcpu = (p->p_pctcpu * ccpu) >> FSHIFT; 246 /* 247 * If the process has slept the entire second, 248 * stop recalculating its priority until it wakes up. 249 */ 250 if (p->p_slptime > 1) 251 continue; 252 s = splhigh(); /* prevent state changes and protect run queue */ 253 /* 254 * p_pctcpu is only for ps. 255 */ 256#if (FSHIFT >= CCPU_SHIFT) 257 p->p_pctcpu += (hz == 100)? 258 ((fixpt_t) p->p_cpticks) << (FSHIFT - CCPU_SHIFT): 259 100 * (((fixpt_t) p->p_cpticks) 260 << (FSHIFT - CCPU_SHIFT)) / hz; 261#else 262 p->p_pctcpu += ((FSCALE - ccpu) * 263 (p->p_cpticks * FSCALE / hz)) >> FSHIFT; 264#endif 265 p->p_cpticks = 0; 266 newcpu = (u_int) decay_cpu(loadfac, p->p_estcpu) + p->p_nice; 267 p->p_estcpu = min(newcpu, UCHAR_MAX); 268 resetpriority(p); 269 if (p->p_priority >= PUSER) { 270#define PPQ (128 / NQS) /* priorities per queue */ 271 if ((p != curproc) && 272#ifdef SMP 273 (u_char)p->p_oncpu == 0xff && /* idle */ 274#endif 275 p->p_stat == SRUN && 276 (p->p_flag & P_INMEM) && 277 (p->p_priority / PPQ) != (p->p_usrpri / PPQ)) { 278 remrq(p); 279 p->p_priority = p->p_usrpri; 280 setrunqueue(p); 281 } else 282 p->p_priority = p->p_usrpri; 283 } 284 splx(s); 285 } 286 vmmeter(); 287 wakeup((caddr_t)&lbolt); 288 timeout(schedcpu, (void *)0, hz); 289} 290 291/* 292 * Recalculate the priority of a process after it has slept for a while. 293 * For all load averages >= 1 and max p_estcpu of 255, sleeping for at 294 * least six times the loadfactor will decay p_estcpu to zero. 295 */ 296static void 297updatepri(p) 298 register struct proc *p; 299{ 300 register unsigned int newcpu = p->p_estcpu; 301 register fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); 302 303 if (p->p_slptime > 5 * loadfac) 304 p->p_estcpu = 0; 305 else { 306 p->p_slptime--; /* the first time was done in schedcpu */ 307 while (newcpu && --p->p_slptime) 308 newcpu = (int) decay_cpu(loadfac, newcpu); 309 p->p_estcpu = min(newcpu, UCHAR_MAX); 310 } 311 resetpriority(p); 312} 313 314/* 315 * We're only looking at 7 bits of the address; everything is 316 * aligned to 4, lots of things are aligned to greater powers 317 * of 2. Shift right by 8, i.e. drop the bottom 256 worth. 318 */ 319#define TABLESIZE 128 320static TAILQ_HEAD(slpquehead, proc) slpque[TABLESIZE]; 321#define LOOKUP(x) (((long)(x) >> 8) & (TABLESIZE - 1)) 322 323/* 324 * During autoconfiguration or after a panic, a sleep will simply 325 * lower the priority briefly to allow interrupts, then return. 326 * The priority to be used (safepri) is machine-dependent, thus this 327 * value is initialized and maintained in the machine-dependent layers. 328 * This priority will typically be 0, or the lowest priority 329 * that is safe for use on the interrupt stack; it can be made 330 * higher to block network software interrupts after panics. 331 */ 332int safepri; 333 334void 335sleepinit() 336{ 337 int i; 338 339 for (i = 0; i < TABLESIZE; i++) 340 TAILQ_INIT(&slpque[i]); 341} 342 343/* 344 * General sleep call. Suspends the current process until a wakeup is 345 * performed on the specified identifier. The process will then be made 346 * runnable with the specified priority. Sleeps at most timo/hz seconds 347 * (0 means no timeout). If pri includes PCATCH flag, signals are checked 348 * before and after sleeping, else signals are not checked. Returns 0 if 349 * awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a 350 * signal needs to be delivered, ERESTART is returned if the current system 351 * call should be restarted if possible, and EINTR is returned if the system 352 * call should be interrupted by the signal (return EINTR). 353 */ 354int 355tsleep(ident, priority, wmesg, timo) 356 void *ident; 357 int priority, timo; 358 const char *wmesg; 359{ 360 struct proc *p = curproc; 361 int s, sig, catch = priority & PCATCH; 362 struct callout_handle thandle; 363 364#ifdef KTRACE 365 if (KTRPOINT(p, KTR_CSW)) 366 ktrcsw(p->p_tracep, 1, 0); 367#endif 368 s = splhigh(); 369 if (cold || panicstr) { 370 /* 371 * After a panic, or during autoconfiguration, 372 * just give interrupts a chance, then just return; 373 * don't run any other procs or panic below, 374 * in case this is the idle process and already asleep. 375 */ 376 splx(safepri); 377 splx(s); 378 return (0); 379 } 380#ifdef DIAGNOSTIC 381 if(p == NULL) 382 panic("tsleep1"); 383 if (ident == NULL || p->p_stat != SRUN) 384 panic("tsleep"); 385 /* XXX This is not exhaustive, just the most common case */ 386 if ((p->p_procq.tqe_prev != NULL) && (*p->p_procq.tqe_prev == p)) 387 panic("sleeping process already on another queue"); 388#endif 389 p->p_wchan = ident; 390 p->p_wmesg = wmesg; 391 p->p_slptime = 0; 392 p->p_priority = priority & PRIMASK; 393 TAILQ_INSERT_TAIL(&slpque[LOOKUP(ident)], p, p_procq); 394 if (timo) 395 thandle = timeout(endtsleep, (void *)p, timo); 396 /* 397 * We put ourselves on the sleep queue and start our timeout 398 * before calling CURSIG, as we could stop there, and a wakeup 399 * or a SIGCONT (or both) could occur while we were stopped. 400 * A SIGCONT would cause us to be marked as SSLEEP 401 * without resuming us, thus we must be ready for sleep 402 * when CURSIG is called. If the wakeup happens while we're 403 * stopped, p->p_wchan will be 0 upon return from CURSIG. 404 */ 405 if (catch) { 406 p->p_flag |= P_SINTR; 407 if ((sig = CURSIG(p))) { 408 if (p->p_wchan) 409 unsleep(p); 410 p->p_stat = SRUN; 411 goto resume; 412 } 413 if (p->p_wchan == 0) { 414 catch = 0; 415 goto resume; 416 } 417 } else 418 sig = 0; 419 p->p_stat = SSLEEP; 420 p->p_stats->p_ru.ru_nvcsw++; 421 mi_switch(); 422resume: 423 curpriority = p->p_usrpri; 424 splx(s); 425 p->p_flag &= ~P_SINTR; 426 if (p->p_flag & P_TIMEOUT) { 427 p->p_flag &= ~P_TIMEOUT; 428 if (sig == 0) { 429#ifdef KTRACE 430 if (KTRPOINT(p, KTR_CSW)) 431 ktrcsw(p->p_tracep, 0, 0); 432#endif 433 return (EWOULDBLOCK); 434 } 435 } else if (timo) 436 untimeout(endtsleep, (void *)p, thandle); 437 if (catch && (sig != 0 || (sig = CURSIG(p)))) { 438#ifdef KTRACE 439 if (KTRPOINT(p, KTR_CSW)) 440 ktrcsw(p->p_tracep, 0, 0); 441#endif 442 if (p->p_sigacts->ps_sigintr & sigmask(sig)) 443 return (EINTR); 444 return (ERESTART); 445 } 446#ifdef KTRACE 447 if (KTRPOINT(p, KTR_CSW)) 448 ktrcsw(p->p_tracep, 0, 0); 449#endif 450 return (0); 451} 452 453/* 454 * Implement timeout for tsleep. 455 * If process hasn't been awakened (wchan non-zero), 456 * set timeout flag and undo the sleep. If proc 457 * is stopped, just unsleep so it will remain stopped. 458 */ 459static void 460endtsleep(arg) 461 void *arg; 462{ 463 register struct proc *p; 464 int s; 465 466 p = (struct proc *)arg; 467 s = splhigh(); 468 if (p->p_wchan) { 469 if (p->p_stat == SSLEEP) 470 setrunnable(p); 471 else 472 unsleep(p); 473 p->p_flag |= P_TIMEOUT; 474 } 475 splx(s); 476} 477 478/* 479 * Remove a process from its wait queue 480 */ 481void 482unsleep(p) 483 register struct proc *p; 484{ 485 int s; 486 487 s = splhigh(); 488 if (p->p_wchan) { 489 TAILQ_REMOVE(&slpque[LOOKUP(p->p_wchan)], p, p_procq); 490 p->p_wchan = 0; 491 } 492 splx(s); 493} 494 495/* 496 * Make all processes sleeping on the specified identifier runnable. 497 */ 498void 499wakeup(ident) 500 register void *ident; 501{ 502 register struct slpquehead *qp; 503 register struct proc *p; 504 int s; 505 506 s = splhigh(); 507 qp = &slpque[LOOKUP(ident)]; 508restart: 509 for (p = qp->tqh_first; p != NULL; p = p->p_procq.tqe_next) { 510#ifdef DIAGNOSTIC 511 if (p->p_stat != SSLEEP && p->p_stat != SSTOP) 512 panic("wakeup"); 513#endif 514 if (p->p_wchan == ident) { 515 TAILQ_REMOVE(qp, p, p_procq); 516 p->p_wchan = 0; 517 if (p->p_stat == SSLEEP) { 518 /* OPTIMIZED EXPANSION OF setrunnable(p); */ 519 if (p->p_slptime > 1) 520 updatepri(p); 521 p->p_slptime = 0; 522 p->p_stat = SRUN; 523 if (p->p_flag & P_INMEM) { 524 setrunqueue(p); 525 maybe_resched(p); 526 } else { 527 p->p_flag |= P_SWAPINREQ; 528 wakeup((caddr_t)&proc0); 529 } 530 /* END INLINE EXPANSION */ 531 goto restart; 532 } 533 } 534 } 535 splx(s); 536} 537 538/* 539 * Make a process sleeping on the specified identifier runnable. 540 * May wake more than one process if a target prcoess is currently 541 * swapped out. 542 */ 543void 544wakeup_one(ident) 545 register void *ident; 546{ 547 register struct slpquehead *qp; 548 register struct proc *p; 549 int s; 550 551 s = splhigh(); 552 qp = &slpque[LOOKUP(ident)]; 553 554 for (p = qp->tqh_first; p != NULL; p = p->p_procq.tqe_next) { 555#ifdef DIAGNOSTIC 556 if (p->p_stat != SSLEEP && p->p_stat != SSTOP) 557 panic("wakeup_one"); 558#endif 559 if (p->p_wchan == ident) { 560 TAILQ_REMOVE(qp, p, p_procq); 561 p->p_wchan = 0; 562 if (p->p_stat == SSLEEP) { 563 /* OPTIMIZED EXPANSION OF setrunnable(p); */ 564 if (p->p_slptime > 1) 565 updatepri(p); 566 p->p_slptime = 0; 567 p->p_stat = SRUN; 568 if (p->p_flag & P_INMEM) { 569 setrunqueue(p); 570 maybe_resched(p); 571 break; 572 } else { 573 p->p_flag |= P_SWAPINREQ; 574 wakeup((caddr_t)&proc0); 575 } 576 /* END INLINE EXPANSION */ 577 } 578 } 579 } 580 splx(s); 581} 582 583/* 584 * The machine independent parts of mi_switch(). 585 * Must be called at splstatclock() or higher. 586 */ 587void 588mi_switch() 589{ 590 register struct proc *p = curproc; /* XXX */ 591 register struct rlimit *rlim; 592 register long s, u; 593 int x; 594 struct timeval tv; 595 596 /* 597 * XXX this spl is almost unnecessary. It is partly to allow for 598 * sloppy callers that don't do it (issignal() via CURSIG() is the 599 * main offender). It is partly to work around a bug in the i386 600 * cpu_switch() (the ipl is not preserved). We ran for years 601 * without it. I think there was only a interrupt latency problem. 602 * The main caller, tsleep(), does an splx() a couple of instructions 603 * after calling here. The buggy caller, issignal(), usually calls 604 * here at spl0() and sometimes returns at splhigh(). The process 605 * then runs for a little too long at splhigh(). The ipl gets fixed 606 * when the process returns to user mode (or earlier). 607 * 608 * It would probably be better to always call here at spl0(). Callers 609 * are prepared to give up control to another process, so they must 610 * be prepared to be interrupted. The clock stuff here may not 611 * actually need splstatclock(). 612 */ 613 x = splstatclock(); 614 615#ifdef SIMPLELOCK_DEBUG 616 if (p->p_simple_locks) 617 printf("sleep: holding simple lock\n"); 618#endif 619 /* 620 * Compute the amount of time during which the current 621 * process was running, and add that to its total so far. 622 */ 623 microtime(&tv); 624 u = p->p_rtime.tv_usec + (tv.tv_usec - runtime.tv_usec); 625 s = p->p_rtime.tv_sec + (tv.tv_sec - runtime.tv_sec); 626 if (u < 0) { 627 u += 1000000; 628 s--; 629 } else if (u >= 1000000) { 630 u -= 1000000; 631 s++; 632 } 633#ifdef SMP 634 if (s < 0) 635 s = u = 0; 636#endif 637 p->p_rtime.tv_usec = u; 638 p->p_rtime.tv_sec = s; 639 640 /* 641 * Check if the process exceeds its cpu resource allocation. 642 * If over max, kill it. 643 */ 644 if (p->p_stat != SZOMB) { 645 rlim = &p->p_rlimit[RLIMIT_CPU]; 646 if (s >= rlim->rlim_cur) { 647 if (s >= rlim->rlim_max) 648 killproc(p, "exceeded maximum CPU limit"); 649 else { 650 psignal(p, SIGXCPU); 651 if (rlim->rlim_cur < rlim->rlim_max) 652 rlim->rlim_cur += 5; 653 } 654 } 655 } 656 657 /* 658 * Pick a new current process and record its start time. 659 */ 660 cnt.v_swtch++; 661 cpu_switch(p); 662 microtime(&runtime); 663 splx(x); 664} 665 666/* 667 * Initialize the (doubly-linked) run queues 668 * to be empty. 669 */ 670/* ARGSUSED*/ 671static void 672rqinit(dummy) 673 void *dummy; 674{ 675 register int i; 676 677 for (i = 0; i < NQS; i++) { 678 qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i]; 679 rtqs[i].ph_link = rtqs[i].ph_rlink = (struct proc *)&rtqs[i]; 680 idqs[i].ph_link = idqs[i].ph_rlink = (struct proc *)&idqs[i]; 681 } 682} 683 684/* 685 * Change process state to be runnable, 686 * placing it on the run queue if it is in memory, 687 * and awakening the swapper if it isn't in memory. 688 */ 689void 690setrunnable(p) 691 register struct proc *p; 692{ 693 register int s; 694 695 s = splhigh(); 696 switch (p->p_stat) { 697 case 0: 698 case SRUN: 699 case SZOMB: 700 default: 701 panic("setrunnable"); 702 case SSTOP: 703 case SSLEEP: 704 unsleep(p); /* e.g. when sending signals */ 705 break; 706 707 case SIDL: 708 break; 709 } 710 p->p_stat = SRUN; 711 if (p->p_flag & P_INMEM) 712 setrunqueue(p); 713 splx(s); 714 if (p->p_slptime > 1) 715 updatepri(p); 716 p->p_slptime = 0; 717 if ((p->p_flag & P_INMEM) == 0) { 718 p->p_flag |= P_SWAPINREQ; 719 wakeup((caddr_t)&proc0); 720 } 721 else 722 maybe_resched(p); 723} 724 725/* 726 * Compute the priority of a process when running in user mode. 727 * Arrange to reschedule if the resulting priority is better 728 * than that of the current process. 729 */ 730void 731resetpriority(p) 732 register struct proc *p; 733{ 734 register unsigned int newpriority; 735 736 if (p->p_rtprio.type == RTP_PRIO_NORMAL) { 737 newpriority = PUSER + p->p_estcpu / 4 + 2 * p->p_nice; 738 newpriority = min(newpriority, MAXPRI); 739 p->p_usrpri = newpriority; 740 } 741 maybe_resched(p); 742} 743 744/* ARGSUSED */ 745static void sched_setup __P((void *dummy)); 746static void 747sched_setup(dummy) 748 void *dummy; 749{ 750 /* Kick off timeout driven events by calling first time. */ 751 roundrobin(NULL); 752 schedcpu(NULL); 753} 754SYSINIT(sched_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, sched_setup, NULL) 755 756