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