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