|
|
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 3.x, 4.x
10: * Copyright (c) 1982, 1993.
11: * An unpublished work by Mark Williams Company, Chicago.
12: * All rights reserved.
13: -lgl) */
14: /*
15: * Process handling and scheduling.
16: */
17: #include <sys/coherent.h>
18: #include <sys/acct.h>
19: #include <errno.h>
20: #include <sys/inode.h>
21: #include <sys/ptrace.h>
22: #include <sys/sched.h>
23: #include <signal.h>
24: #include <sys/stat.h>
25:
26: /*
27: * Initialization.
28: * Set up the hash table queues.
29: */
30: pcsinit()
31: {
32: register PROC *pp;
33: register PLINK *lp;
34:
35: /*
36: * Explicitly initialize everything in the first process.
37: */
38: pp = &procq;
39: SELF = pp;
40: procq.p_nforw = pp;
41: procq.p_nback = pp;
42: procq.p_lforw = pp;
43: procq.p_lback = pp;
44:
45: /* Segments are initialized in mchinit() and eveinit(). */
46: /* procq is static, so p_shmsr[] initializes to nulls. */
47:
48: procq.p_uid = 0; /* Effective uid */
49: procq.p_ruid = 0; /* Real uid */
50: procq.p_rgid = 0; /* Real gid */
51: procq.p_state = 0; /* Scheduling state */
52: procq.p_flags = 0; /* Flags */
53: procq.p_ssig = (sig_t) 0; /* Signals which have been set */
54:
55: procq.p_dfsig = (sig_t) 0xffffffff; /* All signals are defaulted. */
56: procq.p_hsig = (sig_t) 0; /* Signals which are being held */
57: procq.p_dsig = (sig_t) 0; /* Signals which are being deferred */
58:
59: procq.p_isig = (sig_t) 0; /* Signals which are being ignored */
60: procq.p_event = NULL; /* Wakeup event channel */
61: procq.p_alarm = 0; /* Timer for alarms */
62: procq.p_group = 0; /* Process group */
63: /*
64: * Set ttdev to null so that we do not accidentally set a tty for init.
65: */
66: procq.p_ttdev = makedev(0,0); /* Controlling terminal */
67: procq.p_nice = 0; /* Nice value */
68: procq.p_lctim = 0; /* Last time cval was updated */
69: procq.p_utime = 0L; /* User time (HZ) */
70: procq.p_stime = 0L; /* System time */
71: procq.p_cutime = 0L; /* Sum of childs user time */
72: procq.p_cstime = 0L; /* Sum of childs system time */
73: procq.p_exit = 0; /* Exit status */
74: procq.p_polls = NULL; /* Enabled polls */
75: /* Poll timer */
76: procq.p_polltim.t_next = NULL;
77: procq.p_polltim.t_last = NULL;
78: procq.p_polltim.t_lbolt = 0L;
79: procq.p_polltim.t_func = NULL;
80: procq.p_polltim.t_farg = NULL;
81:
82: /* Alarm timer */
83: procq.p_alrmtim.t_next = NULL;
84: procq.p_alrmtim.t_last = NULL;
85: procq.p_alrmtim.t_lbolt = 0L;
86: procq.p_alrmtim.t_func = NULL;
87: procq.p_alrmtim.t_farg = NULL;
88:
89: procq.p_prl = NULL; /* Pending record lock */
90: procq.p_semu = NULL; /* Semaphore undo */
91: for (lp=&linkq[0]; lp<&linkq[NHPLINK]; lp++) {
92: lp->p_lforw = lp;
93: lp->p_lback = lp;
94: }
95: }
96:
97: /*
98: * Initiate a process.
99: */
100: PROC *
101: process()
102: {
103: register PROC *pp1;
104: register PROC *pp;
105:
106: if ((pp=kalloc(sizeof(PROC))) == NULL)
107: return (NULL);
108:
109: pp->p_flags = PFCORE;
110: pp->p_state = PSRUN;
111: pp->p_ttdev = NODEV;
112: pp->p_semu = NULL; /* Semaphore undo */
113:
114: lock(pnxgate);
115: next:
116:
117: /*
118: * Pick the next process id.
119: */
120: if (++cpid >= NPID)
121: cpid = 2;
122: pp->p_pid = cpid;
123:
124: /*
125: * Make sure that process id is not in use.
126: */
127: pp1 = &procq;
128: while ((pp1=pp1->p_nforw) != &procq) {
129: if (pp1->p_pid < pp->p_pid)
130: break;
131: if (pp1->p_pid == pp->p_pid)
132: goto next;
133: }
134:
135: /*
136: * We've got a valid pid, so let's put this process into
137: * the process table.
138: */
139: pp->p_nback = pp1->p_nback;
140: pp1->p_nback->p_nforw = pp;
141: pp->p_nforw = pp1;
142: pp1->p_nback = pp;
143: unlock(pnxgate);
144: return (pp);
145: }
146:
147: /*
148: * Remove a process from the next queue and release and space.
149: */
150: relproc(pp)
151: register PROC *pp;
152: {
153: register SEG * sp;
154:
155: /*
156: * Child process still has a user-area.
157: */
158: if (sp = pp->p_segp[SIUSERP]) {
159:
160: /*
161: * Detach user-area from child process.
162: */
163: pp->p_segp[SIUSERP] = NULL;
164:
165: /*
166: * Child process is swapped out.
167: */
168: if (pp->p_flags & PFSWAP)
169: sp->s_lrefc++;
170:
171: /*
172: * Release child's user-area.
173: */
174: sfree(sp);
175: }
176:
177: /*
178: * Remove process from doubly-linked list of all processes.
179: * Release space allocated for proc structure.
180: */
181: lock(pnxgate);
182: pp->p_nback->p_nforw = pp->p_nforw;
183: pp->p_nforw->p_nback = pp->p_nback;
184: unlock(pnxgate);
185: kfree(pp);
186: }
187:
188: /*
189: * Create a clone of ourselves.
190: * N.B. - consave(&mcon) returns twice; anything not initialized
191: * in automatic storage before the call to segadup() will not be
192: * initialized when the second return from consave() commences.
193: */
194: pfork()
195: {
196: register PROC *cpp;
197: register PROC *pp;
198: register int s;
199: MCON mcon;
200:
201: if ((cpp=process()) == NULL) {
202: SET_U_ERROR( EAGAIN, "no more process table entries" );
203: return -1;
204: }
205:
206: pp = SELF;
207: s = sphi(); /* put current interrupt level into s before segadup */
208: spl(s);
209: /*
210: * As stated above, no auto variable may be changed between calls
211: * to segadup() and consave().
212: */
213: if (segadup(cpp) == 0) {
214: SET_U_ERROR( EAGAIN, "can not duplicate segments" );
215: relproc(cpp);
216: return -1;
217: }
218: shmDup(cpp); /* copy shared memory info & update ref counts */
219: if (u.u_rdir)
220: u.u_rdir->i_refc++;
221: if (u.u_cdir)
222: u.u_cdir->i_refc++;
223: fdadupl();
224: cpp->p_uid = pp->p_uid;
225: cpp->p_ruid = pp->p_ruid;
226: cpp->p_rgid = pp->p_rgid;
227: cpp->p_ppid = pp->p_pid;
228: cpp->p_ttdev = pp->p_ttdev;
229: cpp->p_group = pp->p_group;
230: cpp->p_ssig = pp->p_ssig;
231:
232: cpp->p_dfsig = pp->p_dfsig;
233: cpp->p_dsig = pp->p_dsig;
234: cpp->p_hsig = pp->p_hsig;
235: cpp->p_prl = NULL;
236:
237: cpp->p_isig = pp->p_isig;
238:
239: sphi(); /* s = sphi() was done before segadup() */
240: consave(&mcon);
241: spl(s);
242:
243: /*
244: * Parent process.
245: */
246: if ((pp = SELF) != cpp) {
247: segfinm(cpp->p_segp[SIUSERP]);
248: dmaout(sizeof(mcon),
249: MAPIO(cpp->p_segp[SIUSERP]->s_vmem,
250: U_OFFSET + offset(uproc,u_syscon)),
251: (char *)&mcon);
252: s = sphi();
253: setrun(cpp);
254: spl(s);
255:
256: u.u_rval2 = 0;
257: return(cpp->p_pid);
258: }
259:
260: /*
261: * Child process.
262: */
263: else {
264: u.u_btime = timer.t_time;
265: u.u_flag = AFORK;
266:
267: #ifdef UPROC_VERSION
268: u.u_version = UPROC_VERSION;
269: #endif /* UPROC_VERSION */
270: u.u_sleep[0] = '\0'; /* We are not sleeping to start with. */
271: sproto(0);
272: segload();
273: u.u_rval2 = SELF->p_ppid;
274: return 0;
275: }
276: }
277:
278: /*
279: * Die.
280: */
281: pexit(s)
282: {
283: register PROC *pp1;
284: register PROC *pp;
285: register SEG *sp;
286: register int n;
287: PROC *parent;
288:
289: pp = SELF;
290: T_PIGGY( 0x1, printf("%s:pexit(%x)", u.u_comm, s); );
291:
292: ndpEndProc();
293:
294: /*
295: * Cancel alarm and poll timers [if any].
296: */
297: timeout(&pp->p_alrmtim, 0, NULL, 0);
298: timeout(&pp->p_polltim, 0, NULL, 0);
299:
300: /*
301: * Write out accounting directory and close all files associated with
302: * this process.
303: */
304: setacct();
305: if (u.u_rdir)
306: ldetach(u.u_rdir);
307: if (u.u_cdir)
308: ldetach(u.u_cdir);
309: fdaclose();
310:
311: /*
312: * Free all segments in reverse order, except for user-area.
313: */
314: for (n = NUSEG; --n > 0;) {
315: if (sp = pp->p_segp[n]) {
316: pp->p_segp[n] = NULL;
317: sfree(sp);
318: }
319: }
320:
321: /* Detach remaining shared memory segments. */
322: shmAllDt();
323:
324: /* Adjust(undo) all semaphores. */
325: semAllAdjust(pp);
326:
327: /*
328: * Wakeup our parent. If we have any children, init will become the
329: * new parent. If there are any children we are tracing who are
330: * waiting for us, we wake them up.
331: */
332: pp1 = &procq;
333:
334: /* pp1 runs through the list of all processes */
335: while ((pp1=pp1->p_nforw) != &procq) {
336:
337: /* if pp1 points to parent of the current process...*/
338: if (pp1->p_pid == pp->p_ppid) {
339: parent = pp1; /* Remember our parent. */
340: if (ASLEEP(pp1) && pp1->p_event==(char *)pp1)
341: wakeup((char *)pp1);
342: }
343:
344: /* if pp1 points to child of the current process...*/
345: if (pp1->p_ppid == pp->p_pid) {
346: pp1->p_ppid = 1;
347: if (pp1->p_state == PSDEAD)
348: wakeup((char *)eprocp);
349: if (pp1->p_flags&PFTRAC)
350: wakeup((char *)&pts.pt_req);
351: }
352: }
353:
354: /*
355: * Mark us as dead and give up the processor forever.
356: */
357: pp->p_exit = s;
358: pp->p_state = PSDEAD;
359:
360: /*
361: * If this is a process group leader, inform all members of the group
362: * of the recent death with a HUP signal.
363: */
364: if (pp->p_group == pp->p_pid) {
365: ukill(-pp->p_pid, SIGHUP);
366: }
367:
368: /*
369: * If the parent is ignoring SIGCLD,
370: * remove the zombie right away.
371: */
372: if (SIG_BIT(SIGCLD) & parent->p_isig) {
373: parent->p_cutime += pp->p_utime + pp->p_cutime;
374: parent->p_cstime += pp->p_stime + pp->p_cstime;
375: relproc(pp);
376: } else {
377: /*
378: * If SIGCLD is not defaulted, notify our parent
379: * of our demise.
380: */
381: if (!(SIG_BIT(SIGCLD) & parent->p_dfsig)) {
382: sendsig(SIGCLD, parent );
383: }
384: }
385:
386: dispatch();
387: }
388:
389: /*
390: * x_sleep()
391: *
392: * Surrender CPU while awaiting some event or resource.
393: *
394: * Arguments:
395: * event: key value; so wakeup() can find this sleep
396: * schedPri: prilo/primed/prihi/pritape/pritty/pridisk/prinet
397: * just copied into proc struct for scheduler to use.
398: * (see sys/v_types.h)
399: * sleepPri: slpriNoSig - signals may not interrupt sleep
400: * slpriSigLjmp - signals cause longjmp (EINTR)
401: * slpriSigCatch - signals are caught
402: * (see sys/sched.h)
403: * reason: up to 10 chars of text for ps command "event"
404: *
405: * Return values:
406: * 0 wakeup received
407: * 1 signal (other than SIGSTOP/SIGCONT) received
408: * 2 SIGSTOP/SIGCONT (unimplemented now)
409: *
410: * If longjmp occurs, won't return from x_sleep!
411: */
412: int
413: x_sleep(event, schedPri, sleepPri, reason)
414: char * event;
415: int schedPri;
416: int sleepPri;
417: char * reason;
418: {
419: int i;
420: register PROC *bp;
421: register PROC *fp;
422: register PROC *pp;
423: register int s;
424:
425: /*
426: * The descriptive string may be at most 10 characters long.
427: * It will only be NUL terminated if it has 9 or fewer characters.
428: */
429: for (i = 0; i < U_SLEEP_LEN; ++i) {
430: if ('\0' == (u.u_sleep[i] = reason[i])) {
431: break;
432: }
433: }
434:
435: pp = SELF;
436:
437: /*
438: * Get ready to go to sleep and do so.
439: */
440: s = sphi();
441: pp->p_state = (sleepPri == slpriNoSig) ? PSSLEEP : PSSLSIG;
442: pp->p_schedPri = schedPri;
443: pp->p_event = event;
444: pp->p_lctim = utimer;
445: fp = &linkq[hash(event)];
446: bp = fp->p_lback;
447: pp->p_lforw = fp;
448: fp->p_lback = pp;
449: pp->p_lback = bp;
450: bp->p_lforw = pp;
451: spl(s);
452:
453: /* Here is sleep if signals may *not* interrupt. */
454: if (sleepPri == slpriNoSig) {
455: dispatch();
456: u.u_sleep[0] = '\0';
457: return 0;
458: }
459:
460: /* Here is sleep if signals *may* interrupt. */
461: /* Don't sleep at all if there is already a signal pending. */
462: if (!nondsig()) {
463: dispatch();
464: u.u_sleep[0] = '\0';
465: if (!nondsig()) {
466: return 0;
467: }
468: }
469:
470: /* The process has been interrupted from sleep by a signal. */
471:
472: if (sleepPri == slpriSigCatch) {
473: return 1;
474: }
475:
476: /* Do longjmp to beginning of system call. */
477: T_HAL(8, printf("[%d]Ljmps ", SELF->p_pid));
478: sphi();
479: envrest(&u.u_sigenv);
480: }
481:
482: /*
483: * Defer function to wake up all processes sleeping on the event `e'.
484: */
485: wakeup(e)
486: char *e;
487: {
488: void dwakeup();
489:
490: #ifdef TRACER
491: /*
492: * In diagnostic kernel, keep return addr on queue as well.
493: */
494: int *r=(int*)(&e);
495: defer0(dwakeup, e, *(r-1));
496: #else
497: defer(dwakeup, e);
498: #endif
499: }
500:
501: /*
502: * Wake up all processes sleeping on "event".
503: */
504: void
505: dwakeup(event)
506: char *event;
507: {
508: register PROC *pp;
509: register PROC *pp1;
510: register int s;
511:
512: /*
513: * Identify event queue to check.
514: * Disable interrupts.
515: */
516: pp1 = &linkq[hash(event)];
517: pp = pp1;
518: s = sphi();
519:
520: /*
521: * Traverse doubly-linked circular event-queue.
522: */
523: while ((pp = pp->p_lforw) != pp1) {
524:
525: /*
526: * Process is waiting on event 'event'.
527: */
528: if (pp->p_event == event) {
529: /*
530: * Remove process from event queue.
531: * Update process priority.
532: * Insert process into run queue.
533: */
534: pp->p_lback->p_lforw = pp->p_lforw;
535: pp->p_lforw->p_lback = pp->p_lback;
536: setrun(pp);
537:
538: /*
539: * Enable interrupts.
540: * Restart search at start of event queue.
541: * Disable interrupts.
542: */
543: spl(s);
544: pp = pp1;
545: s = sphi();
546: }
547: }
548: spl(s);
549: }
550:
551: /*
552: * Select next process for execution, working backward from iprocp.
553: * If it is not the idle process, delete it from the run queue.
554: * If it is not the current process, consave the current process and
555: * conrest the selected process.
556: */
557: dispatch()
558: {
559: register PROC *pp;
560: register int s;
561:
562: s = sphi();
563: pp = iprocp->p_lback;
564: if (pp != iprocp) {
565: pp->p_lforw->p_lback = pp->p_lback;
566: pp->p_lback->p_lforw = pp->p_lforw;
567: }
568: spl(s);
569:
570: quantum = NCRTICK;
571: disflag = 0;
572: if (pp != SELF) {
573: /*
574: * Consave() returns twice.
575: * 1st time is after our context is saved in u.u_syscon,
576: * whereupon we should restore other proc's context.
577: * 2nd time is after our context is restored by another proc.
578: * Conrest() forces a context switch to a new process.
579: */
580: s = sphi();
581: SELF = pp;
582: if (consave(&u.u_syscon) == 0) {
583: conrest(*pp->p_segp[SIUSERP]->s_vmem, &u.u_syscon);
584: }
585:
586: if (SELF->p_pid) { /* init is special! */
587: ndpConRest();
588: segload();
589: }
590: spl(s);
591: }
592: }
593:
594: /*
595: * Add a process to the run queue, just forward of iprocp.
596: * This routine must be called at high priority.
597: */
598: setrun(pp)
599: register PROC *pp;
600: {
601: pp->p_lback = iprocp;
602: pp->p_lforw = iprocp->p_lforw;
603: pp->p_lback->p_lforw = pp;
604: pp->p_lforw->p_lback = pp;
605: pp->p_state = PSRUN;
606: }
607:
608: /*
609: * Wait for the gate `g' to unlock, and then lock it.
610: */
611: lock(g)
612: register GATE g;
613: {
614: register int s;
615:
616: s = sphi();
617: while (g[0]) {
618: g[1] = 1;
619: x_sleep((char *)g, primed, slpriNoSig, "lock");
620: /* Waiting for a gate to unlock. */
621: }
622: g[0] = 1;
623: spl(s);
624: }
625:
626: /*
627: * Unlock the gate `g'.
628: */
629: unlock(g)
630: register GATE g;
631: {
632: g[0] = 0;
633: if (g[1]) {
634: g[1] = 0;
635: disflag = 1;
636: wakeup((char *)g);
637: }
638: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.