|
|
1.1 ! root 1: /* slp.c 4.14 81/06/11 */ ! 2: ! 3: #include "../h/param.h" ! 4: #include "../h/systm.h" ! 5: #include "../h/dir.h" ! 6: #include "../h/user.h" ! 7: #include "../h/lnode.h" ! 8: #include "../h/proc.h" ! 9: #include "../h/file.h" ! 10: #include "../h/inode.h" ! 11: #include "../h/vm.h" ! 12: #include "../h/pte.h" ! 13: #include "../h/mtpr.h" ! 14: #include "../h/share.h" ! 15: ! 16: #define SQSIZE 0100 /* Must be power of 2 */ ! 17: #define HASH(x) (( (int) x >> 5) & (SQSIZE-1)) ! 18: struct proc *slpque[SQSIZE]; ! 19: ! 20: /* ! 21: * Give up the processor till a wakeup occurs ! 22: * on chan, at which time the process ! 23: * enters the scheduling queue at priority pri. ! 24: * The most important effect of pri is that when ! 25: * pri<=PZERO a signal cannot disturb the sleep; ! 26: * if pri>PZERO signals will be processed. ! 27: * Callers of this routine must be prepared for ! 28: * premature return, and check that the reason for ! 29: * sleeping has gone away. ! 30: */ ! 31: sleep(chan, pri) ! 32: caddr_t chan; ! 33: { ! 34: register struct proc *rp, **hp; ! 35: register s; ! 36: ! 37: rp = u.u_procp; ! 38: s = spl6(); ! 39: if (chan==0 || rp->p_stat != SRUN || rp->p_rlink) ! 40: panic("sleep"); ! 41: rp->p_wchan = chan; ! 42: rp->p_slptime = 0; ! 43: rp->p_pri = pri; ! 44: hp = &slpque[HASH(chan)]; ! 45: rp->p_link = *hp; ! 46: *hp = rp; ! 47: if(pri > PZERO) { ! 48: if(rp->p_sig && issig(rp)) { ! 49: if (rp->p_wchan) ! 50: unsleep(rp); ! 51: rp->p_stat = SRUN; ! 52: (void) spl0(); ! 53: goto psig; ! 54: } ! 55: if (rp->p_wchan == 0) ! 56: goto out; ! 57: rp->p_stat = SSLEEP; ! 58: (void) spl0(); ! 59: swtch(); ! 60: if(rp->p_sig && issig(rp)) ! 61: goto psig; ! 62: } else { ! 63: rp->p_stat = SSLEEP; ! 64: (void) spl0(); ! 65: swtch(); ! 66: } ! 67: out: ! 68: splx(s); ! 69: return; ! 70: ! 71: /* ! 72: * If priority was low (>PZERO) and ! 73: * there has been a signal, ! 74: * execute non-local goto to ! 75: * the qsav location. ! 76: * (see trap1/trap.c) ! 77: */ ! 78: psig: ! 79: longjmp(u.u_qsav); ! 80: /*NOTREACHED*/ ! 81: } ! 82: ! 83: /* ! 84: * Sleep on chan at pri. ! 85: * Return in no more than the indicated number of seconds. ! 86: * (If seconds==0, no timeout implied) ! 87: * Return TS_OK if chan was awakened normally ! 88: * TS_TIME if timeout occurred ! 89: * TS_SIG if asynchronous signal occurred ! 90: */ ! 91: tsleep(chan, pri, seconds) ! 92: caddr_t chan; ! 93: { ! 94: label_t lqsav; ! 95: register n, rval; ! 96: register struct proc *pp = u.u_procp; ! 97: ! 98: n = spl7(); ! 99: bcopy((caddr_t)u.u_qsav, (caddr_t)lqsav, sizeof (label_t)); ! 100: pp->p_tsleep = seconds; ! 101: if (setjmp(u.u_qsav)) ! 102: rval = TS_SIG; ! 103: else { ! 104: sleep(chan, pri); ! 105: if (pp->p_flag&STIMO) ! 106: rval = TS_TIME; ! 107: else ! 108: rval = TS_OK; ! 109: } ! 110: pp->p_tsleep = 0; ! 111: pp->p_flag &= ~STIMO; ! 112: bcopy((caddr_t)lqsav, (caddr_t)u.u_qsav, sizeof (label_t)); ! 113: splx(n); ! 114: return(rval); ! 115: } ! 116: ! 117: /* ! 118: * Remove a process from its wait queue ! 119: */ ! 120: unsleep(p) ! 121: register struct proc *p; ! 122: { ! 123: register struct proc **hp; ! 124: register s; ! 125: ! 126: s = spl6(); ! 127: if (p->p_wchan) { ! 128: hp = &slpque[HASH(p->p_wchan)]; ! 129: while (*hp != p) ! 130: hp = &(*hp)->p_link; ! 131: *hp = p->p_link; ! 132: p->p_wchan = 0; ! 133: } ! 134: splx(s); ! 135: } ! 136: ! 137: /* ! 138: * Wake up all processes sleeping on chan. ! 139: */ ! 140: wakeup(chan) ! 141: register caddr_t chan; ! 142: { ! 143: register struct proc *p, **q, **h; ! 144: int s; ! 145: ! 146: s = spl6(); ! 147: h = &slpque[HASH(chan)]; ! 148: restart: ! 149: for (q = h; p = *q; ) { ! 150: if (p->p_rlink || p->p_stat != SSLEEP && p->p_stat != SSTOP) ! 151: panic("wakeup"); ! 152: if (p->p_wchan==chan) { ! 153: p->p_wchan = 0; ! 154: *q = p->p_link; ! 155: p->p_slptime = 0; ! 156: if (p->p_stat == SSLEEP) { ! 157: /* OPTIMIZED INLINE EXPANSION OF setrun(p) */ ! 158: p->p_stat = SRUN; ! 159: if (p->p_flag & SLOAD) ! 160: setrq(p); ! 161: if(p->p_pri < curpri) { ! 162: runrun++; ! 163: aston(); ! 164: } ! 165: if ((p->p_flag&SLOAD) == 0) { ! 166: if (runout != 0) { ! 167: runout = 0; ! 168: wakeup((caddr_t)&runout); ! 169: } ! 170: wantin++; ! 171: } ! 172: /* END INLINE EXPANSION */ ! 173: goto restart; ! 174: } ! 175: } else ! 176: q = &p->p_link; ! 177: } ! 178: splx(s); ! 179: } ! 180: ! 181: /* ! 182: * Initialize the (doubly-linked) run queues ! 183: * to be empty. ! 184: */ ! 185: rqinit() ! 186: { ! 187: register int i; ! 188: ! 189: for (i = 0; i < NQS; i++) ! 190: qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i]; ! 191: } ! 192: ! 193: /* ! 194: * Set the process running; ! 195: * arrange for it to be swapped in if necessary. ! 196: */ ! 197: setrun(p) ! 198: register struct proc *p; ! 199: { ! 200: register s; ! 201: ! 202: s = spl6(); ! 203: switch (p->p_stat) { ! 204: ! 205: case 0: ! 206: case SWAIT: ! 207: case SRUN: ! 208: case SZOMB: ! 209: default: ! 210: panic("setrun"); ! 211: ! 212: case SSTOP: ! 213: case SSLEEP: ! 214: unsleep(p); /* e.g. when sending signals */ ! 215: break; ! 216: ! 217: case SIDL: ! 218: break; ! 219: } ! 220: p->p_stat = SRUN; ! 221: if (p->p_flag & SLOAD) ! 222: setrq(p); ! 223: splx(s); ! 224: if(p->p_pri < curpri) { ! 225: runrun++; ! 226: aston(); ! 227: } ! 228: if ((p->p_flag&SLOAD) == 0) { ! 229: if(runout != 0) { ! 230: runout = 0; ! 231: wakeup((caddr_t)&runout); ! 232: } ! 233: wantin++; ! 234: } ! 235: } ! 236: ! 237: /* ! 238: * Set user priority. ! 239: * The rescheduling flag (runrun) ! 240: * is set if the priority is better ! 241: * than the currently running process. ! 242: * ! 243: * (Remember divide by 4 in setrq().) ! 244: */ ! 245: setpri(pp) ! 246: register struct proc *pp; ! 247: { ! 248: register int p; ! 249: register float f = pp->p_sharepri; ! 250: register int n = pp->p_nice; ! 251: ! 252: if (f > MaxSharePri || n == (2*NZERO-1)) { ! 253: if (pp->p_lnode->kl_norms) { ! 254: if (n == (2*NZERO-1)) ! 255: p = 123; /* Background process */ ! 256: else ! 257: p = 119; /* Background user */ ! 258: } else ! 259: p = 127; /* Idle process */ ! 260: } else { ! 261: f *= (float)((115-16)-PUSER); ! 262: p = f / MaxSharePri; ! 263: if (n > NZERO) ! 264: p += 16; /* Nice process */ ! 265: if((p += PUSER) > 115) ! 266: p = 115; ! 267: } ! 268: if(p < curpri) { ! 269: runrun++; ! 270: aston(); ! 271: } ! 272: pp->p_usrpri = p; ! 273: return(p); ! 274: } ! 275: ! 276: /* ! 277: * Create a new process-- the internal version of ! 278: * sys fork. ! 279: * It returns 1 in the new process, 0 in the old. ! 280: */ ! 281: newproc(isvfork) ! 282: { ! 283: register struct proc *p; ! 284: register struct proc *rpp, *rip; ! 285: register int n; ! 286: ! 287: p = NULL; ! 288: /* ! 289: * First, just locate a slot for a process ! 290: * and copy the useful info from this process into it. ! 291: * The panic "cannot happen" because fork has already ! 292: * checked for the existence of a slot. ! 293: */ ! 294: retry: ! 295: mpid++; ! 296: if(mpid >= 30000) { ! 297: mpid = 0; ! 298: goto retry; ! 299: } ! 300: for(rpp = proc; rpp < procNPROC; rpp++) { ! 301: if(rpp->p_stat == NULL && p==NULL) ! 302: p = rpp; ! 303: if (rpp->p_pid==mpid || rpp->p_pgrp==mpid) ! 304: goto retry; ! 305: } ! 306: if ((rpp = p)==NULL) ! 307: panic("no procs"); ! 308: ! 309: /* ! 310: * make proc entry for new proc ! 311: */ ! 312: ! 313: rip = u.u_procp; ! 314: rpp->p_stat = SIDL; ! 315: rpp->p_clktim = 0; ! 316: rpp->p_flag = SLOAD | (rip->p_flag & (SSEXEC|SPAGI|SDETACH|SNUSIG|STRC|SPROCTR)); ! 317: if (isvfork) { ! 318: rpp->p_flag |= SVFORK; ! 319: rpp->p_ndx = rip->p_ndx; ! 320: } else ! 321: rpp->p_ndx = rpp - proc; ! 322: rpp->p_uid = rip->p_uid; ! 323: rpp->p_pgrp = rip->p_pgrp; ! 324: rpp->p_nice = rip->p_nice; ! 325: rpp->p_textp = isvfork ? 0 : rip->p_textp; ! 326: rpp->p_pid = mpid; ! 327: rpp->p_ppid = rip->p_pid; ! 328: rpp->p_pptr = rip; ! 329: rpp->p_time = 0; ! 330: rpp->p_cpu = 0; ! 331: rpp->p_siga0 = rip->p_siga0; ! 332: rpp->p_siga1 = rip->p_siga1; ! 333: /* take along any pending signals, like stops? */ ! 334: if (isvfork) { ! 335: rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0; ! 336: rpp->p_szpt = clrnd(ctopt(UPAGES)); ! 337: forkstat.cntvfork++; ! 338: forkstat.sizvfork += rip->p_dsize + rip->p_ssize; ! 339: } else { ! 340: rpp->p_tsize = rip->p_tsize; ! 341: rpp->p_dsize = rip->p_dsize; ! 342: rpp->p_ssize = rip->p_ssize; ! 343: rip->p_lnode->kl_muse += rip->p_dsize + rip->p_ssize; ! 344: rpp->p_szpt = rip->p_szpt; ! 345: forkstat.cntfork++; ! 346: forkstat.sizfork += rip->p_dsize + rip->p_ssize; ! 347: } ! 348: rpp->p_rssize = 0; ! 349: rpp->p_maxrss = rip->p_maxrss; ! 350: rpp->p_wchan = 0; ! 351: rpp->p_slptime = 0; ! 352: rpp->p_pctcpu = 0; ! 353: rpp->p_cpticks = 0; ! 354: rpp->p_lnode = rip->p_lnode; ! 355: rpp->p_sharepri = rip->p_sharepri; ! 356: rpp->p_lnode->kl_refcount++; ! 357: n = PIDHASH(rpp->p_pid); ! 358: p->p_idhash = pidhash[n]; ! 359: pidhash[n] = rpp - proc; ! 360: ! 361: /* ! 362: * make duplicate entries ! 363: * where needed ! 364: */ ! 365: ! 366: multprog++; ! 367: ! 368: for(n=0; n<NOFILE; n++) ! 369: if(u.u_ofile[n] != NULL) ! 370: u.u_ofile[n]->f_count++; ! 371: ! 372: u.u_cdir->i_count++; ! 373: if (u.u_rdir) ! 374: u.u_rdir->i_count++; ! 375: /* ! 376: * Partially simulate the environment ! 377: * of the new process so that when it is actually ! 378: * created (by copying) it will look right. ! 379: */ ! 380: ! 381: rip->p_flag |= SKEEP; /* prevent parent from being swapped */ ! 382: ! 383: if (procdup(rpp, isvfork)) ! 384: return (1); ! 385: ! 386: (void) spl6(); ! 387: rpp->p_stat = SRUN; ! 388: setrq(rpp); ! 389: (void) spl0(); ! 390: /* SSWAP NOT NEEDED IN THIS CASE AS u.u_pcb.pcb_sswap SUFFICES */ ! 391: /* rpp->p_flag |= SSWAP; */ ! 392: rip->p_flag &= ~SKEEP; ! 393: if (isvfork) { ! 394: u.u_procp->p_xlink = rpp; ! 395: u.u_procp->p_flag |= SNOVM; ! 396: while (rpp->p_flag & SVFORK) ! 397: sleep((caddr_t)rpp, PZERO - 1); ! 398: if ((rpp->p_flag & SLOAD) == 0) ! 399: panic("newproc vfork"); ! 400: uaccess(rpp, Vfmap, &vfutl); ! 401: u.u_procp->p_xlink = 0; ! 402: vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap); ! 403: u.u_procp->p_flag &= ~SNOVM; ! 404: rpp->p_ndx = rpp - proc; ! 405: rpp->p_flag |= SVFDONE; ! 406: wakeup((caddr_t)rpp); ! 407: } ! 408: return (0); ! 409: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.