|
|
1.1 root 1: #include "sys/param.h"
2: #include "sys/systm.h"
3: #include "sys/user.h"
4: #include "sys/proc.h"
5: #include "sys/file.h"
6: #include "sys/inode.h"
7: #include "sys/vm.h"
8: #include "sys/pte.h"
9: #include "sys/mtpr.h"
10:
11: #define SQSIZE 0100 /* Must be power of 2 */
12: #define HASH(x) (( (int) x >> 5) & (SQSIZE-1))
13: struct proc *slpque[SQSIZE];
14:
15: /*
16: * Give up the processor till a wakeup occurs
17: * on chan, at which time the process
18: * enters the scheduling queue at priority pri.
19: * The most important effect of pri is that when
20: * pri<=PZERO a signal cannot disturb the sleep;
21: * if pri>PZERO signals will be processed.
22: * Callers of this routine must be prepared for
23: * premature return, and check that the reason for
24: * sleeping has gone away.
25: */
26: sleep(chan, pri)
27: caddr_t chan;
28: {
29: register struct proc *rp, **hp;
30: register s;
31:
32: rp = u.u_procp;
33: s = spl6();
34: if (chan==0 || rp->p_stat != SRUN || rp->p_rlink)
35: panic("sleep");
36: rp->p_wchan = chan;
37: rp->p_slptime = 0;
38: rp->p_pri = pri;
39: hp = &slpque[HASH(chan)];
40: rp->p_link = *hp;
41: *hp = rp;
42: if(pri > PZERO) {
43: if(rp->p_sig && issig()) {
44: if (rp->p_wchan)
45: unsleep(rp);
46: rp->p_stat = SRUN;
47: (void) spl0();
48: goto psig;
49: }
50: if (rp->p_wchan == 0)
51: goto out;
52: rp->p_stat = SSLEEP;
53: (void) spl0();
54: swtch();
55: if(rp->p_sig && issig())
56: goto psig;
57: } else {
58: rp->p_stat = SSLEEP;
59: (void) spl0();
60: swtch();
61: }
62: out:
63: splx(s);
64: return;
65:
66: /*
67: * If priority was low (>PZERO) and
68: * there has been a signal,
69: * execute non-local goto to
70: * the qsav location.
71: * (see trap1/trap.c)
72: */
73: psig:
74: longjmp(u.u_qsav);
75: /*NOTREACHED*/
76: }
77:
78: /*
79: * Sleep on chan at pri.
80: * Return in no more than the indicated number of seconds.
81: * (If seconds==0, no timeout implied)
82: * Return TS_OK if chan was awakened normally
83: * TS_TIME if timeout occurred
84: * TS_SIG if asynchronous signal occurred
85: */
86: tsleep(chan, pri, seconds)
87: caddr_t chan;
88: {
89: label_t lqsav;
90: register n, rval;
91: register struct proc *pp = u.u_procp;
92:
93: n = spl7();
94: bcopy((caddr_t)u.u_qsav, (caddr_t)lqsav, sizeof (label_t));
95: pp->p_tsleep = seconds;
96: if (setjmp(u.u_qsav))
97: rval = TS_SIG;
98: else {
99: sleep(chan, pri);
100: if (pp->p_flag&STIMO)
101: rval = TS_TIME;
102: else
103: rval = TS_OK;
104: }
105: pp->p_flag &= ~STIMO;
106: bcopy((caddr_t)lqsav, (caddr_t)u.u_qsav, sizeof (label_t));
107: splx(n);
108: return(rval);
109: }
110:
111: /*
112: * Remove a process from its wait queue
113: */
114: unsleep(p)
115: register struct proc *p;
116: {
117: register struct proc **hp;
118: register s;
119:
120: s = spl6();
121: if (p->p_wchan) {
122: hp = &slpque[HASH(p->p_wchan)];
123: while (*hp != p)
124: hp = &(*hp)->p_link;
125: *hp = p->p_link;
126: p->p_wchan = 0;
127: }
128: splx(s);
129: }
130:
131: /*
132: * Wake up all processes sleeping on chan.
133: */
134: wakeup(chan)
135: register caddr_t chan;
136: {
137: register struct proc *p, **q, **h;
138: int s;
139:
140: s = spl6();
141: h = &slpque[HASH(chan)];
142: restart:
143: for (q = h; p = *q; ) {
144: if (p->p_rlink || p->p_stat != SSLEEP && p->p_stat != SSTOP)
145: panic("wakeup");
146: if (p->p_wchan==chan) {
147: p->p_wchan = 0;
148: *q = p->p_link;
149: p->p_slptime = 0;
150: p->p_tsleep = 0;
151: if (p->p_stat == SSLEEP) {
152: /* OPTIMIZED INLINE EXPANSION OF setrun(p) */
153: p->p_stat = SRUN;
154: if (p->p_flag & SLOAD)
155: setrq(p);
156: if(p->p_pri < curpri) {
157: runrun++;
158: aston();
159: }
160: if ((p->p_flag&SLOAD) == 0) {
161: if (runout != 0) {
162: runout = 0;
163: wakeup((caddr_t)&runout);
164: }
165: wantin++;
166: }
167: /* END INLINE EXPANSION */
168: goto restart;
169: }
170: } else
171: q = &p->p_link;
172: }
173: splx(s);
174: }
175:
176: /*
177: * Initialize the (doubly-linked) run queues
178: * to be empty.
179: */
180: rqinit()
181: {
182: register int i;
183:
184: for (i = 0; i < NQS; i++)
185: qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i];
186: }
187:
188: /*
189: * Set the process running;
190: * arrange for it to be swapped in if necessary.
191: */
192: setrun(p)
193: register struct proc *p;
194: {
195: register s;
196:
197: s = spl6();
198: switch (p->p_stat) {
199: default:
200: panic("setrun");
201:
202: case SSTOP:
203: case SSLEEP:
204: unsleep(p); /* e.g. when sending signals */
205: break;
206:
207: case SIDL:
208: break;
209: }
210: p->p_stat = SRUN;
211: if (p->p_flag & SLOAD)
212: setrq(p);
213: splx(s);
214: if(p->p_pri < curpri) {
215: runrun++;
216: aston();
217: }
218: if ((p->p_flag&SLOAD) == 0) {
219: if(runout != 0) {
220: runout = 0;
221: wakeup((caddr_t)&runout);
222: }
223: wantin++;
224: }
225: }
226:
227: /*
228: * Set user priority.
229: * The rescheduling flag (runrun)
230: * is set if the priority is better
231: * than the currently running process.
232: */
233: setpri(pp)
234: register struct proc *pp;
235: {
236: register int p;
237:
238: p = pp->p_cpu/4;
239: p += PUSER + 2*(pp->p_nice - NZERO);
240: if (pp->p_rssize > pp->p_maxrss && freemem < desfree)
241: p += 2*4; /* i.e. nice(4) */
242: if (p > PRIMAX)
243: p = PRIMAX;
244: if(p < curpri) {
245: runrun++;
246: aston();
247: }
248: pp->p_usrpri = p;
249: return(p);
250: }
251:
252: /*
253: * Create a new process--
254: * the internal version of sys fork.
255: * supply a process slot and a pid.
256: * returns 1 in the new process, 0 in the old.
257: */
258: newproc(rpp, pid)
259: register struct proc *rpp;
260: int pid;
261: {
262: register struct proc *rip;
263: register int n;
264:
265: /*
266: * init the proc entry
267: */
268: if (rpp->p_stat != 0)
269: panic("newproc");
270: rip = u.u_procp;
271: bzero((caddr_t)rpp, sizeof(*rpp));
272: rpp->p_stat = SIDL;
273: rpp->p_flag = SLOAD | (rip->p_flag & (SSEXEC|SPAGI|STRC|SPROCTR));
274: rpp->p_uid = rip->p_uid;
275: rpp->p_pgrp = rip->p_pgrp;
276: rpp->p_nice = rip->p_nice;
277: rpp->p_textp = rip->p_textp;
278: rpp->p_pid = pid;
279: rpp->p_ppid = rip->p_pid;
280: rpp->p_pptr = rip;
281: rpp->p_siga0 = rip->p_siga0;
282: rpp->p_siga1 = rip->p_siga1;
283: /* take along any pending signals, like stops? */
284: rpp->p_tsize = rip->p_tsize;
285: rpp->p_dsize = rip->p_dsize;
286: rpp->p_ssize = rip->p_ssize;
287: rpp->p_szpt = rip->p_szpt;
288: rpp->p_maxrss = rip->p_maxrss;
289: /*
290: * duplicate file references and so on
291: */
292: for(n=0; n<NOFILE; n++)
293: if(u.u_ofile[n] != NULL)
294: u.u_ofile[n]->f_count++;
295: u.u_cdir->i_count++;
296: if (u.u_rdir)
297: u.u_rdir->i_count++;
298: /*
299: * make the copy
300: * child returns 1 when made runnable
301: * parent makes child runnable and returns 0
302: */
303: rip->p_flag |= SKEEP; /* prevent parent from being swapped */
304: if (procdup(rpp))
305: return (1);
306: (void) spl6();
307: rpp->p_stat = SRUN;
308: setrq(rpp);
309: (void) spl0();
310: /* SSWAP NOT NEEDED IN THIS CASE AS u.u_pcb.pcb_sswap SUFFICES */
311: /* rpp->p_flag |= SSWAP; */
312: rip->p_flag &= ~SKEEP;
313: return (0);
314: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.