date and time created 80/04/09 16:04:11 by bill
[unix-history] / usr / src / sys / kern / kern_synch.c
CommitLineData
a379cce8
BJ
1/* kern_synch.c 3.1 %H% */
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"
12
13#ifdef FASTVAX
14asm(" .globl _eintr");
15#endif
16
17#define SQSIZE 0100 /* Must be power of 2 */
18#define HASH(x) (( (int) x >> 5) & (SQSIZE-1))
19struct proc *slpque[SQSIZE];
20
21/*
22 * Give up the processor till a wakeup occurs
23 * on chan, at which time the process
24 * enters the scheduling queue at priority pri.
25 * The most important effect of pri is that when
26 * pri<=PZERO a signal cannot disturb the sleep;
27 * if pri>PZERO signals will be processed.
28 * Callers of this routine must be prepared for
29 * premature return, and check that the reason for
30 * sleeping has gone away.
31 */
32sleep(chan, pri)
33caddr_t chan;
34{
35 register struct proc *rp;
36 register s, h;
37
38 rp = u.u_procp;
39 s = spl6();
40 if (chan==0 || rp->p_stat != SRUN || rp->p_rlink)
41 panic("sleep");
42 rp->p_stat = SSLEEP;
43 rp->p_wchan = chan;
44 rp->p_slptime = 0;
45 rp->p_pri = pri;
46 h = HASH(chan);
47 rp->p_link = slpque[h];
48 slpque[h] = rp;
49 if(pri > PZERO) {
50 if(rp->p_sig && issig()) {
51 rp->p_wchan = 0;
52 rp->p_stat = SRUN;
53 slpque[h] = rp->p_link;
54 VOID spl0();
55 goto psig;
56 }
57 VOID spl0();
58 if(runin != 0) {
59 runin = 0;
60 wakeup((caddr_t)&runin);
61 }
62 swtch();
63 if(rp->p_sig && issig())
64 goto psig;
65 } else {
66 VOID spl0();
67 swtch();
68 }
69 splx(s);
70 return;
71
72 /*
73 * If priority was low (>PZERO) and
74 * there has been a signal,
75 * execute non-local goto to
76 * the qsav location.
77 * (see trap1/trap.c)
78 */
79psig:
80#ifndef FASTVAX
81 longjmp(u.u_qsav);
82#else
83 asm(".set U_SSAV,140");
84 asm("movl _u+U_SSAV,fp");
85 asm("movl _u+U_SSAV+4,sp");
86 asm("movl _u+U_SSAV+8,r11");
87 u.u_error = EINTR;
88 asm("jmp _eintr");
89#endif
90 /*NOTREACHED*/
91}
92
93/*
94 * Wake up all processes sleeping on chan.
95 */
96wakeup(chan)
97register caddr_t chan;
98{
99 register struct proc *p, *q;
100 register i;
101 int s;
102
103 s = spl6();
104 i = HASH(chan);
105restart:
106 p = slpque[i];
107 q = NULL;
108 while(p != NULL) {
109 if (p->p_rlink || p->p_stat != SSLEEP)
110 panic("wakeup");
111 if (p->p_wchan==chan && p->p_stat!=SZOMB) {
112 if (q == NULL)
113 slpque[i] = p->p_link;
114 else
115 q->p_link = p->p_link;
116 p->p_wchan = 0;
117 p->p_slptime = 0;
118 /* OPTIMIZED INLINE EXPANSION OF setrun(p) */
119 p->p_stat = SRUN;
120 if (p->p_flag & SLOAD) {
121#ifndef FASTVAX
122 p->p_link = runq;
123 runq = p->p_link;
124#else
125 setrq(p);
126#endif
127 }
128 if(p->p_pri < curpri)
129 runrun++;
130 if(runout != 0 && (p->p_flag&SLOAD) == 0) {
131 runout = 0;
132 wakeup((caddr_t)&runout);
133 }
134 /* END INLINE EXPANSION */
135 goto restart;
136 }
137 q = p;
138 p = p->p_link;
139 }
140 splx(s);
141}
142
143#ifdef FASTVAX
144/*
145 * Initialize the (doubly-linked) run queues
146 * to be empty.
147 */
148rqinit()
149{
150 register int i;
151
152 for (i = 0; i < NQS; i++)
153 qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i];
154}
155#endif
156
157/*
158 * Set the process running;
159 * arrange for it to be swapped in if necessary.
160 */
161setrun(p)
162register struct proc *p;
163{
164 register caddr_t w;
165 register s;
166
167 s = spl6();
168 switch (p->p_stat) {
169
170 case 0:
171 case SWAIT:
172 case SRUN:
173 case SZOMB:
174 default:
175 panic("setrun");
176
177 case SSLEEP:
178 if (w = p->p_wchan) {
179 wakeup(w);
180 splx(s);
181 return;
182 }
183 break;
184
185 case SIDL:
186 case SSTOP:
187 break;
188 }
189 p->p_stat = SRUN;
190 if (p->p_flag & SLOAD)
191 setrq(p);
192 splx(s);
193 if(p->p_pri < curpri)
194 runrun++;
195 if(runout != 0 && (p->p_flag&SLOAD) == 0) {
196 runout = 0;
197 wakeup((caddr_t)&runout);
198 }
199}
200
201/*
202 * Set user priority.
203 * The rescheduling flag (runrun)
204 * is set if the priority is better
205 * than the currently running process.
206 */
207setpri(pp)
208register struct proc *pp;
209{
210 register p;
211
212 p = (pp->p_cpu & 0377)/16;
213 p += PUSER + pp->p_nice - NZERO;
214 if(p > 127)
215 p = 127;
216 if(p < curpri)
217 runrun++;
218 pp->p_usrpri = p;
219 return(p);
220}
221
222/*
223 * Create a new process-- the internal version of
224 * sys fork.
225 * It returns 1 in the new process, 0 in the old.
226 */
227newproc(isvfork)
228{
229 register struct proc *p;
230 register struct proc *rpp, *rip;
231 register int n;
232
233 p = NULL;
234 /*
235 * First, just locate a slot for a process
236 * and copy the useful info from this process into it.
237 * The panic "cannot happen" because fork has already
238 * checked for the existence of a slot.
239 */
240retry:
241 mpid++;
242 if(mpid >= 30000) {
243 mpid = 0;
244 goto retry;
245 }
246 for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) {
247 if(rpp->p_stat == NULL && p==NULL)
248 p = rpp;
249 if (rpp->p_pid==mpid || rpp->p_pgrp==mpid)
250 goto retry;
251 }
252 if ((rpp = p)==NULL)
253 panic("no procs");
254
255 /*
256 * make proc entry for new proc
257 */
258
259 rip = u.u_procp;
260 rpp->p_stat = SIDL;
261 rpp->p_clktim = 0;
262 rpp->p_flag = SLOAD | (rip->p_flag & SPAGI);
263 if (isvfork) {
264 rpp->p_flag |= SVFORK;
265 rpp->p_ndx = rip->p_ndx;
266 } else
267 rpp->p_ndx = rpp - proc;
268 rpp->p_uid = rip->p_uid;
269 rpp->p_pgrp = rip->p_pgrp;
270 rpp->p_nice = rip->p_nice;
271 rpp->p_textp = isvfork ? 0 : rip->p_textp;
272 rpp->p_pid = mpid;
273 rpp->p_ppid = rip->p_pid;
274 rpp->p_time = 0;
275 rpp->p_cpu = 0;
276 if (isvfork) {
277 rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0;
278 rpp->p_szpt = clrnd(ctopt(UPAGES));
279 forkstat.cntvfork++;
280 forkstat.sizvfork += rip->p_dsize + rip->p_ssize;
281 } else {
282 rpp->p_tsize = rip->p_tsize;
283 rpp->p_dsize = rip->p_dsize;
284 rpp->p_ssize = rip->p_ssize;
285 rpp->p_szpt = rip->p_szpt;
286 forkstat.cntfork++;
287 forkstat.sizfork += rip->p_dsize + rip->p_ssize;
288 }
289 rpp->p_rssize = 0;
290 rpp->p_wchan = 0;
291 rpp->p_slptime = 0;
292 rpp->p_aveflt = rip->p_aveflt;
293 rate.v_pgin += rip->p_aveflt;
294 rpp->p_faults = 0;
295 n = PIDHASH(rpp->p_pid);
296 p->p_idhash = pidhash[n];
297 pidhash[n] = rpp - proc;
298
299 /*
300 * make duplicate entries
301 * where needed
302 */
303
304 multprog++;
305
306 for(n=0; n<NOFILE; n++)
307 if(u.u_ofile[n] != NULL) {
308 u.u_ofile[n]->f_count++;
309 if(!isvfork && u.u_vrpages[n])
310 u.u_ofile[n]->f_inode->i_vfdcnt++;
311 }
312
313 u.u_cdir->i_count++;
314 if (u.u_rdir)
315 u.u_rdir->i_count++;
316 /*
317 * Partially simulate the environment
318 * of the new process so that when it is actually
319 * created (by copying) it will look right.
320 */
321
322 rip->p_flag |= SKEEP; /* prevent parent from being swapped */
323
324 if (procdup(rpp, isvfork))
325 return (1);
326
327 spl6();
328 rpp->p_stat = SRUN;
329 setrq(rpp);
330 spl0();
331 /* THE SSWAP BIT IS REPLACED BY u.u_pcb.pcb_sswap SEE procdup */
332 /* rpp->p_flag |= SSWAP; */
333 rip->p_flag &= ~SKEEP;
334 if (isvfork) {
335 u.u_procp->p_xlink = rpp;
336 u.u_procp->p_flag |= SNOVM;
337 while (rpp->p_flag & SVFORK)
338 sleep((caddr_t)rpp, PZERO - 1);
339 if ((rpp->p_flag & SLOAD) == 0)
340 panic("newproc vfork");
341 uaccess(rpp, Vfmap, &vfutl);
342 u.u_procp->p_xlink = 0;
343 vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap);
344 for (n = 0; n < NOFILE; n++)
345 if (vfutl.u_vrpages[n]) {
346 if ((u.u_vrpages[n] = vfutl.u_vrpages[n] - 1) == 0)
347 if (--u.u_ofile[n]->f_inode->i_vfdcnt < 0)
348 panic("newproc i_vfdcnt");
349 vfutl.u_vrpages[n] = 0;
350 }
351 u.u_procp->p_flag &= ~SNOVM;
352 rpp->p_ndx = rpp - proc;
353 rpp->p_flag |= SVFDONE;
354 wakeup((caddr_t)rpp);
355 }
356 return (0);
357}