fix so it compiles
[unix-history] / usr / src / sys / kern / kern_synch.c
CommitLineData
f406ae69
KB
1/*-
2 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
3 * Copyright (c) 1991 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * %sccs.include.redist.c%
da7c5cc6 7 *
968e7138 8 * @(#)kern_synch.c 7.23 (Berkeley) %G%
da7c5cc6 9 */
961945a8 10
94368568
JB
11#include "param.h"
12#include "systm.h"
94368568 13#include "proc.h"
94368568
JB
14#include "kernel.h"
15#include "buf.h"
c081e302
MK
16#include "signalvar.h"
17#include "resourcevar.h"
9fe02b59
MT
18#ifdef KTRACE
19#include "ktrace.h"
20#endif
1edb1cf8 21
132d8a6d 22#include "machine/cpu.h"
9db58063 23
70ca6a82 24u_char curpri; /* usrpri of curproc */
cca8a63d 25int lbolt; /* once a second sleep address */
70ca6a82 26
1edb1cf8
BJ
27/*
28 * Force switch among equal priority processes every 100ms.
29 */
30roundrobin()
31{
32
132d8a6d 33 need_resched();
b32450f4 34 timeout(roundrobin, (caddr_t)0, hz / 10);
1edb1cf8
BJ
35}
36
d048c9b6
KM
37/*
38 * constants for digital decay and forget
39 * 90% of (p_cpu) usage in 5*loadav time
40 * 95% of (p_pctcpu) usage in 60 seconds (load insensitive)
41 * Note that, as ps(1) mentions, this can let percentages
42 * total over 100% (I've seen 137.9% for 3 processes).
43 *
44 * Note that hardclock updates p_cpu and p_cpticks independently.
45 *
46 * We wish to decay away 90% of p_cpu in (5 * loadavg) seconds.
47 * That is, the system wants to compute a value of decay such
48 * that the following for loop:
49 * for (i = 0; i < (5 * loadavg); i++)
50 * p_cpu *= decay;
51 * will compute
52 * p_cpu *= 0.1;
53 * for all values of loadavg:
54 *
55 * Mathematically this loop can be expressed by saying:
56 * decay ** (5 * loadavg) ~= .1
57 *
58 * The system computes decay as:
59 * decay = (2 * loadavg) / (2 * loadavg + 1)
60 *
61 * We wish to prove that the system's computation of decay
62 * will always fulfill the equation:
63 * decay ** (5 * loadavg) ~= .1
64 *
65 * If we compute b as:
66 * b = 2 * loadavg
67 * then
68 * decay = b / (b + 1)
69 *
70 * We now need to prove two things:
71 * 1) Given factor ** (5 * loadavg) ~= .1, prove factor == b/(b+1)
72 * 2) Given b/(b+1) ** power ~= .1, prove power == (5 * loadavg)
73 *
74 * Facts:
75 * For x close to zero, exp(x) =~ 1 + x, since
76 * exp(x) = 0! + x**1/1! + x**2/2! + ... .
77 * therefore exp(-1/b) =~ 1 - (1/b) = (b-1)/b.
78 * For x close to zero, ln(1+x) =~ x, since
79 * ln(1+x) = x - x**2/2 + x**3/3 - ... -1 < x < 1
80 * therefore ln(b/(b+1)) = ln(1 - 1/(b+1)) =~ -1/(b+1).
81 * ln(.1) =~ -2.30
82 *
83 * Proof of (1):
84 * Solve (factor)**(power) =~ .1 given power (5*loadav):
85 * solving for factor,
86 * ln(factor) =~ (-2.30/5*loadav), or
132d8a6d 87 * factor =~ exp(-1/((5/2.30)*loadav)) =~ exp(-1/(2*loadav)) =
d048c9b6
KM
88 * exp(-1/b) =~ (b-1)/b =~ b/(b+1). QED
89 *
90 * Proof of (2):
91 * Solve (factor)**(power) =~ .1 given factor == (b/(b+1)):
92 * solving for power,
93 * power*ln(b/(b+1)) =~ -2.30, or
94 * power =~ 2.3 * (b + 1) = 4.6*loadav + 2.3 =~ 5*loadav. QED
95 *
96 * Actual power values for the implemented algorithm are as follows:
97 * loadav: 1 2 3 4
98 * power: 5.68 10.32 14.94 19.55
99 */
1e35e051 100
80b6b780 101/* calculations for digital decay to forget 90% of usage in 5*loadav sec */
132d8a6d
MK
102#define loadfactor(loadav) (2 * (loadav))
103#define decay_cpu(loadfac, cpu) (((loadfac) * (cpu)) / ((loadfac) + FSCALE))
80b6b780
KM
104
105/* decay 95% of `p_pctcpu' in 60 seconds; see CCPU_SHIFT before changing */
106fixpt_t ccpu = 0.95122942450071400909 * FSCALE; /* exp(-1/20) */
107
108/*
109 * If `ccpu' is not equal to `exp(-1/20)' and you still want to use the
110 * faster/more-accurate formula, you'll have to estimate CCPU_SHIFT below
111 * and possibly adjust FSHIFT in "param.h" so that (FSHIFT >= CCPU_SHIFT).
112 *
113 * To estimate CCPU_SHIFT for exp(-1/20), the following formula was used:
114 * 1 - exp(-1/20) ~= 0.0487 ~= 0.0488 == 1 (fixed pt, *11* bits).
115 *
116 * If you dont want to bother with the faster/more-accurate formula, you
117 * can set CCPU_SHIFT to (FSHIFT + 1) which will use a slower/less-accurate
118 * (more general) method of calculating the %age of CPU used by a process.
119 */
120#define CCPU_SHIFT 11
1edb1cf8 121
1edb1cf8
BJ
122/*
123 * Recompute process priorities, once a second
124 */
125schedcpu()
126{
ea853f5f 127 register fixpt_t loadfac = loadfactor(averunnable.ldavg[0]);
1edb1cf8 128 register struct proc *p;
132d8a6d
MK
129 register int s;
130 register unsigned int newcpu;
1edb1cf8 131
1edb1cf8 132 wakeup((caddr_t)&lbolt);
1d348849 133 for (p = allproc; p != NULL; p = p->p_nxt) {
132d8a6d
MK
134 /*
135 * Increment time in/out of memory and sleep time
136 * (if sleeping). We ignore overflow; with 16-bit int's
137 * (remember them?) overflow takes 45 days.
138 */
139 p->p_time++;
140 if (p->p_stat == SSLEEP || p->p_stat == SSTOP)
141 p->p_slptime++;
80b6b780 142 p->p_pctcpu = (p->p_pctcpu * ccpu) >> FSHIFT;
1e35e051
MK
143 /*
144 * If the process has slept the entire second,
145 * stop recalculating its priority until it wakes up.
146 */
80b6b780 147 if (p->p_slptime > 1)
1e35e051 148 continue;
1e35e051
MK
149 /*
150 * p_pctcpu is only for ps.
151 */
80b6b780
KM
152#if (FSHIFT >= CCPU_SHIFT)
153 p->p_pctcpu += (hz == 100)?
154 ((fixpt_t) p->p_cpticks) << (FSHIFT - CCPU_SHIFT):
155 100 * (((fixpt_t) p->p_cpticks)
156 << (FSHIFT - CCPU_SHIFT)) / hz;
157#else
158 p->p_pctcpu += ((FSCALE - ccpu) *
159 (p->p_cpticks * FSCALE / hz)) >> FSHIFT;
160#endif
1edb1cf8 161 p->p_cpticks = 0;
132d8a6d
MK
162 newcpu = (u_int) decay_cpu(loadfac, p->p_cpu) + p->p_nice;
163 p->p_cpu = min(newcpu, UCHAR_MAX);
164 setpri(p);
1e35e051 165 s = splhigh(); /* prevent state changes */
1edb1cf8 166 if (p->p_pri >= PUSER) {
132d8a6d 167#define PPQ (128 / NQS) /* priorities per queue */
c081e302 168 if ((p != curproc) &&
1edb1cf8
BJ
169 p->p_stat == SRUN &&
170 (p->p_flag & SLOAD) &&
fab25db3 171 (p->p_pri / PPQ) != (p->p_usrpri / PPQ)) {
1edb1cf8
BJ
172 remrq(p);
173 p->p_pri = p->p_usrpri;
174 setrq(p);
175 } else
176 p->p_pri = p->p_usrpri;
177 }
178 splx(s);
179 }
180 vmmeter();
1edb1cf8 181 if (bclnlist != NULL)
132d8a6d 182 wakeup((caddr_t)pageproc);
b32450f4 183 timeout(schedcpu, (caddr_t)0, hz);
1edb1cf8 184}
a379cce8 185
1e35e051
MK
186/*
187 * Recalculate the priority of a process after it has slept for a while.
132d8a6d
MK
188 * For all load averages >= 1 and max p_cpu of 255, sleeping for at least
189 * six times the loadfactor will decay p_cpu to zero.
1e35e051
MK
190 */
191updatepri(p)
192 register struct proc *p;
193{
132d8a6d 194 register unsigned int newcpu = p->p_cpu;
ea853f5f 195 register fixpt_t loadfac = loadfactor(averunnable.ldavg[0]);
132d8a6d
MK
196
197 if (p->p_slptime > 5 * loadfac)
198 p->p_cpu = 0;
199 else {
200 p->p_slptime--; /* the first time was done in schedcpu */
201 while (newcpu && --p->p_slptime)
202 newcpu = (int) decay_cpu(loadfac, newcpu);
203 p->p_cpu = min(newcpu, UCHAR_MAX);
204 }
205 setpri(p);
1e35e051
MK
206}
207
a379cce8
BJ
208#define SQSIZE 0100 /* Must be power of 2 */
209#define HASH(x) (( (int) x >> 5) & (SQSIZE-1))
3abb418a
KM
210struct slpque {
211 struct proc *sq_head;
212 struct proc **sq_tailp;
213} slpque[SQSIZE];
a379cce8 214
ffa9c89a
MK
215/*
216 * During autoconfiguration or after a panic, a sleep will simply
217 * lower the priority briefly to allow interrupts, then return.
218 * The priority to be used (safepri) is machine-dependent, thus this
219 * value is initialized and maintained in the machine-dependent layers.
220 * This priority will typically be 0, or the lowest priority
221 * that is safe for use on the interrupt stack; it can be made
222 * higher to block network software interrupts after panics.
223 */
224int safepri;
225
a379cce8 226/*
25667a4a
MK
227 * General sleep call.
228 * Suspends current process until a wakeup is made on chan.
229 * The process will then be made runnable with priority pri.
230 * Sleeps at most timo/hz seconds (0 means no timeout).
231 * If pri includes PCATCH flag, signals are checked
232 * before and after sleeping, else signals are not checked.
233 * Returns 0 if awakened, EWOULDBLOCK if the timeout expires.
234 * If PCATCH is set and a signal needs to be delivered,
235 * ERESTART is returned if the current system call should be restarted
236 * if possible, and EINTR is returned if the system call should
237 * be interrupted by the signal (return EINTR).
a379cce8 238 */
25667a4a 239tsleep(chan, pri, wmesg, timo)
968e7138 240 void *chan;
67e9a600
MT
241 int pri;
242 char *wmesg;
243 int timo;
244{
c081e302 245 register struct proc *p = curproc;
67e9a600
MT
246 register struct slpque *qp;
247 register s;
25667a4a 248 int sig, catch = pri & PCATCH;
67e9a600
MT
249 extern int cold;
250 int endtsleep();
251
9fe02b59
MT
252#ifdef KTRACE
253 if (KTRPOINT(p, KTR_CSW))
254 ktrcsw(p->p_tracep, 1, 0);
255#endif
67e9a600
MT
256 s = splhigh();
257 if (cold || panicstr) {
258 /*
259 * After a panic, or during autoconfiguration,
260 * just give interrupts a chance, then just return;
261 * don't run any other procs or panic below,
262 * in case this is the idle process and already asleep.
67e9a600 263 */
ffa9c89a 264 splx(safepri);
67e9a600
MT
265 splx(s);
266 return (0);
267 }
268#ifdef DIAGNOSTIC
968e7138 269 if (chan == NULL || p->p_stat != SRUN || p->p_rlink)
25667a4a 270 panic("tsleep");
67e9a600 271#endif
132d8a6d
MK
272 p->p_wchan = chan;
273 p->p_wmesg = wmesg;
274 p->p_slptime = 0;
275 p->p_pri = pri & PRIMASK;
67e9a600
MT
276 qp = &slpque[HASH(chan)];
277 if (qp->sq_head == 0)
132d8a6d 278 qp->sq_head = p;
67e9a600 279 else
132d8a6d
MK
280 *qp->sq_tailp = p;
281 *(qp->sq_tailp = &p->p_link) = 0;
ffa9c89a 282 if (timo)
132d8a6d 283 timeout(endtsleep, (caddr_t)p, timo);
67e9a600 284 /*
132d8a6d
MK
285 * We put ourselves on the sleep queue and start our timeout
286 * before calling CURSIG, as we could stop there, and a wakeup
287 * or a SIGCONT (or both) could occur while we were stopped.
ffa9c89a
MK
288 * A SIGCONT would cause us to be marked as SSLEEP
289 * without resuming us, thus we must be ready for sleep
290 * when CURSIG is called. If the wakeup happens while we're
132d8a6d 291 * stopped, p->p_wchan will be 0 upon return from CURSIG.
67e9a600 292 */
25667a4a 293 if (catch) {
132d8a6d
MK
294 p->p_flag |= SSINTR;
295 if (sig = CURSIG(p)) {
296 if (p->p_wchan)
297 unsleep(p);
298 p->p_stat = SRUN;
ffa9c89a 299 goto resume;
25667a4a 300 }
132d8a6d 301 if (p->p_wchan == 0) {
ffa9c89a
MK
302 catch = 0;
303 goto resume;
25667a4a 304 }
d4018dda
CT
305 } else
306 sig = 0;
132d8a6d 307 p->p_stat = SSLEEP;
132d8a6d 308 p->p_stats->p_ru.ru_nvcsw++;
67e9a600 309 swtch();
ffa9c89a 310resume:
132d8a6d 311 curpri = p->p_usrpri;
67e9a600 312 splx(s);
132d8a6d
MK
313 p->p_flag &= ~SSINTR;
314 if (p->p_flag & STIMO) {
315 p->p_flag &= ~STIMO;
d4018dda 316 if (sig == 0) {
9fe02b59
MT
317#ifdef KTRACE
318 if (KTRPOINT(p, KTR_CSW))
319 ktrcsw(p->p_tracep, 0, 0);
320#endif
ffa9c89a 321 return (EWOULDBLOCK);
9fe02b59 322 }
ffa9c89a 323 } else if (timo)
132d8a6d
MK
324 untimeout(endtsleep, (caddr_t)p);
325 if (catch && (sig != 0 || (sig = CURSIG(p)))) {
9fe02b59
MT
326#ifdef KTRACE
327 if (KTRPOINT(p, KTR_CSW))
328 ktrcsw(p->p_tracep, 0, 0);
329#endif
132d8a6d 330 if (p->p_sigacts->ps_sigintr & sigmask(sig))
25667a4a
MK
331 return (EINTR);
332 return (ERESTART);
333 }
9fe02b59
MT
334#ifdef KTRACE
335 if (KTRPOINT(p, KTR_CSW))
336 ktrcsw(p->p_tracep, 0, 0);
337#endif
67e9a600
MT
338 return (0);
339}
340
341/*
342 * Implement timeout for tsleep.
343 * If process hasn't been awakened (wchan non-zero),
344 * set timeout flag and undo the sleep. If proc
345 * is stopped, just unsleep so it will remain stopped.
346 */
347endtsleep(p)
348 register struct proc *p;
349{
350 int s = splhigh();
351
352 if (p->p_wchan) {
353 if (p->p_stat == SSLEEP)
354 setrun(p);
355 else
356 unsleep(p);
357 p->p_flag |= STIMO;
358 }
359 splx(s);
360}
361
25667a4a
MK
362/*
363 * Short-term, non-interruptable sleep.
364 */
a379cce8 365sleep(chan, pri)
968e7138 366 void *chan;
bd76c595 367 int pri;
a379cce8 368{
c081e302 369 register struct proc *p = curproc;
3abb418a 370 register struct slpque *qp;
6fdc0335 371 register s;
79a4402e 372 extern int cold;
a379cce8 373
25667a4a
MK
374#ifdef DIAGNOSTIC
375 if (pri > PZERO) {
376 printf("sleep called with pri %d > PZERO, wchan: %x\n",
968e7138 377 pri, chan);
25667a4a
MK
378 panic("old sleep");
379 }
380#endif
1e35e051 381 s = splhigh();
79a4402e 382 if (cold || panicstr) {
76acd871 383 /*
79a4402e
MK
384 * After a panic, or during autoconfiguration,
385 * just give interrupts a chance, then just return;
386 * don't run any other procs or panic below,
387 * in case this is the idle process and already asleep.
76acd871 388 */
ffa9c89a 389 splx(safepri);
76acd871
MK
390 splx(s);
391 return;
392 }
67e9a600 393#ifdef DIAGNOSTIC
968e7138 394 if (chan == NULL || p->p_stat != SRUN || p->p_rlink)
a379cce8 395 panic("sleep");
67e9a600 396#endif
132d8a6d
MK
397 p->p_wchan = chan;
398 p->p_wmesg = NULL;
399 p->p_slptime = 0;
400 p->p_pri = pri;
3abb418a
KM
401 qp = &slpque[HASH(chan)];
402 if (qp->sq_head == 0)
132d8a6d 403 qp->sq_head = p;
3abb418a 404 else
132d8a6d
MK
405 *qp->sq_tailp = p;
406 *(qp->sq_tailp = &p->p_link) = 0;
407 p->p_stat = SSLEEP;
132d8a6d 408 p->p_stats->p_ru.ru_nvcsw++;
9fe02b59
MT
409#ifdef KTRACE
410 if (KTRPOINT(p, KTR_CSW))
411 ktrcsw(p->p_tracep, 1, 0);
412#endif
25667a4a 413 swtch();
9fe02b59
MT
414#ifdef KTRACE
415 if (KTRPOINT(p, KTR_CSW))
416 ktrcsw(p->p_tracep, 0, 0);
417#endif
132d8a6d 418 curpri = p->p_usrpri;
a379cce8 419 splx(s);
a379cce8
BJ
420}
421
87d0f32e
BJ
422/*
423 * Remove a process from its wait queue
424 */
425unsleep(p)
18a4549b 426 register struct proc *p;
87d0f32e 427{
3abb418a 428 register struct slpque *qp;
87d0f32e 429 register struct proc **hp;
3abb418a 430 int s;
87d0f32e 431
1e35e051 432 s = splhigh();
87d0f32e 433 if (p->p_wchan) {
3abb418a 434 hp = &(qp = &slpque[HASH(p->p_wchan)])->sq_head;
87d0f32e
BJ
435 while (*hp != p)
436 hp = &(*hp)->p_link;
437 *hp = p->p_link;
3abb418a
KM
438 if (qp->sq_tailp == &p->p_link)
439 qp->sq_tailp = hp;
87d0f32e
BJ
440 p->p_wchan = 0;
441 }
442 splx(s);
443}
444
a379cce8 445/*
132d8a6d
MK
446 * Wakeup on "chan"; set all processes
447 * sleeping on chan to run state.
a379cce8
BJ
448 */
449wakeup(chan)
968e7138 450 register void *chan;
a379cce8 451{
3abb418a
KM
452 register struct slpque *qp;
453 register struct proc *p, **q;
a379cce8
BJ
454 int s;
455
1e35e051 456 s = splhigh();
3abb418a 457 qp = &slpque[HASH(chan)];
a379cce8 458restart:
3abb418a 459 for (q = &qp->sq_head; p = *q; ) {
67e9a600 460#ifdef DIAGNOSTIC
87d0f32e 461 if (p->p_rlink || p->p_stat != SSLEEP && p->p_stat != SSTOP)
a379cce8 462 panic("wakeup");
67e9a600 463#endif
132d8a6d 464 if (p->p_wchan == chan) {
a379cce8 465 p->p_wchan = 0;
e5df4be8 466 *q = p->p_link;
3abb418a
KM
467 if (qp->sq_tailp == &p->p_link)
468 qp->sq_tailp = q;
87d0f32e
BJ
469 if (p->p_stat == SSLEEP) {
470 /* OPTIMIZED INLINE EXPANSION OF setrun(p) */
6f414c22
MK
471 if (p->p_slptime > 1)
472 updatepri(p);
132d8a6d 473 p->p_slptime = 0;
87d0f32e 474 p->p_stat = SRUN;
c74c8a79 475 if (p->p_flag & SLOAD)
87d0f32e 476 setrq(p);
fab25db3
MK
477 /*
478 * Since curpri is a usrpri,
479 * p->p_pri is always better than curpri.
480 */
132d8a6d
MK
481 if ((p->p_flag&SLOAD) == 0)
482 wakeup((caddr_t)&proc0);
483 else
484 need_resched();
87d0f32e 485 /* END INLINE EXPANSION */
e5df4be8 486 goto restart;
a379cce8 487 }
e5df4be8
BJ
488 } else
489 q = &p->p_link;
a379cce8
BJ
490 }
491 splx(s);
492}
493
a379cce8
BJ
494/*
495 * Initialize the (doubly-linked) run queues
496 * to be empty.
497 */
498rqinit()
499{
500 register int i;
501
502 for (i = 0; i < NQS; i++)
503 qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i];
504}
a379cce8
BJ
505
506/*
132d8a6d
MK
507 * Change process state to be runnable,
508 * placing it on the run queue if it is in memory,
509 * and awakening the swapper if it isn't in memory.
a379cce8
BJ
510 */
511setrun(p)
18a4549b 512 register struct proc *p;
a379cce8 513{
18a4549b 514 register int s;
a379cce8 515
1e35e051 516 s = splhigh();
a379cce8
BJ
517 switch (p->p_stat) {
518
519 case 0:
520 case SWAIT:
521 case SRUN:
522 case SZOMB:
523 default:
524 panic("setrun");
525
6fdc0335 526 case SSTOP:
a379cce8 527 case SSLEEP:
87d0f32e 528 unsleep(p); /* e.g. when sending signals */
a379cce8
BJ
529 break;
530
531 case SIDL:
a379cce8
BJ
532 break;
533 }
534 p->p_stat = SRUN;
535 if (p->p_flag & SLOAD)
536 setrq(p);
537 splx(s);
27bc21f7
MK
538 if (p->p_slptime > 1)
539 updatepri(p);
132d8a6d
MK
540 p->p_slptime = 0;
541 if ((p->p_flag&SLOAD) == 0)
542 wakeup((caddr_t)&proc0);
543 else if (p->p_pri < curpri)
544 need_resched();
a379cce8
BJ
545}
546
547/*
132d8a6d
MK
548 * Compute priority of process when running in user mode.
549 * Arrange to reschedule if the resulting priority
550 * is better than that of the current process.
a379cce8 551 */
132d8a6d
MK
552setpri(p)
553 register struct proc *p;
a379cce8 554{
132d8a6d
MK
555 register unsigned int newpri;
556
557 newpri = PUSER + p->p_cpu / 4 + 2 * p->p_nice;
558 newpri = min(newpri, MAXPRI);
559 p->p_usrpri = newpri;
560 if (newpri < curpri)
561 need_resched();
a379cce8 562}