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