|
|
1.1 root 1: /* slp.c 4.14 81/06/11 */
2:
3: #include "../h/param.h"
4: #include "../h/systm.h"
5: #include "../h/dir.h"
6: #include "../h/user.h"
7: #include "../h/lnode.h"
8: #include "../h/proc.h"
9: #include "../h/file.h"
10: #include "../h/inode.h"
11: #include "../h/vm.h"
12: #include "../h/pte.h"
13: #include "../h/mtpr.h"
14: #include "../h/share.h"
15:
16: #define SQSIZE 0100 /* Must be power of 2 */
17: #define HASH(x) (( (int) x >> 5) & (SQSIZE-1))
18: struct proc *slpque[SQSIZE];
19:
20: /*
21: * Give up the processor till a wakeup occurs
22: * on chan, at which time the process
23: * enters the scheduling queue at priority pri.
24: * The most important effect of pri is that when
25: * pri<=PZERO a signal cannot disturb the sleep;
26: * if pri>PZERO signals will be processed.
27: * Callers of this routine must be prepared for
28: * premature return, and check that the reason for
29: * sleeping has gone away.
30: */
31: sleep(chan, pri)
32: caddr_t chan;
33: {
34: register struct proc *rp, **hp;
35: register s;
36:
37: rp = u.u_procp;
38: s = spl6();
39: if (chan==0 || rp->p_stat != SRUN || rp->p_rlink)
40: panic("sleep");
41: rp->p_wchan = chan;
42: rp->p_slptime = 0;
43: rp->p_pri = pri;
44: hp = &slpque[HASH(chan)];
45: rp->p_link = *hp;
46: *hp = rp;
47: if(pri > PZERO) {
48: if(rp->p_sig && issig(rp)) {
49: if (rp->p_wchan)
50: unsleep(rp);
51: rp->p_stat = SRUN;
52: (void) spl0();
53: goto psig;
54: }
55: if (rp->p_wchan == 0)
56: goto out;
57: rp->p_stat = SSLEEP;
58: (void) spl0();
59: swtch();
60: if(rp->p_sig && issig(rp))
61: goto psig;
62: } else {
63: rp->p_stat = SSLEEP;
64: (void) spl0();
65: swtch();
66: }
67: out:
68: splx(s);
69: return;
70:
71: /*
72: * If priority was low (>PZERO) and
73: * there has been a signal,
74: * execute non-local goto to
75: * the qsav location.
76: * (see trap1/trap.c)
77: */
78: psig:
79: longjmp(u.u_qsav);
80: /*NOTREACHED*/
81: }
82:
83: /*
84: * Sleep on chan at pri.
85: * Return in no more than the indicated number of seconds.
86: * (If seconds==0, no timeout implied)
87: * Return TS_OK if chan was awakened normally
88: * TS_TIME if timeout occurred
89: * TS_SIG if asynchronous signal occurred
90: */
91: tsleep(chan, pri, seconds)
92: caddr_t chan;
93: {
94: label_t lqsav;
95: register n, rval;
96: register struct proc *pp = u.u_procp;
97:
98: n = spl7();
99: bcopy((caddr_t)u.u_qsav, (caddr_t)lqsav, sizeof (label_t));
100: pp->p_tsleep = seconds;
101: if (setjmp(u.u_qsav))
102: rval = TS_SIG;
103: else {
104: sleep(chan, pri);
105: if (pp->p_flag&STIMO)
106: rval = TS_TIME;
107: else
108: rval = TS_OK;
109: }
110: pp->p_tsleep = 0;
111: pp->p_flag &= ~STIMO;
112: bcopy((caddr_t)lqsav, (caddr_t)u.u_qsav, sizeof (label_t));
113: splx(n);
114: return(rval);
115: }
116:
117: /*
118: * Remove a process from its wait queue
119: */
120: unsleep(p)
121: register struct proc *p;
122: {
123: register struct proc **hp;
124: register s;
125:
126: s = spl6();
127: if (p->p_wchan) {
128: hp = &slpque[HASH(p->p_wchan)];
129: while (*hp != p)
130: hp = &(*hp)->p_link;
131: *hp = p->p_link;
132: p->p_wchan = 0;
133: }
134: splx(s);
135: }
136:
137: /*
138: * Wake up all processes sleeping on chan.
139: */
140: wakeup(chan)
141: register caddr_t chan;
142: {
143: register struct proc *p, **q, **h;
144: int s;
145:
146: s = spl6();
147: h = &slpque[HASH(chan)];
148: restart:
149: for (q = h; p = *q; ) {
150: if (p->p_rlink || p->p_stat != SSLEEP && p->p_stat != SSTOP)
151: panic("wakeup");
152: if (p->p_wchan==chan) {
153: p->p_wchan = 0;
154: *q = p->p_link;
155: p->p_slptime = 0;
156: if (p->p_stat == SSLEEP) {
157: /* OPTIMIZED INLINE EXPANSION OF setrun(p) */
158: p->p_stat = SRUN;
159: if (p->p_flag & SLOAD)
160: setrq(p);
161: if(p->p_pri < curpri) {
162: runrun++;
163: aston();
164: }
165: if ((p->p_flag&SLOAD) == 0) {
166: if (runout != 0) {
167: runout = 0;
168: wakeup((caddr_t)&runout);
169: }
170: wantin++;
171: }
172: /* END INLINE EXPANSION */
173: goto restart;
174: }
175: } else
176: q = &p->p_link;
177: }
178: splx(s);
179: }
180:
181: /*
182: * Initialize the (doubly-linked) run queues
183: * to be empty.
184: */
185: rqinit()
186: {
187: register int i;
188:
189: for (i = 0; i < NQS; i++)
190: qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i];
191: }
192:
193: /*
194: * Set the process running;
195: * arrange for it to be swapped in if necessary.
196: */
197: setrun(p)
198: register struct proc *p;
199: {
200: register s;
201:
202: s = spl6();
203: switch (p->p_stat) {
204:
205: case 0:
206: case SWAIT:
207: case SRUN:
208: case SZOMB:
209: default:
210: panic("setrun");
211:
212: case SSTOP:
213: case SSLEEP:
214: unsleep(p); /* e.g. when sending signals */
215: break;
216:
217: case SIDL:
218: break;
219: }
220: p->p_stat = SRUN;
221: if (p->p_flag & SLOAD)
222: setrq(p);
223: splx(s);
224: if(p->p_pri < curpri) {
225: runrun++;
226: aston();
227: }
228: if ((p->p_flag&SLOAD) == 0) {
229: if(runout != 0) {
230: runout = 0;
231: wakeup((caddr_t)&runout);
232: }
233: wantin++;
234: }
235: }
236:
237: /*
238: * Set user priority.
239: * The rescheduling flag (runrun)
240: * is set if the priority is better
241: * than the currently running process.
242: *
243: * (Remember divide by 4 in setrq().)
244: */
245: setpri(pp)
246: register struct proc *pp;
247: {
248: register int p;
249: register float f = pp->p_sharepri;
250: register int n = pp->p_nice;
251:
252: if (f > MaxSharePri || n == (2*NZERO-1)) {
253: if (pp->p_lnode->kl_norms) {
254: if (n == (2*NZERO-1))
255: p = 123; /* Background process */
256: else
257: p = 119; /* Background user */
258: } else
259: p = 127; /* Idle process */
260: } else {
261: f *= (float)((115-16)-PUSER);
262: p = f / MaxSharePri;
263: if (n > NZERO)
264: p += 16; /* Nice process */
265: if((p += PUSER) > 115)
266: p = 115;
267: }
268: if(p < curpri) {
269: runrun++;
270: aston();
271: }
272: pp->p_usrpri = p;
273: return(p);
274: }
275:
276: /*
277: * Create a new process-- the internal version of
278: * sys fork.
279: * It returns 1 in the new process, 0 in the old.
280: */
281: newproc(isvfork)
282: {
283: register struct proc *p;
284: register struct proc *rpp, *rip;
285: register int n;
286:
287: p = NULL;
288: /*
289: * First, just locate a slot for a process
290: * and copy the useful info from this process into it.
291: * The panic "cannot happen" because fork has already
292: * checked for the existence of a slot.
293: */
294: retry:
295: mpid++;
296: if(mpid >= 30000) {
297: mpid = 0;
298: goto retry;
299: }
300: for(rpp = proc; rpp < procNPROC; rpp++) {
301: if(rpp->p_stat == NULL && p==NULL)
302: p = rpp;
303: if (rpp->p_pid==mpid || rpp->p_pgrp==mpid)
304: goto retry;
305: }
306: if ((rpp = p)==NULL)
307: panic("no procs");
308:
309: /*
310: * make proc entry for new proc
311: */
312:
313: rip = u.u_procp;
314: rpp->p_stat = SIDL;
315: rpp->p_clktim = 0;
316: rpp->p_flag = SLOAD | (rip->p_flag & (SSEXEC|SPAGI|SDETACH|SNUSIG|STRC|SPROCTR));
317: if (isvfork) {
318: rpp->p_flag |= SVFORK;
319: rpp->p_ndx = rip->p_ndx;
320: } else
321: rpp->p_ndx = rpp - proc;
322: rpp->p_uid = rip->p_uid;
323: rpp->p_pgrp = rip->p_pgrp;
324: rpp->p_nice = rip->p_nice;
325: rpp->p_textp = isvfork ? 0 : rip->p_textp;
326: rpp->p_pid = mpid;
327: rpp->p_ppid = rip->p_pid;
328: rpp->p_pptr = rip;
329: rpp->p_time = 0;
330: rpp->p_cpu = 0;
331: rpp->p_siga0 = rip->p_siga0;
332: rpp->p_siga1 = rip->p_siga1;
333: /* take along any pending signals, like stops? */
334: if (isvfork) {
335: rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0;
336: rpp->p_szpt = clrnd(ctopt(UPAGES));
337: forkstat.cntvfork++;
338: forkstat.sizvfork += rip->p_dsize + rip->p_ssize;
339: } else {
340: rpp->p_tsize = rip->p_tsize;
341: rpp->p_dsize = rip->p_dsize;
342: rpp->p_ssize = rip->p_ssize;
343: rip->p_lnode->kl_muse += rip->p_dsize + rip->p_ssize;
344: rpp->p_szpt = rip->p_szpt;
345: forkstat.cntfork++;
346: forkstat.sizfork += rip->p_dsize + rip->p_ssize;
347: }
348: rpp->p_rssize = 0;
349: rpp->p_maxrss = rip->p_maxrss;
350: rpp->p_wchan = 0;
351: rpp->p_slptime = 0;
352: rpp->p_pctcpu = 0;
353: rpp->p_cpticks = 0;
354: rpp->p_lnode = rip->p_lnode;
355: rpp->p_sharepri = rip->p_sharepri;
356: rpp->p_lnode->kl_refcount++;
357: n = PIDHASH(rpp->p_pid);
358: p->p_idhash = pidhash[n];
359: pidhash[n] = rpp - proc;
360:
361: /*
362: * make duplicate entries
363: * where needed
364: */
365:
366: multprog++;
367:
368: for(n=0; n<NOFILE; n++)
369: if(u.u_ofile[n] != NULL)
370: u.u_ofile[n]->f_count++;
371:
372: u.u_cdir->i_count++;
373: if (u.u_rdir)
374: u.u_rdir->i_count++;
375: /*
376: * Partially simulate the environment
377: * of the new process so that when it is actually
378: * created (by copying) it will look right.
379: */
380:
381: rip->p_flag |= SKEEP; /* prevent parent from being swapped */
382:
383: if (procdup(rpp, isvfork))
384: return (1);
385:
386: (void) spl6();
387: rpp->p_stat = SRUN;
388: setrq(rpp);
389: (void) spl0();
390: /* SSWAP NOT NEEDED IN THIS CASE AS u.u_pcb.pcb_sswap SUFFICES */
391: /* rpp->p_flag |= SSWAP; */
392: rip->p_flag &= ~SKEEP;
393: if (isvfork) {
394: u.u_procp->p_xlink = rpp;
395: u.u_procp->p_flag |= SNOVM;
396: while (rpp->p_flag & SVFORK)
397: sleep((caddr_t)rpp, PZERO - 1);
398: if ((rpp->p_flag & SLOAD) == 0)
399: panic("newproc vfork");
400: uaccess(rpp, Vfmap, &vfutl);
401: u.u_procp->p_xlink = 0;
402: vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap);
403: u.u_procp->p_flag &= ~SNOVM;
404: rpp->p_ndx = rpp - proc;
405: rpp->p_flag |= SVFDONE;
406: wakeup((caddr_t)rpp);
407: }
408: return (0);
409: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.