|
|
1.1 root 1: /* (lgl-
2: * The information contained herein is a trade secret of Mark Williams
3: * Company, and is confidential information. It is provided under a
4: * license agreement, and may be copied or disclosed only under the
5: * terms of that agreement. Any reproduction or disclosure of this
6: * material without the express written authorization of Mark Williams
7: * Company or persuant to the license agreement is unlawful.
8: *
9: * COHERENT Version 2.3.37
10: * Copyright (c) 1982, 1983, 1984.
11: * An unpublished work by Mark Williams Company, Chicago.
12: * All rights reserved.
13: -lgl) */
14: /*
15: * Coherent.
16: * Process handling and scheduling.
17: *
18: * $Log: proc.c,v $
19: * Revision 1.2 92/08/04 12:34:18 bin
20: * changed for ker 59
21: *
22: * Revision 1.5 92/04/03 14:35:36 hal
23: * Kernel #49: piggy trace variable.
24: *
25: * Revision 1.4 92/02/03 17:00:09 piggy
26: * Send SIGHUP to all group members on death of group leader.
27: */
28: #include <sys/coherent.h>
29: #include <acct.h>
30: #include <errno.h>
31: #include <sys/inode.h>
32: #include <sys/proc.h>
33: #include <sys/ptrace.h>
34: #include <sys/sched.h>
35: #include <sys/seg.h>
36: #include <signal.h>
37: #include <sys/stat.h>
38:
39: /*
40: * Initialization.
41: * Set up the hash table queues.
42: */
43: pcsinit()
44: {
45: register PROC *pp;
46: register PLINK *lp;
47:
48: /*
49: * Explicitly initialize everything in the first process.
50: */
51: pp = &procq;
52: SELF = pp;
53: procq.p_nforw = pp;
54: procq.p_nback = pp;
55: procq.p_lforw = pp;
56: procq.p_lback = pp;
57:
58: #ifdef _I386
59: /* Segments are initialized in mchinit() and eveinit(). */
60:
61: procq.p_uid = 0; /* Effective uid */
62: procq.p_ruid = 0; /* Real uid */
63: procq.p_rgid = 0; /* Real gid */
64: procq.p_state = 0; /* Scheduling state */
65: procq.p_flags = 0; /* Flags */
66: procq.p_ssig = (sig_t) 0; /* Signals which have been set */
67: #ifdef _I386
68: procq.p_dfsig = (sig_t) 0xffffffff; /* All signals are defaulted. */
69: procq.p_hsig = (sig_t) 0; /* Signals which are being held */
70: procq.p_dsig = (sig_t) 0; /* Signals which are being deferred */
71: #endif
72: procq.p_isig = (sig_t) 0; /* Signals which are being ignored */
73: procq.p_event = NULL; /* Wakeup event channel */
74: procq.p_alarm = 0; /* Timer for alarms */
75: procq.p_group = 0; /* Process group */
76: /*
77: * Set ttdev to null so that we do not accidentally set a tty for init.
78: */
79: procq.p_ttdev = makedev(0,0); /* Controlling terminal */
80: procq.p_nice = 0; /* Nice value */
81: procq.p_cval = 0; /* Cpu schedule value */
82: procq.p_sval = 0; /* Swap schedule value */
83: procq.p_ival = 0; /* Importance value */
84: procq.p_rval = 0; /* Response value */
85: procq.p_lctim = 0; /* Last time cval was updated */
86: procq.p_utime = 0L; /* User time (HZ) */
87: procq.p_stime = 0L; /* System time */
88: procq.p_cutime = 0L; /* Sum of childs user time */
89: procq.p_cstime = 0L; /* Sum of childs system time */
90: procq.p_exit = 0; /* Exit status */
91: procq.p_polls = NULL; /* Enabled polls */
92: /* Poll timer */
93: procq.p_polltim.t_next = NULL;
94: procq.p_polltim.t_last = NULL;
95: procq.p_polltim.t_lbolt = 0L;
96: procq.p_polltim.t_func = NULL;
97: procq.p_polltim.t_farg = NULL;
98: #ifndef _I386
99: procq.p_polltim.t_ldrv = 0;
100: #endif /* _I386 */
101:
102: /* Alarm timer */
103: procq.p_alrmtim.t_next = NULL;
104: procq.p_alrmtim.t_last = NULL;
105: procq.p_alrmtim.t_lbolt = 0L;
106: procq.p_alrmtim.t_func = NULL;
107: procq.p_alrmtim.t_farg = NULL;
108: #ifndef _I386
109: procq.p_alrmtim.t_ldrv = 0;
110: #endif /* _I386 */
111:
112: procq.p_prl = NULL; /* Pending record lock */
113: #endif /* _I386 */
114:
115: for (lp=&linkq[0]; lp<&linkq[NHPLINK]; lp++) {
116: lp->p_lforw = lp;
117: lp->p_lback = lp;
118: }
119: }
120:
121: /*
122: * Initiate a process.
123: */
124: PROC *
125: #ifdef _I386
126: process()
127: #else
128: process(f)
129: int (*f)();
130: #endif
131: {
132: register PROC *pp1;
133: register PROC *pp;
134: register SEG *sp;
135: MCON mcon;
136:
137: if ((pp=kalloc(sizeof(PROC))) == NULL)
138: return (NULL);
139:
140: pp->p_flags = PFCORE;
141: pp->p_state = PSRUN;
142: pp->p_ttdev = NODEV;
143: #ifndef _I386
144: /*
145: * What is this, and why is it 286 only?
146: */
147: if (f != NULL) {
148: pp->p_flags |= PFKERN;
149: sp = salloc((fsize_t)UPASIZE, SFSYST|SFHIGH|SFNSWP);
150: if (sp == NULL) {
151: kfree(pp);
152: return (NULL);
153: }
154: pp->p_segp[SIUSERP] = sp;
155: msetsys(&mcon, f, FP_SEL(sp->s_faddr));
156: kfcopy( (char *)&mcon,
157: sp->s_faddr + offset(uproc, u_syscon),
158: sizeof(mcon));
159: }
160: #endif
161: lock(pnxgate);
162: next:
163:
164: /*
165: * Pick the next process id.
166: */
167: /* DO NOT MESS WITH THE FOLLOWING CONDITIONAL UNLESS YOU
168: TEST THE RESULTS ON BOTH 286 AND 386 */
169: #ifdef _I386
170: if (++cpid >= NPID)
171: cpid = 2;
172: pp->p_pid = cpid;
173: #else
174: pp->p_pid = cpid++;
175: if (cpid >= NPID)
176: cpid = 2;
177: #endif
178:
179: /*
180: * Make sure that process id is not in use.
181: */
182: pp1 = &procq;
183: while ((pp1=pp1->p_nforw) != &procq) {
184: if (pp1->p_pid < pp->p_pid)
185: break;
186: if (pp1->p_pid == pp->p_pid)
187: goto next;
188: }
189:
190: /*
191: * We've got a valid pid, so let's put this process into
192: * the process table.
193: */
194: pp->p_nback = pp1->p_nback;
195: pp1->p_nback->p_nforw = pp;
196: pp->p_nforw = pp1;
197: pp1->p_nback = pp;
198: unlock(pnxgate);
199: return (pp);
200: }
201:
202: /*
203: * Remove a process from the next queue and release and space.
204: */
205: relproc(pp)
206: register PROC *pp;
207: {
208: register SEG * sp;
209:
210: /*
211: * Child process still has a user-area.
212: */
213: if ((sp = pp->p_segp[SIUSERP]) != NULL) {
214:
215: /*
216: * Detach user-area from child process.
217: */
218: pp->p_segp[SIUSERP] = NULL;
219:
220: /*
221: * Child process is swapped out.
222: */
223: if (pp->p_flags & PFSWAP)
224: sp->s_lrefc++;
225:
226: /*
227: * Release child's user-area.
228: */
229: sfree(sp);
230: }
231:
232: /*
233: * Remove process from doubly-linked list of all processes.
234: * Release space allocated for proc structure.
235: */
236: lock(pnxgate);
237: pp->p_nback->p_nforw = pp->p_nforw;
238: pp->p_nforw->p_nback = pp->p_nback;
239: unlock(pnxgate);
240: kfree(pp);
241: }
242:
243: /*
244: * Create a clone of ourselves.
245: * N.B. - consave(&mcon) returns twice; anything not initialized
246: * in automatic storage before the call to segadup() will not be
247: * initialized when the second return from consave() commences.
248: */
249: pfork()
250: {
251: register PROC *cpp;
252: register PROC *pp;
253: register int s;
254: MCON mcon;
255:
256: #ifdef _I386
257: if ((cpp=process()) == NULL) {
258: #else
259: if ((cpp=process(NULL)) == NULL) {
260: #endif
261: SET_U_ERROR( EAGAIN, "no more process table entries" );
262: return -1;
263: }
264:
265: #ifndef _I386
266: s = sphi();
267: usave(); /* Put the current copy of uarea into its segment */
268: spl(s);
269: #endif
270:
271: pp = SELF;
272: s = sphi(); /* put current interrupt level into s before segadup */
273: spl(s);
274: /*
275: * As stated above, no auto variable may be changed between calls
276: * to segadup() and consave().
277: */
278: if (segadup(cpp) == 0) {
279: SET_U_ERROR( EAGAIN, "can not duplicate segments" );
280: relproc(cpp);
281: return -1;
282: }
283: if (u.u_rdir != NULL)
284: u.u_rdir->i_refc++;
285: if (u.u_cdir != NULL)
286: u.u_cdir->i_refc++;
287: fdadupl();
288: cpp->p_uid = pp->p_uid;
289: cpp->p_ruid = pp->p_ruid;
290: cpp->p_rgid = pp->p_rgid;
291: cpp->p_ppid = pp->p_pid;
292: cpp->p_ttdev = pp->p_ttdev;
293: cpp->p_group = pp->p_group;
294: cpp->p_ssig = pp->p_ssig;
295: #ifdef _I386
296: cpp->p_dfsig = pp->p_dfsig;
297: cpp->p_dsig = pp->p_dsig;
298: cpp->p_hsig = pp->p_hsig;
299: #endif /* _I386 */
300: cpp->p_isig = pp->p_isig;
301: cpp->p_cval = CVCHILD;
302: cpp->p_ival = IVCHILD;
303: cpp->p_sval = SVCHILD;
304: cpp->p_rval = RVCHILD;
305: #ifdef _I386
306: cpp->p_prl = NULL;
307: #endif
308:
309: sphi(); /* s = sphi() was done before segadup() */
310: consave(&mcon);
311: spl(s);
312:
313: /*
314: * Parent process.
315: */
316: if ((pp = SELF) != cpp) {
317: segfinm(cpp->p_segp[SIUSERP]);
318: #ifdef _I386
319: dmaout(sizeof(mcon),
320: MAPIO(cpp->p_segp[SIUSERP]->s_vmem,offset(uproc,u_syscon)),
321: (char *)&mcon);
322: #else
323: kfcopy((char *)&mcon,
324: cpp->p_segp[SIUSERP]->s_faddr + offset(uproc,u_syscon),
325: sizeof(mcon));
326: #endif
327: mfixcon(cpp);
328: s = sphi();
329: setrun(cpp);
330: spl(s);
331: #ifdef _I386
332: u.u_rval2 = 0;
333: #endif
334: return(cpp->p_pid);
335: }
336:
337: /*
338: * Child process.
339: */
340: else {
341: u.u_btime = timer.t_time;
342: u.u_flag = AFORK;
343: #ifdef _I386
344: #ifdef UPROC_VERSION
345: u.u_version = UPROC_VERSION;
346: #endif /* UPROC_VERSION */
347: u.u_sleep[0] = '\0'; /* We are not sleeping to start with. */
348: sproto(0);
349: #else
350: sproto();
351: #endif
352: segload();
353: #ifdef _I386
354: u.u_rval2 = SELF->p_ppid;
355: #endif
356: return 0;
357: }
358: }
359:
360: /*
361: * Die.
362: */
363: pexit(s)
364: {
365: register PROC *pp1;
366: register PROC *pp;
367: register SEG *sp;
368: register int n;
369: PROC *parent;
370:
371: pp = SELF;
372:
373: T_PIGGY( 0x1, printf("%s:pexit(%x)", u.u_comm, s); );
374: /*
375: * Cancel alarm and poll timers [if any].
376: */
377: timeout(&pp->p_alrmtim, 0, NULL, 0);
378: timeout(&pp->p_polltim, 0, NULL, 0);
379:
380: /*
381: * Write out accounting directory and close all files associated with
382: * this process.
383: */
384: setacct();
385: if (u.u_rdir)
386: ldetach(u.u_rdir);
387: if (u.u_cdir)
388: ldetach(u.u_cdir);
389: fdaclose();
390:
391: /*
392: * Free all segments in reverse order, except for user-area.
393: */
394: for (n = NUSEG; --n > 0;) {
395: if ((sp = pp->p_segp[n]) != NULL) {
396: pp->p_segp[n] = NULL;
397: sfree(sp);
398: }
399: }
400:
401: /*
402: * Wakeup our parent. If we have any children, init will become the
403: * new parent. If there are any children we are tracing who are
404: * waiting for us, we wake them up.
405: */
406: pp1 = &procq;
407: while ((pp1=pp1->p_nforw) != &procq) {
408: if (pp1->p_pid == pp->p_ppid) {
409: parent = pp1; /* Remember our parent. */
410: if (pp1->p_state==PSSLEEP && pp1->p_event==(char *)pp1)
411: wakeup((char *)pp1);
412: }
413: if (pp1->p_ppid == pp->p_pid) {
414: pp1->p_ppid = 1;
415: if (pp1->p_state == PSDEAD)
416: wakeup((char *)eprocp);
417: if ((pp1->p_flags&PFTRAC) != 0)
418: wakeup((char *)&pts.pt_req);
419: }
420: }
421:
422: /*
423: * Wake up swapper if swap timer is active.
424: */
425: if (stimer.t_last != 0)
426: wakeup((char *) &stimer);
427:
428: /*
429: * Mark us as dead and give up the processor forever.
430: */
431: pp->p_exit = s;
432: pp->p_state = PSDEAD;
433:
434: #ifdef _I386
435: /*
436: * If this is a process group leader, inform all members of the group
437: * of the recent death with a HUP signal.
438: */
439: if (pp->p_group == pp->p_pid) {
440: ukill(-pp->p_pid, SIGHUP);
441: }
442: #else
443: uasa = 0;
444: #endif
445:
446: #ifdef _I386
447: T_PIGGY( 0x100, printf("<CHLD pid: %d ppid: %d>",
448: pp->p_pid, parent->p_pid); );
449:
450: /*
451: * If the parent is ignoring SIGCHLD,
452: * remove the zombie right away.
453: */
454: # define CHLDBIT (((sig_t) 1) << (SIGCHLD - 1))
455: if (CHLDBIT & parent->p_isig) {
456: parent->p_cutime += pp->p_utime + pp->p_cutime;
457: parent->p_cstime += pp->p_stime + pp->p_cstime;
458: relproc(pp);
459: } else {
460: /*
461: * If SIGCHLD is not defaulted, notify our parent
462: * of our demise.
463: */
464: if (!(CHLDBIT & parent->p_dfsig)) {
465: sendsig(SIGCHLD, parent );
466: }
467: }
468: #endif /* _I386 */
469:
470: dispatch();
471: }
472:
473: #ifdef _I386
474: /*
475: * Sleep verbosely. Put a short string describing our reason for sleeping
476: * into our U area, and then go to sleep.
477: */
478: v_sleep(e, cl, sl, sr, msg)
479: char *e;
480: int cl, sl, sr;
481: char *msg;
482: {
483: int i;
484:
485: /*
486: * The descriptive string may be at most 10 characters long.
487: * It will only be NUL terminated if it has 9 or fewer characters.
488: */
489: for (i = 0; i < 10; ++i) {
490: if ('\0' == (u.u_sleep[i] = msg[i])) {
491: break;
492: }
493: }
494:
495: sleep(e, cl, sl, sr);
496: } /* v_sleep() */
497: #endif
498:
499: /*
500: * Sleep on the event `e'. This gives up the processor until someone
501: * wakes us up. Since it is possible for many people to sleep on the
502: * same event, the caller when awakened should make sure that what he
503: * was waiting for has completed and if not, go to sleep again. `cl'
504: * is the cpu value we get to get the cpu as soon as we are woken up.
505: * `sl' is the swap value we get to keep us in memory for the duration
506: * of the sleep. `sr' is the swap value that allows us to get swapped
507: * in if we have been swapped out.
508: */
509: sleep(e, cl, sl, sr)
510: char *e;
511: {
512: register PROC *bp;
513: register PROC *fp;
514: register PROC *pp;
515: register int s;
516:
517: pp = SELF;
518:
519: /*
520: * See if we have a signal awaiting.
521: */
522: if (cl<CVNOSIG && pp->p_ssig && nondsig()) {
523: sphi();
524: envrest(&u.u_sigenv);
525: }
526:
527: /*
528: * Get ready to go to sleep and do so.
529: */
530: s = sphi();
531: pp->p_state = PSSLEEP;
532: pp->p_event = e;
533: pp->p_lctim = utimer;
534: addu(pp->p_cval, cl);
535: pp->p_ival = sl;
536: pp->p_rval = sr;
537: fp = &linkq[hash(e)];
538: bp = fp->p_lback;
539: pp->p_lforw = fp;
540: fp->p_lback = pp;
541: pp->p_lback = bp;
542: bp->p_lforw = pp;
543: spl(s);
544: dispatch();
545:
546: /*
547: * We have just woken up. Get ready to return.
548: */
549: subu(pp->p_cval, cl);
550: pp->p_ival = 0;
551: pp->p_rval = 0;
552:
553: /*
554: * Since we are no longer asleep, we no longer need
555: * to publish a reason for sleeping.
556: */
557: #ifdef _I386
558: u.u_sleep[0] = '\0';
559: #endif
560:
561: /*
562: * Check for an interrupted system call.
563: */
564: if (cl<CVNOSIG && pp->p_ssig && nondsig()) {
565: sphi();
566: envrest(&u.u_sigenv);
567: }
568: }
569:
570: /*
571: * Defer function to wake up all processes sleeping on the event `e'.
572: */
573: wakeup(e)
574: char *e;
575: {
576: void dwakeup();
577:
578: #ifdef TRACER
579: /*
580: * In diagnostic kernel, keep return addr on queue as well.
581: */
582: int *r=(int*)(&e);
583: defer0(dwakeup, e, *(r-1));
584: #else
585: defer(dwakeup, e);
586: #endif
587: }
588:
589: /*
590: * Wake up all processes sleeping on the event `e'.
591: */
592: void
593: dwakeup(e)
594: char *e;
595: {
596: register PROC *pp;
597: register PROC *pp1;
598: register int s;
599:
600: /*
601: * Identify event queue to check.
602: * Disable interrupts.
603: */
604: pp1 = &linkq[hash(e)];
605: pp = pp1;
606: s = sphi();
607:
608: /*
609: * Traverse doubly-linked circular event-queue.
610: */
611: while ((pp = pp->p_lforw) != pp1) {
612:
613: /*
614: * Process is waiting on event 'e'.
615: */
616: if (pp->p_event == e) {
617: /*
618: * Remove process from event queue.
619: * Update process priority.
620: * Insert process into run queue.
621: */
622: pp->p_lback->p_lforw = pp->p_lforw;
623: pp->p_lforw->p_lback = pp->p_lback;
624: addu(pp->p_cval, (utimer-pp->p_lctim)*CVCLOCK);
625: setrun(pp);
626:
627: /*
628: * Enable interrupts.
629: * Restart search at start of event queue.
630: * Disable interrupts.
631: */
632: spl(s);
633: pp = pp1;
634: s = sphi();
635: }
636: }
637: spl(s);
638: }
639:
640: /*
641: * Reschedule the processor.
642: */
643: dispatch()
644: {
645: register PROC *pp1;
646: register PROC *pp2;
647: register unsigned v;
648: register int s;
649:
650: s = sphi();
651: pp1 = iprocp;
652: pp2 = &procq;
653: v = 0;
654: while ((pp2=pp2->p_lforw) != &procq) {
655: v -= pp2->p_cval;
656: if ((pp2->p_flags&PFCORE) == 0)
657: continue;
658: pp1 = pp2->p_lforw;
659: pp1->p_cval += pp2->p_cval;
660: pp2->p_cval = v;
661: pp1->p_lback = pp2->p_lback;
662: pp1->p_lback->p_lforw = pp1;
663: pp1 = pp2;
664: break;
665: }
666: spl(s);
667:
668: quantum = NCRTICK;
669: disflag = 0;
670: if (pp1 != SELF) {
671: /*
672: * Consave() returns twice.
673: * 1st time is after our context is saved in u.u_syscon,
674: * whereupon we should restore other proc's context.
675: * 2nd time is after our context is restored by another proc.
676: * Conrest() forces a context switch to a new process.
677: */
678: s = sphi();
679: SELF = pp1;
680: if (consave(&u.u_syscon) == 0) {
681: #ifdef _I386
682: conrest(*pp1->p_segp[SIUSERP]->s_vmem, &u.u_syscon);
683: #else
684: conrest(
685: FP_SEL(pp1->p_u->s_faddr), offset(uproc,u_syscon));
686: #endif
687: }
688: if (SELF->p_pid != 0)
689: segload();
690: spl(s);
691: }
692: }
693:
694: /*
695: * Add a process to the run queue.
696: * This routine must be called at high priority.
697: */
698: setrun(pp1)
699: register PROC *pp1;
700: {
701: register PROC *pp2;
702: register unsigned v;
703:
704: v = 0;
705: pp2 = &procq;
706: for (;;) {
707: pp2 = pp2->p_lback;
708: if ((v+=pp2->p_lforw->p_cval) >= pp1->p_cval)
709: break;
710: if (pp2 == &procq)
711: break;
712: }
713: pp2->p_lforw->p_lback = pp1;
714: pp1->p_lforw = pp2->p_lforw;
715: pp2->p_lforw = pp1;
716: pp1->p_lback = pp2;
717: v -= pp1->p_cval;
718: pp1->p_cval = v;
719: pp1->p_lforw->p_cval -= v;
720: pp1->p_state = PSRUN;
721: }
722:
723: /*
724: * Wait for the gate `g' to unlock, and then lock it.
725: */
726: lock(g)
727: register GATE g;
728: {
729: register int s;
730:
731: s = sphi();
732: while (g[0]) {
733: g[1] = 1;
734: v_sleep((char *)g, CVGATE, IVGATE, SVGATE, "lock");
735: /* Waiting for a gate to unlock. */
736: }
737: g[0] = 1;
738: spl(s);
739: }
740:
741: /*
742: * Unlock the gate `g'.
743: */
744: unlock(g)
745: register GATE g;
746: {
747: g[0] = 0;
748: if (g[1]) {
749: g[1] = 0;
750: disflag = 1;
751: wakeup((char *)g);
752: }
753: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.