|
|
1.1 root 1: /* $Header: /newbits/286_KERNEL/USRSRC/coh/RCS/proc.c,v 1.1 92/01/09 13:29:01 bin Exp Locker: bin $ */
2: /* (lgl-
3: * The information contained herein is a trade secret of Mark Williams
4: * Company, and is confidential information. It is provided under a
5: * license agreement, and may be copied or disclosed only under the
6: * terms of that agreement. Any reproduction or disclosure of this
7: * material without the express written authorization of Mark Williams
8: * Company or persuant to the license agreement is unlawful.
9: *
10: * COHERENT Version 2.3.37
11: * Copyright (c) 1982, 1983, 1984.
12: * An unpublished work by Mark Williams Company, Chicago.
13: * All rights reserved.
14: -lgl) */
15: /*
16: * Coherent.
17: * Process handling and scheduling.
18: *
19: * $Log: proc.c,v $
20: * Revision 1.1 92/01/09 13:29:01 bin
21: * Initial revision
22: *
23: * Revision 1.2 88/08/05 15:30:01 src
24: * pfork() made more rigorous, supports loadable driver forks, etc.
25: * lock/unlock more efficient, since know wakeup is synchronous.
26: *
27: * Revision 1.1 88/03/24 16:14:16 src
28: * Initial revision
29: *
30: * 88/03/10 Allan Cornish /usr/src/sys/coh/proc.c
31: * Numerous temporary fixes due to AMD 286 chip being buggy in protected mode.
32: * These partial fixes will be removed once all CPU's are replaced.
33: *
34: * 88/01/21 Allan Cornish /usr/src/sys/coh/proc.c
35: * Race condition caused by pexit() calling sfree() on the user-area
36: * when the segmentation gate is locked is now prevented.
37: * Release of the user area now deferred until relproc() invoked by uwait().
38: *
39: * 87/11/13 Allan Cornish /usr/src/sys/coh/proc.c
40: * pexit() now sets uasa to 0 before dispatching processor.
41: *
42: * 87/11/05 Allan Cornish /usr/src/sys/coh/proc.c
43: * New seg struct now used to allow extended addressing.
44: *
45: * 87/07/08 Allan Cornish /usr/src/sys/coh/proc.c
46: * pexit() now cancels poll/alarm timed functions before terminating.
47: *
48: * 87/01/05 Allan Cornish /usr/src/sys/coh/proc.c
49: * pexit() now wakes the swapper before terminating.
50: */
51: #include <sys/coherent.h>
52: #include <acct.h>
53: #include <errno.h>
54: #include <sys/inode.h>
55: #include <sys/proc.h>
56: #include <sys/ptrace.h>
57: #include <sys/sched.h>
58: #include <sys/seg.h>
59: #include <signal.h>
60: #include <sys/stat.h>
61: #include <sys/uproc.h>
62:
63: /*
64: * Initialisation.
65: * Set up the hash table queues.
66: */
67: pcsinit()
68: {
69: register PROC *pp;
70: register PLINK *lp;
71:
72: pp = &procq;
73: SELF = pp;
74: procq.p_nforw = pp;
75: procq.p_nback = pp;
76: procq.p_lforw = pp;
77: procq.p_lback = pp;
78: for (lp=&linkq[0]; lp<&linkq[NHPLINK]; lp++) {
79: lp->p_lforw = lp;
80: lp->p_lback = lp;
81: }
82: }
83:
84: /*
85: * Initiate a process. `f' is a kernel function that is associated with
86: * the process.
87: */
88: PROC *
89: process(f)
90: int (*f)();
91: {
92: register PROC *pp1;
93: register PROC *pp;
94: register SEG *sp;
95: MCON mcon;
96:
97: if ((pp=kalloc(sizeof(PROC))) == NULL)
98: return (NULL);
99:
100: pp->p_flags = PFCORE;
101: pp->p_state = PSRUN;
102: pp->p_ttdev = NODEV;
103:
104: if (f != NULL) {
105: pp->p_flags |= PFKERN;
106: sp = salloc((fsize_t)UPASIZE, SFSYST|SFHIGH|SFNSWP);
107: if (sp == NULL) {
108: kfree(pp);
109: return (NULL);
110: }
111: pp->p_segp[SIUSERP] = sp;
112: msetsys( &mcon, f, FP_SEL(sp->s_faddr) );
113: kfcopy( (char *)&mcon,
114: sp->s_faddr + offset(uproc, u_syscon),
115: sizeof(mcon) );
116: }
117: lock(pnxgate);
118: next:
119: pp->p_pid = cpid++;
120: if (cpid >= NPID)
121: cpid = 2;
122: pp1 = &procq;
123: while ((pp1=pp1->p_nforw) != &procq) {
124: if (pp1->p_pid < pp->p_pid)
125: break;
126: if (pp1->p_pid == pp->p_pid)
127: goto next;
128: }
129: pp->p_nback = pp1->p_nback;
130: pp1->p_nback->p_nforw = pp;
131: pp->p_nforw = pp1;
132: pp1->p_nback = pp;
133: unlock(pnxgate);
134: return (pp);
135: }
136:
137: /*
138: * Remove a process from the next queue and release and space.
139: */
140: relproc(pp)
141: register PROC *pp;
142: {
143: register SEG * sp;
144:
145: /*
146: * Child process still has a user-area.
147: */
148: if ( (sp = pp->p_segp[SIUSERP]) != NULL ) {
149:
150: /*
151: * Detach user-area from child process.
152: */
153: pp->p_segp[SIUSERP] = NULL;
154:
155: /*
156: * Child process is swapped out.
157: */
158: if ( pp->p_flags & PFSWAP )
159: sp->s_lrefc++;
160:
161: /*
162: * Release child's user-area.
163: */
164: sfree( sp );
165: }
166:
167: /*
168: * Remove process from doubly-linked list of all processes.
169: * Release space allocated for proc structure.
170: */
171: lock(pnxgate);
172: pp->p_nback->p_nforw = pp->p_nforw;
173: pp->p_nforw->p_nback = pp->p_nback;
174: unlock(pnxgate);
175: kfree(pp);
176: }
177:
178: /*
179: * Create a clone of ourselves.
180: * N.B. - consave(&mcon) returns twice; anything not initialized
181: * in automatic storage before the call to segadup() will not be
182: * initialized when the second return from consave() commences.
183: */
184: pfork()
185: {
186: register PROC *cpp;
187: register PROC *pp;
188: register int s;
189: MCON mcon;
190:
191: if ((cpp=process(NULL)) == NULL) {
192: u.u_error = EAGAIN;
193: return;
194: }
195:
196: s = sphi(); /* Make usave a null macro if unnecessary */
197: usave(); /* Put the current copy of uarea into its segment */
198: spl(s);
199:
200: if (segadup(cpp) == 0) {
201: u.u_error = EAGAIN;
202: relproc(cpp);
203: return;
204: }
205: if ( u.u_rdir != NULL )
206: u.u_rdir->i_refc++;
207: if ( u.u_cdir != NULL )
208: u.u_cdir->i_refc++;
209: fdadupl();
210: pp = SELF;
211: cpp->p_uid = pp->p_uid;
212: cpp->p_ruid = pp->p_ruid;
213: cpp->p_rgid = pp->p_rgid;
214: cpp->p_ppid = pp->p_pid;
215: cpp->p_ttdev = pp->p_ttdev;
216: cpp->p_group = pp->p_group;
217: cpp->p_ssig = pp->p_ssig;
218: cpp->p_isig = pp->p_isig;
219: cpp->p_cval = CVCHILD;
220: cpp->p_ival = IVCHILD;
221: cpp->p_sval = SVCHILD;
222: cpp->p_rval = RVCHILD;
223:
224: s = sphi();
225: consave(&mcon);
226: spl( s );
227:
228: /*
229: * Parent process.
230: */
231: if ( (pp = SELF) != cpp ) {
232: segfinm(cpp->p_segp[SIUSERP]);
233: kfcopy( (char *)&mcon,
234: cpp->p_segp[SIUSERP]->s_faddr + offset(uproc,u_syscon),
235: sizeof(mcon) );
236: mfixcon(cpp);
237: s = sphi();
238: setrun(cpp);
239: spl(s);
240: return( cpp->p_pid );
241: }
242:
243: /*
244: * Child process.
245: */
246: else {
247: u.u_btime = timer.t_time;
248: u.u_flag = AFORK;
249: /* for (i=0; i<NUSEG; i++) done in sproto */
250: /* u.u_segl[i].sr_segp = pp->p_segp[i]; ditto */
251: sproto();
252: segload();
253: return( 0 );
254: }
255: }
256:
257: /*
258: * Die.
259: */
260: pexit(s)
261: {
262: register PROC *pp1;
263: register PROC *pp;
264: register SEG *sp;
265: register int n;
266:
267: pp = SELF;
268:
269: /*
270: * Cancel alarm and poll timers [if any].
271: */
272: timeout( &pp->p_alrmtim, 0, NULL, 0 );
273: timeout( &pp->p_polltim, 0, NULL, 0 );
274:
275: /*
276: * Write out accounting directory and close all files associated with
277: * this process.
278: */
279: setacct();
280: if ( u.u_rdir )
281: ldetach(u.u_rdir);
282: if ( u.u_cdir )
283: ldetach(u.u_cdir);
284: fdaclose();
285:
286: /*
287: * Free all segments in reverse order, except for user-area.
288: */
289: for ( n = NUSEG; --n > 0; ) {
290: if ( (sp = pp->p_segp[n]) != NULL ) {
291: pp->p_segp[n] = NULL;
292: sfree( sp );
293: }
294: }
295:
296: /*
297: * Wakeup our parent. If we have any children, init will become the
298: * new parent. If there are any children we are tracing who are
299: * waiting for us, we wake them up.
300: */
301: pp1 = &procq;
302: while ((pp1=pp1->p_nforw) != &procq) {
303: if (pp1->p_pid == pp->p_ppid) {
304: if (pp1->p_state==PSSLEEP && pp1->p_event==(char *)pp1)
305: wakeup((char *)pp1);
306: }
307: if (pp1->p_ppid == pp->p_pid) {
308: pp1->p_ppid = 1;
309: if (pp1->p_state == PSDEAD)
310: wakeup((char *)eprocp);
311: if ((pp1->p_flags&PFTRAC) != 0)
312: wakeup((char *)&pts.pt_req);
313: }
314: }
315:
316: /*
317: * Wake up swapper if swap timer is active.
318: */
319: if ( stimer.t_last != 0 )
320: wakeup( (char *) &stimer );
321:
322: /*
323: * And finally mark us as dead and give up the processor forever.
324: */
325: pp->p_exit = s;
326: pp->p_state = PSDEAD;
327: uasa = 0;
328: dispatch();
329: }
330:
331: /*
332: * Sleep on the event `e'. This gives up the processor until someone
333: * wakes us up. Since it is possible for many people to sleep on the
334: * same event, the caller when awakened should make sure that what he
335: * was waiting for has completed and if not, go to sleep again. `cl'
336: * is the cpu value we get to get the cpu as soon as we are woken up.
337: * `sl' is the swap value we get to keep us in memory for the duration
338: * of the sleep. `sr' is the swap value that allows us to get swapped
339: * in if we have been swapped out.
340: */
341: sleep(e, cl, sl, sr)
342: char *e;
343: {
344: register PROC *bp;
345: register PROC *fp;
346: register PROC *pp;
347: register int s;
348:
349: pp = SELF;
350:
351: /*
352: * See if we have a signal awaiting.
353: */
354: if (cl<CVNOSIG && pp->p_ssig && nondsig()) {
355: sphi();
356: envrest(&u.u_sigenv);
357: }
358:
359: /*
360: * Get ready to go to sleep and do so.
361: */
362: s = sphi();
363: pp->p_state = PSSLEEP;
364: pp->p_event = e;
365: pp->p_lctim = utimer;
366: addu(pp->p_cval, cl);
367: pp->p_ival = sl;
368: pp->p_rval = sr;
369: fp = &linkq[hash(e)];
370: bp = fp->p_lback;
371: pp->p_lforw = fp;
372: fp->p_lback = pp;
373: pp->p_lback = bp;
374: bp->p_lforw = pp;
375: spl(s);
376: dispatch();
377:
378: /*
379: * We have just woken up. Get ready to return.
380: */
381: subu(pp->p_cval, cl);
382: pp->p_ival = 0;
383: pp->p_rval = 0;
384:
385: /*
386: * Check for an interrupted system call.
387: */
388: if (cl<CVNOSIG && pp->p_ssig && nondsig()) {
389: sphi();
390: envrest(&u.u_sigenv);
391: }
392: }
393:
394: /*
395: * Defer function to wake up all processes sleeping on the event `e'.
396: */
397: wakeup(e)
398: char *e;
399: {
400: extern void dwakeup();
401:
402: defer( dwakeup, e );
403: }
404:
405: /*
406: * Wake up all processes sleeping on the event `e'.
407: */
408: static void
409: dwakeup( e )
410: char *e;
411: {
412: register PROC *pp;
413: register PROC *pp1;
414: register int s;
415:
416: /*
417: * Identify event queue to check.
418: * Disable interrupts.
419: */
420: pp1 = &linkq[hash(e)];
421: pp = pp1;
422: s = sphi();
423:
424: /*
425: * Traverse doubly-linked circular event-queue.
426: */
427: while ( (pp = pp->p_lforw) != pp1 ) {
428:
429: /*
430: * Process is waiting on event 'e'.
431: */
432: if ( pp->p_event == e ) {
433: /*
434: * Remove process from event queue.
435: * Update process priority.
436: * Insert process into run queue.
437: */
438: pp->p_lback->p_lforw = pp->p_lforw;
439: pp->p_lforw->p_lback = pp->p_lback;
440: addu( pp->p_cval, (utimer-pp->p_lctim)*CVCLOCK );
441: setrun( pp );
442:
443: /*
444: * Enable interrupts.
445: * Restart search at start of event queue.
446: * Disable interrupts.
447: */
448: spl( s );
449: pp = pp1;
450: s = sphi();
451: }
452: }
453: spl(s);
454: }
455:
456: /*
457: * Reschedule the processor.
458: */
459: dispatch()
460: {
461: register PROC *pp1;
462: register PROC *pp2;
463: register unsigned v;
464: register int s;
465:
466: s = sphi();
467: pp1 = iprocp;
468: pp2 = &procq;
469: v = 0;
470: while ((pp2=pp2->p_lforw) != &procq) {
471: v -= pp2->p_cval;
472: if ((pp2->p_flags&PFCORE) == 0)
473: continue;
474: pp1 = pp2->p_lforw;
475: pp1->p_cval += pp2->p_cval;
476: pp2->p_cval = v;
477: pp1->p_lback = pp2->p_lback;
478: pp1->p_lback->p_lforw = pp1;
479: pp1 = pp2;
480: break;
481: }
482: spl(s);
483:
484: quantum = NCRTICK;
485: disflag = 0;
486: if ( pp1 != SELF ) {
487: /*
488: * Consave() returns twice.
489: * 1st time is after our context is saved in u.u_syscon,
490: * whereupon we should restore other proc's context.
491: * 2nd time is after our context is restored by another proc.
492: * Conrest() forces a context switch to a new process.
493: */
494: s = sphi();
495: SELF = pp1;
496: if (consave(&u.u_syscon) == 0)
497: conrest( FP_SEL(pp1->p_u->s_faddr),
498: offset(uproc,u_syscon) );
499: if ( SELF->p_pid != 0 )
500: segload();
501: spl(s);
502: }
503: }
504:
505: /*
506: * Add a process to the run queue.
507: * This routine must be called at high priority.
508: */
509: setrun(pp1)
510: register PROC *pp1;
511: {
512: register PROC *pp2;
513: register unsigned v;
514:
515: v = 0;
516: pp2 = &procq;
517: for (;;) {
518: pp2 = pp2->p_lback;
519: if ((v+=pp2->p_lforw->p_cval) >= pp1->p_cval)
520: break;
521: if (pp2 == &procq)
522: break;
523: }
524: pp2->p_lforw->p_lback = pp1;
525: pp1->p_lforw = pp2->p_lforw;
526: pp2->p_lforw = pp1;
527: pp1->p_lback = pp2;
528: v -= pp1->p_cval;
529: pp1->p_cval = v;
530: pp1->p_lforw->p_cval -= v;
531: pp1->p_state = PSRUN;
532: }
533:
534: /*
535: * Wait for the gate `g' to unlock, and then lock it.
536: */
537: lock(g)
538: register GATE g;
539: {
540: register int s;
541:
542: s = sphi();
543: while (g[0]) {
544: g[1] = 1;
545: sleep((char *)g, CVGATE, IVGATE, SVGATE);
546: }
547: g[0] = 1;
548: spl(s);
549: }
550:
551: /*
552: * Unlock the gate `g'.
553: */
554: unlock(g)
555: register GATE g;
556: {
557: g[0] = 0;
558: if (g[1]) {
559: g[1] = 0;
560: disflag = 1;
561: wakeup((char *)g);
562: }
563: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.