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