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