|
|
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.