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