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