|
|
1.1 ! root 1: /* $Header: /newbits/286_KERNEL/USRSRC/coh/RCS/proc.c,v 1.1 92/01/09 13:29:01 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 2.3.37 ! 11: * Copyright (c) 1982, 1983, 1984. ! 12: * An unpublished work by Mark Williams Company, Chicago. ! 13: * All rights reserved. ! 14: -lgl) */ ! 15: /* ! 16: * Coherent. ! 17: * Process handling and scheduling. ! 18: * ! 19: * $Log: proc.c,v $ ! 20: * Revision 1.1 92/01/09 13:29:01 bin ! 21: * Initial revision ! 22: * ! 23: * Revision 1.2 88/08/05 15:30:01 src ! 24: * pfork() made more rigorous, supports loadable driver forks, etc. ! 25: * lock/unlock more efficient, since know wakeup is synchronous. ! 26: * ! 27: * Revision 1.1 88/03/24 16:14:16 src ! 28: * Initial revision ! 29: * ! 30: * 88/03/10 Allan Cornish /usr/src/sys/coh/proc.c ! 31: * Numerous temporary fixes due to AMD 286 chip being buggy in protected mode. ! 32: * These partial fixes will be removed once all CPU's are replaced. ! 33: * ! 34: * 88/01/21 Allan Cornish /usr/src/sys/coh/proc.c ! 35: * Race condition caused by pexit() calling sfree() on the user-area ! 36: * when the segmentation gate is locked is now prevented. ! 37: * Release of the user area now deferred until relproc() invoked by uwait(). ! 38: * ! 39: * 87/11/13 Allan Cornish /usr/src/sys/coh/proc.c ! 40: * pexit() now sets uasa to 0 before dispatching processor. ! 41: * ! 42: * 87/11/05 Allan Cornish /usr/src/sys/coh/proc.c ! 43: * New seg struct now used to allow extended addressing. ! 44: * ! 45: * 87/07/08 Allan Cornish /usr/src/sys/coh/proc.c ! 46: * pexit() now cancels poll/alarm timed functions before terminating. ! 47: * ! 48: * 87/01/05 Allan Cornish /usr/src/sys/coh/proc.c ! 49: * pexit() now wakes the swapper before terminating. ! 50: */ ! 51: #include <sys/coherent.h> ! 52: #include <acct.h> ! 53: #include <errno.h> ! 54: #include <sys/inode.h> ! 55: #include <sys/proc.h> ! 56: #include <sys/ptrace.h> ! 57: #include <sys/sched.h> ! 58: #include <sys/seg.h> ! 59: #include <signal.h> ! 60: #include <sys/stat.h> ! 61: #include <sys/uproc.h> ! 62: ! 63: /* ! 64: * Initialisation. ! 65: * Set up the hash table queues. ! 66: */ ! 67: pcsinit() ! 68: { ! 69: register PROC *pp; ! 70: register PLINK *lp; ! 71: ! 72: pp = &procq; ! 73: SELF = pp; ! 74: procq.p_nforw = pp; ! 75: procq.p_nback = pp; ! 76: procq.p_lforw = pp; ! 77: procq.p_lback = pp; ! 78: for (lp=&linkq[0]; lp<&linkq[NHPLINK]; lp++) { ! 79: lp->p_lforw = lp; ! 80: lp->p_lback = lp; ! 81: } ! 82: } ! 83: ! 84: /* ! 85: * Initiate a process. `f' is a kernel function that is associated with ! 86: * the process. ! 87: */ ! 88: PROC * ! 89: process(f) ! 90: int (*f)(); ! 91: { ! 92: register PROC *pp1; ! 93: register PROC *pp; ! 94: register SEG *sp; ! 95: MCON mcon; ! 96: ! 97: if ((pp=kalloc(sizeof(PROC))) == NULL) ! 98: return (NULL); ! 99: ! 100: pp->p_flags = PFCORE; ! 101: pp->p_state = PSRUN; ! 102: pp->p_ttdev = NODEV; ! 103: ! 104: if (f != NULL) { ! 105: pp->p_flags |= PFKERN; ! 106: sp = salloc((fsize_t)UPASIZE, SFSYST|SFHIGH|SFNSWP); ! 107: if (sp == NULL) { ! 108: kfree(pp); ! 109: return (NULL); ! 110: } ! 111: pp->p_segp[SIUSERP] = sp; ! 112: msetsys( &mcon, f, FP_SEL(sp->s_faddr) ); ! 113: kfcopy( (char *)&mcon, ! 114: sp->s_faddr + offset(uproc, u_syscon), ! 115: sizeof(mcon) ); ! 116: } ! 117: lock(pnxgate); ! 118: next: ! 119: pp->p_pid = cpid++; ! 120: if (cpid >= NPID) ! 121: cpid = 2; ! 122: pp1 = &procq; ! 123: while ((pp1=pp1->p_nforw) != &procq) { ! 124: if (pp1->p_pid < pp->p_pid) ! 125: break; ! 126: if (pp1->p_pid == pp->p_pid) ! 127: goto next; ! 128: } ! 129: pp->p_nback = pp1->p_nback; ! 130: pp1->p_nback->p_nforw = pp; ! 131: pp->p_nforw = pp1; ! 132: pp1->p_nback = pp; ! 133: unlock(pnxgate); ! 134: return (pp); ! 135: } ! 136: ! 137: /* ! 138: * Remove a process from the next queue and release and space. ! 139: */ ! 140: relproc(pp) ! 141: register PROC *pp; ! 142: { ! 143: register SEG * sp; ! 144: ! 145: /* ! 146: * Child process still has a user-area. ! 147: */ ! 148: if ( (sp = pp->p_segp[SIUSERP]) != NULL ) { ! 149: ! 150: /* ! 151: * Detach user-area from child process. ! 152: */ ! 153: pp->p_segp[SIUSERP] = NULL; ! 154: ! 155: /* ! 156: * Child process is swapped out. ! 157: */ ! 158: if ( pp->p_flags & PFSWAP ) ! 159: sp->s_lrefc++; ! 160: ! 161: /* ! 162: * Release child's user-area. ! 163: */ ! 164: sfree( sp ); ! 165: } ! 166: ! 167: /* ! 168: * Remove process from doubly-linked list of all processes. ! 169: * Release space allocated for proc structure. ! 170: */ ! 171: lock(pnxgate); ! 172: pp->p_nback->p_nforw = pp->p_nforw; ! 173: pp->p_nforw->p_nback = pp->p_nback; ! 174: unlock(pnxgate); ! 175: kfree(pp); ! 176: } ! 177: ! 178: /* ! 179: * Create a clone of ourselves. ! 180: * N.B. - consave(&mcon) returns twice; anything not initialized ! 181: * in automatic storage before the call to segadup() will not be ! 182: * initialized when the second return from consave() commences. ! 183: */ ! 184: pfork() ! 185: { ! 186: register PROC *cpp; ! 187: register PROC *pp; ! 188: register int s; ! 189: MCON mcon; ! 190: ! 191: if ((cpp=process(NULL)) == NULL) { ! 192: u.u_error = EAGAIN; ! 193: return; ! 194: } ! 195: ! 196: s = sphi(); /* Make usave a null macro if unnecessary */ ! 197: usave(); /* Put the current copy of uarea into its segment */ ! 198: spl(s); ! 199: ! 200: if (segadup(cpp) == 0) { ! 201: u.u_error = EAGAIN; ! 202: relproc(cpp); ! 203: return; ! 204: } ! 205: if ( u.u_rdir != NULL ) ! 206: u.u_rdir->i_refc++; ! 207: if ( u.u_cdir != NULL ) ! 208: u.u_cdir->i_refc++; ! 209: fdadupl(); ! 210: pp = SELF; ! 211: cpp->p_uid = pp->p_uid; ! 212: cpp->p_ruid = pp->p_ruid; ! 213: cpp->p_rgid = pp->p_rgid; ! 214: cpp->p_ppid = pp->p_pid; ! 215: cpp->p_ttdev = pp->p_ttdev; ! 216: cpp->p_group = pp->p_group; ! 217: cpp->p_ssig = pp->p_ssig; ! 218: cpp->p_isig = pp->p_isig; ! 219: cpp->p_cval = CVCHILD; ! 220: cpp->p_ival = IVCHILD; ! 221: cpp->p_sval = SVCHILD; ! 222: cpp->p_rval = RVCHILD; ! 223: ! 224: s = sphi(); ! 225: consave(&mcon); ! 226: spl( s ); ! 227: ! 228: /* ! 229: * Parent process. ! 230: */ ! 231: if ( (pp = SELF) != cpp ) { ! 232: segfinm(cpp->p_segp[SIUSERP]); ! 233: kfcopy( (char *)&mcon, ! 234: cpp->p_segp[SIUSERP]->s_faddr + offset(uproc,u_syscon), ! 235: sizeof(mcon) ); ! 236: mfixcon(cpp); ! 237: s = sphi(); ! 238: setrun(cpp); ! 239: spl(s); ! 240: return( cpp->p_pid ); ! 241: } ! 242: ! 243: /* ! 244: * Child process. ! 245: */ ! 246: else { ! 247: u.u_btime = timer.t_time; ! 248: u.u_flag = AFORK; ! 249: /* for (i=0; i<NUSEG; i++) done in sproto */ ! 250: /* u.u_segl[i].sr_segp = pp->p_segp[i]; ditto */ ! 251: sproto(); ! 252: segload(); ! 253: return( 0 ); ! 254: } ! 255: } ! 256: ! 257: /* ! 258: * Die. ! 259: */ ! 260: pexit(s) ! 261: { ! 262: register PROC *pp1; ! 263: register PROC *pp; ! 264: register SEG *sp; ! 265: register int n; ! 266: ! 267: pp = SELF; ! 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]) != NULL ) { ! 291: pp->p_segp[n] = NULL; ! 292: sfree( sp ); ! 293: } ! 294: } ! 295: ! 296: /* ! 297: * Wakeup our parent. If we have any children, init will become the ! 298: * new parent. If there are any children we are tracing who are ! 299: * waiting for us, we wake them up. ! 300: */ ! 301: pp1 = &procq; ! 302: while ((pp1=pp1->p_nforw) != &procq) { ! 303: if (pp1->p_pid == pp->p_ppid) { ! 304: if (pp1->p_state==PSSLEEP && pp1->p_event==(char *)pp1) ! 305: wakeup((char *)pp1); ! 306: } ! 307: if (pp1->p_ppid == pp->p_pid) { ! 308: pp1->p_ppid = 1; ! 309: if (pp1->p_state == PSDEAD) ! 310: wakeup((char *)eprocp); ! 311: if ((pp1->p_flags&PFTRAC) != 0) ! 312: wakeup((char *)&pts.pt_req); ! 313: } ! 314: } ! 315: ! 316: /* ! 317: * Wake up swapper if swap timer is active. ! 318: */ ! 319: if ( stimer.t_last != 0 ) ! 320: wakeup( (char *) &stimer ); ! 321: ! 322: /* ! 323: * And finally mark us as dead and give up the processor forever. ! 324: */ ! 325: pp->p_exit = s; ! 326: pp->p_state = PSDEAD; ! 327: uasa = 0; ! 328: dispatch(); ! 329: } ! 330: ! 331: /* ! 332: * Sleep on the event `e'. This gives up the processor until someone ! 333: * wakes us up. Since it is possible for many people to sleep on the ! 334: * same event, the caller when awakened should make sure that what he ! 335: * was waiting for has completed and if not, go to sleep again. `cl' ! 336: * is the cpu value we get to get the cpu as soon as we are woken up. ! 337: * `sl' is the swap value we get to keep us in memory for the duration ! 338: * of the sleep. `sr' is the swap value that allows us to get swapped ! 339: * in if we have been swapped out. ! 340: */ ! 341: sleep(e, cl, sl, sr) ! 342: char *e; ! 343: { ! 344: register PROC *bp; ! 345: register PROC *fp; ! 346: register PROC *pp; ! 347: register int s; ! 348: ! 349: pp = SELF; ! 350: ! 351: /* ! 352: * See if we have a signal awaiting. ! 353: */ ! 354: if (cl<CVNOSIG && pp->p_ssig && nondsig()) { ! 355: sphi(); ! 356: envrest(&u.u_sigenv); ! 357: } ! 358: ! 359: /* ! 360: * Get ready to go to sleep and do so. ! 361: */ ! 362: s = sphi(); ! 363: pp->p_state = PSSLEEP; ! 364: pp->p_event = e; ! 365: pp->p_lctim = utimer; ! 366: addu(pp->p_cval, cl); ! 367: pp->p_ival = sl; ! 368: pp->p_rval = sr; ! 369: fp = &linkq[hash(e)]; ! 370: bp = fp->p_lback; ! 371: pp->p_lforw = fp; ! 372: fp->p_lback = pp; ! 373: pp->p_lback = bp; ! 374: bp->p_lforw = pp; ! 375: spl(s); ! 376: dispatch(); ! 377: ! 378: /* ! 379: * We have just woken up. Get ready to return. ! 380: */ ! 381: subu(pp->p_cval, cl); ! 382: pp->p_ival = 0; ! 383: pp->p_rval = 0; ! 384: ! 385: /* ! 386: * Check for an interrupted system call. ! 387: */ ! 388: if (cl<CVNOSIG && pp->p_ssig && nondsig()) { ! 389: sphi(); ! 390: envrest(&u.u_sigenv); ! 391: } ! 392: } ! 393: ! 394: /* ! 395: * Defer function to wake up all processes sleeping on the event `e'. ! 396: */ ! 397: wakeup(e) ! 398: char *e; ! 399: { ! 400: extern void dwakeup(); ! 401: ! 402: defer( dwakeup, e ); ! 403: } ! 404: ! 405: /* ! 406: * Wake up all processes sleeping on the event `e'. ! 407: */ ! 408: static void ! 409: dwakeup( e ) ! 410: char *e; ! 411: { ! 412: register PROC *pp; ! 413: register PROC *pp1; ! 414: register int s; ! 415: ! 416: /* ! 417: * Identify event queue to check. ! 418: * Disable interrupts. ! 419: */ ! 420: pp1 = &linkq[hash(e)]; ! 421: pp = pp1; ! 422: s = sphi(); ! 423: ! 424: /* ! 425: * Traverse doubly-linked circular event-queue. ! 426: */ ! 427: while ( (pp = pp->p_lforw) != pp1 ) { ! 428: ! 429: /* ! 430: * Process is waiting on event 'e'. ! 431: */ ! 432: if ( pp->p_event == e ) { ! 433: /* ! 434: * Remove process from event queue. ! 435: * Update process priority. ! 436: * Insert process into run queue. ! 437: */ ! 438: pp->p_lback->p_lforw = pp->p_lforw; ! 439: pp->p_lforw->p_lback = pp->p_lback; ! 440: addu( pp->p_cval, (utimer-pp->p_lctim)*CVCLOCK ); ! 441: setrun( pp ); ! 442: ! 443: /* ! 444: * Enable interrupts. ! 445: * Restart search at start of event queue. ! 446: * Disable interrupts. ! 447: */ ! 448: spl( s ); ! 449: pp = pp1; ! 450: s = sphi(); ! 451: } ! 452: } ! 453: spl(s); ! 454: } ! 455: ! 456: /* ! 457: * Reschedule the processor. ! 458: */ ! 459: dispatch() ! 460: { ! 461: register PROC *pp1; ! 462: register PROC *pp2; ! 463: register unsigned v; ! 464: register int s; ! 465: ! 466: s = sphi(); ! 467: pp1 = iprocp; ! 468: pp2 = &procq; ! 469: v = 0; ! 470: while ((pp2=pp2->p_lforw) != &procq) { ! 471: v -= pp2->p_cval; ! 472: if ((pp2->p_flags&PFCORE) == 0) ! 473: continue; ! 474: pp1 = pp2->p_lforw; ! 475: pp1->p_cval += pp2->p_cval; ! 476: pp2->p_cval = v; ! 477: pp1->p_lback = pp2->p_lback; ! 478: pp1->p_lback->p_lforw = pp1; ! 479: pp1 = pp2; ! 480: break; ! 481: } ! 482: spl(s); ! 483: ! 484: quantum = NCRTICK; ! 485: disflag = 0; ! 486: if ( pp1 != SELF ) { ! 487: /* ! 488: * Consave() returns twice. ! 489: * 1st time is after our context is saved in u.u_syscon, ! 490: * whereupon we should restore other proc's context. ! 491: * 2nd time is after our context is restored by another proc. ! 492: * Conrest() forces a context switch to a new process. ! 493: */ ! 494: s = sphi(); ! 495: SELF = pp1; ! 496: if (consave(&u.u_syscon) == 0) ! 497: conrest( FP_SEL(pp1->p_u->s_faddr), ! 498: offset(uproc,u_syscon) ); ! 499: if ( SELF->p_pid != 0 ) ! 500: segload(); ! 501: spl(s); ! 502: } ! 503: } ! 504: ! 505: /* ! 506: * Add a process to the run queue. ! 507: * This routine must be called at high priority. ! 508: */ ! 509: setrun(pp1) ! 510: register PROC *pp1; ! 511: { ! 512: register PROC *pp2; ! 513: register unsigned v; ! 514: ! 515: v = 0; ! 516: pp2 = &procq; ! 517: for (;;) { ! 518: pp2 = pp2->p_lback; ! 519: if ((v+=pp2->p_lforw->p_cval) >= pp1->p_cval) ! 520: break; ! 521: if (pp2 == &procq) ! 522: break; ! 523: } ! 524: pp2->p_lforw->p_lback = pp1; ! 525: pp1->p_lforw = pp2->p_lforw; ! 526: pp2->p_lforw = pp1; ! 527: pp1->p_lback = pp2; ! 528: v -= pp1->p_cval; ! 529: pp1->p_cval = v; ! 530: pp1->p_lforw->p_cval -= v; ! 531: pp1->p_state = PSRUN; ! 532: } ! 533: ! 534: /* ! 535: * Wait for the gate `g' to unlock, and then lock it. ! 536: */ ! 537: lock(g) ! 538: register GATE g; ! 539: { ! 540: register int s; ! 541: ! 542: s = sphi(); ! 543: while (g[0]) { ! 544: g[1] = 1; ! 545: sleep((char *)g, CVGATE, IVGATE, SVGATE); ! 546: } ! 547: g[0] = 1; ! 548: spl(s); ! 549: } ! 550: ! 551: /* ! 552: * Unlock the gate `g'. ! 553: */ ! 554: unlock(g) ! 555: register GATE g; ! 556: { ! 557: g[0] = 0; ! 558: if (g[1]) { ! 559: g[1] = 0; ! 560: disflag = 1; ! 561: wakeup((char *)g); ! 562: } ! 563: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.