more lint
[unix-history] / usr / src / sys / kern / kern_synch.c
CommitLineData
b32450f4 1/* kern_synch.c 4.23 82/10/17 */
a379cce8
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/dir.h"
6#include "../h/user.h"
7#include "../h/proc.h"
8#include "../h/file.h"
9#include "../h/inode.h"
10#include "../h/vm.h"
11#include "../h/pte.h"
1edb1cf8 12#ifdef MUSH
9c25520d 13#include "../h/quota.h"
1edb1cf8
BJ
14#include "../h/share.h"
15#endif
16#include "../h/kernel.h"
17#include "../h/buf.h"
206ecc72 18#include "../vax/mtpr.h" /* XXX */
1edb1cf8
BJ
19
20/*
21 * Force switch among equal priority processes every 100ms.
22 */
23roundrobin()
24{
25
26 runrun++;
27 aston();
b32450f4 28 timeout(roundrobin, (caddr_t)0, hz / 10);
1edb1cf8
BJ
29}
30
d01b68d6 31/* constants to digital decay and forget 90% of usage in 5*loadav time */
1edb1cf8
BJ
32#undef ave
33#define ave(a,b) ((int)(((int)(a*b))/(b+1)))
34int nrscale = 2;
35double avenrun[];
1edb1cf8
BJ
36double ccpu = 0.95122942450071400909; /* exp(-1/20) */
37
1edb1cf8
BJ
38/*
39 * Recompute process priorities, once a second
40 */
41schedcpu()
42{
43 register struct proc *p;
44 register int s, a;
45
1edb1cf8 46 wakeup((caddr_t)&lbolt);
1edb1cf8
BJ
47 for (p = proc; p < procNPROC; p++) if (p->p_stat && p->p_stat!=SZOMB) {
48#ifdef MUSH
1edb1cf8
BJ
49 if (p->p_quota->q_uid)
50 p->p_quota->q_cost +=
51 shconsts.sc_click * p->p_rssize;
52#endif
53 if (p->p_time != 127)
54 p->p_time++;
1edb1cf8
BJ
55 if (p->p_stat==SSLEEP || p->p_stat==SSTOP)
56 if (p->p_slptime != 127)
57 p->p_slptime++;
58 if (p->p_flag&SLOAD)
59 p->p_pctcpu = ccpu * p->p_pctcpu +
60 (1.0 - ccpu) * (p->p_cpticks/(float)hz);
61 p->p_cpticks = 0;
62#ifdef MUSH
63 a = ave((p->p_cpu & 0377), avenrun[0]*nrscale) +
64 p->p_nice - NZERO + p->p_quota->q_nice;
65#else
66 a = ave((p->p_cpu & 0377), avenrun[0]*nrscale) +
67 p->p_nice - NZERO;
68#endif
69 if (a < 0)
70 a = 0;
71 if (a > 255)
72 a = 255;
73 p->p_cpu = a;
74 (void) setpri(p);
75 s = spl6(); /* prevent state changes */
76 if (p->p_pri >= PUSER) {
77 if ((p != u.u_procp || noproc) &&
78 p->p_stat == SRUN &&
79 (p->p_flag & SLOAD) &&
80 p->p_pri != p->p_usrpri) {
81 remrq(p);
82 p->p_pri = p->p_usrpri;
83 setrq(p);
84 } else
85 p->p_pri = p->p_usrpri;
86 }
87 splx(s);
88 }
89 vmmeter();
90 if (runin!=0) {
91 runin = 0;
92 wakeup((caddr_t)&runin);
93 }
94 if (bclnlist != NULL)
95 wakeup((caddr_t)&proc[2]);
b32450f4 96 timeout(schedcpu, (caddr_t)0, hz);
1edb1cf8 97}
a379cce8
BJ
98
99#define SQSIZE 0100 /* Must be power of 2 */
100#define HASH(x) (( (int) x >> 5) & (SQSIZE-1))
101struct proc *slpque[SQSIZE];
102
103/*
104 * Give up the processor till a wakeup occurs
105 * on chan, at which time the process
106 * enters the scheduling queue at priority pri.
107 * The most important effect of pri is that when
108 * pri<=PZERO a signal cannot disturb the sleep;
109 * if pri>PZERO signals will be processed.
110 * Callers of this routine must be prepared for
111 * premature return, and check that the reason for
112 * sleeping has gone away.
113 */
114sleep(chan, pri)
bd76c595
BJ
115 caddr_t chan;
116 int pri;
a379cce8 117{
e5df4be8 118 register struct proc *rp, **hp;
6fdc0335 119 register s;
a379cce8
BJ
120
121 rp = u.u_procp;
122 s = spl6();
123 if (chan==0 || rp->p_stat != SRUN || rp->p_rlink)
124 panic("sleep");
a379cce8
BJ
125 rp->p_wchan = chan;
126 rp->p_slptime = 0;
127 rp->p_pri = pri;
e5df4be8
BJ
128 hp = &slpque[HASH(chan)];
129 rp->p_link = *hp;
130 *hp = rp;
18a4549b
BJ
131 if (pri > PZERO) {
132 if (ISSIG(rp)) {
e5df4be8
BJ
133 if (rp->p_wchan)
134 unsleep(rp);
a379cce8 135 rp->p_stat = SRUN;
81263dba 136 (void) spl0();
a379cce8
BJ
137 goto psig;
138 }
e5df4be8
BJ
139 if (rp->p_wchan == 0)
140 goto out;
141 rp->p_stat = SSLEEP;
81263dba 142 (void) spl0();
bd76c595 143 u.u_ru.ru_nvcsw++;
a379cce8 144 swtch();
18a4549b 145 if (ISSIG(rp))
a379cce8
BJ
146 goto psig;
147 } else {
6fdc0335 148 rp->p_stat = SSLEEP;
81263dba 149 (void) spl0();
bd76c595 150 u.u_ru.ru_nvcsw++;
a379cce8
BJ
151 swtch();
152 }
e5df4be8 153out:
a379cce8
BJ
154 splx(s);
155 return;
156
157 /*
158 * If priority was low (>PZERO) and
18a4549b 159 * there has been a signal, execute non-local goto through
d01b68d6 160 * u.u_qsave, aborting the system call in progress (see trap.c)
18a4549b 161 * (or finishing a tsleep, see below)
a379cce8
BJ
162 */
163psig:
d01b68d6 164 longjmp(&u.u_qsave);
a379cce8
BJ
165 /*NOTREACHED*/
166}
167
87d0f32e
BJ
168/*
169 * Remove a process from its wait queue
170 */
171unsleep(p)
18a4549b 172 register struct proc *p;
87d0f32e
BJ
173{
174 register struct proc **hp;
175 register s;
176
177 s = spl6();
178 if (p->p_wchan) {
179 hp = &slpque[HASH(p->p_wchan)];
180 while (*hp != p)
181 hp = &(*hp)->p_link;
182 *hp = p->p_link;
183 p->p_wchan = 0;
184 }
185 splx(s);
186}
187
a379cce8
BJ
188/*
189 * Wake up all processes sleeping on chan.
190 */
191wakeup(chan)
18a4549b 192 register caddr_t chan;
a379cce8 193{
e5df4be8 194 register struct proc *p, **q, **h;
a379cce8
BJ
195 int s;
196
197 s = spl6();
e5df4be8 198 h = &slpque[HASH(chan)];
a379cce8 199restart:
e5df4be8 200 for (q = h; p = *q; ) {
87d0f32e 201 if (p->p_rlink || p->p_stat != SSLEEP && p->p_stat != SSTOP)
a379cce8 202 panic("wakeup");
6fdc0335 203 if (p->p_wchan==chan) {
a379cce8 204 p->p_wchan = 0;
e5df4be8 205 *q = p->p_link;
a379cce8 206 p->p_slptime = 0;
87d0f32e
BJ
207 if (p->p_stat == SSLEEP) {
208 /* OPTIMIZED INLINE EXPANSION OF setrun(p) */
209 p->p_stat = SRUN;
c74c8a79 210 if (p->p_flag & SLOAD)
87d0f32e 211 setrq(p);
18a4549b 212 if (p->p_pri < curpri) {
87d0f32e 213 runrun++;
534d9295
BJ
214 aston();
215 }
7eb2e67e
BJ
216 if ((p->p_flag&SLOAD) == 0) {
217 if (runout != 0) {
218 runout = 0;
219 wakeup((caddr_t)&runout);
220 }
221 wantin++;
87d0f32e
BJ
222 }
223 /* END INLINE EXPANSION */
e5df4be8 224 goto restart;
a379cce8 225 }
e5df4be8
BJ
226 } else
227 q = &p->p_link;
a379cce8
BJ
228 }
229 splx(s);
230}
231
a379cce8
BJ
232/*
233 * Initialize the (doubly-linked) run queues
234 * to be empty.
235 */
236rqinit()
237{
238 register int i;
239
240 for (i = 0; i < NQS; i++)
241 qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i];
242}
a379cce8
BJ
243
244/*
245 * Set the process running;
246 * arrange for it to be swapped in if necessary.
247 */
248setrun(p)
18a4549b 249 register struct proc *p;
a379cce8 250{
18a4549b 251 register int s;
a379cce8
BJ
252
253 s = spl6();
254 switch (p->p_stat) {
255
256 case 0:
257 case SWAIT:
258 case SRUN:
259 case SZOMB:
260 default:
261 panic("setrun");
262
6fdc0335 263 case SSTOP:
a379cce8 264 case SSLEEP:
87d0f32e 265 unsleep(p); /* e.g. when sending signals */
a379cce8
BJ
266 break;
267
268 case SIDL:
a379cce8
BJ
269 break;
270 }
271 p->p_stat = SRUN;
272 if (p->p_flag & SLOAD)
273 setrq(p);
274 splx(s);
18a4549b 275 if (p->p_pri < curpri) {
a379cce8 276 runrun++;
534d9295
BJ
277 aston();
278 }
7eb2e67e 279 if ((p->p_flag&SLOAD) == 0) {
18a4549b 280 if (runout != 0) {
7eb2e67e
BJ
281 runout = 0;
282 wakeup((caddr_t)&runout);
283 }
284 wantin++;
a379cce8
BJ
285 }
286}
287
288/*
289 * Set user priority.
290 * The rescheduling flag (runrun)
291 * is set if the priority is better
292 * than the currently running process.
293 */
294setpri(pp)
18a4549b 295 register struct proc *pp;
a379cce8 296{
18a4549b 297 register int p;
a379cce8 298
16a64baa 299 p = (pp->p_cpu & 0377)/4;
598563b5 300 p += PUSER + 2*(pp->p_nice - NZERO);
9afea775
BJ
301 if (pp->p_rssize > pp->p_maxrss && freemem < desfree)
302 p += 2*4; /* effectively, nice(4) */
18a4549b 303 if (p > 127)
a379cce8 304 p = 127;
18a4549b 305 if (p < curpri) {
a379cce8 306 runrun++;
a51a6e74
BJ
307 aston();
308 }
a379cce8 309 pp->p_usrpri = p;
18a4549b 310 return (p);
a379cce8 311}