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