|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "../port/error.h" ! 7: ! 8: Ref pidalloc; ! 9: Ref noteidalloc; ! 10: ! 11: struct ! 12: { ! 13: Lock; ! 14: Proc *arena; ! 15: Proc *free; ! 16: }procalloc; ! 17: ! 18: struct ! 19: { ! 20: Lock; ! 21: Waitq *free; ! 22: }waitqalloc; ! 23: ! 24: typedef struct ! 25: { ! 26: Lock; ! 27: Proc *head; ! 28: Proc *tail; ! 29: int n; ! 30: } Schedq; ! 31: ! 32: int nrdy; ! 33: int lastreadied; ! 34: Schedq runq[Nrq]; ! 35: ! 36: char *statename[] = ! 37: { /* BUG: generate automatically */ ! 38: "Dead", ! 39: "Moribund", ! 40: "Ready", ! 41: "Scheding", ! 42: "Running", ! 43: "Queueing", ! 44: "Wakeme", ! 45: "Broken", ! 46: "Stopped", ! 47: "Rendez", ! 48: }; ! 49: ! 50: /* ! 51: * Always splhi()'ed. ! 52: */ ! 53: void ! 54: schedinit(void) /* never returns */ ! 55: { ! 56: Proc *p; ! 57: ! 58: setlabel(&m->sched); ! 59: if(u){ ! 60: m->proc = 0; ! 61: p = u->p; ! 62: invalidateu(); /* safety first */ ! 63: u = 0; ! 64: if(p->state == Running) ! 65: ready(p); ! 66: else ! 67: if(p->state == Moribund) { ! 68: p->pid = 0; ! 69: p->state = Dead; ! 70: /* ! 71: * Holding locks from pexit: ! 72: * procalloc, palloc ! 73: */ ! 74: mmurelease(p); ! 75: simpleputpage(p->upage); ! 76: p->upage = 0; ! 77: ! 78: p->qnext = procalloc.free; ! 79: procalloc.free = p; ! 80: ! 81: unlock(&palloc); ! 82: unlock(&procalloc); ! 83: } ! 84: p->mach = 0; ! 85: } ! 86: sched(); ! 87: } ! 88: ! 89: void ! 90: sched(void) ! 91: { ! 92: Proc *p; ! 93: ! 94: if(u){ ! 95: splhi(); ! 96: m->cs++; ! 97: procsave(u->p); ! 98: if(setlabel(&u->p->sched)){ /* woke up */ ! 99: p = u->p; ! 100: p->state = Running; ! 101: p->mach = m; ! 102: m->proc = p; ! 103: procrestore(p); ! 104: spllo(); ! 105: return; ! 106: } ! 107: gotolabel(&m->sched); ! 108: } ! 109: p = runproc(); ! 110: mapstack(p); ! 111: gotolabel(&p->sched); ! 112: } ! 113: ! 114: /* ! 115: * this should be called in clock() to implement round robin ! 116: */ ! 117: int ! 118: anyready(void) ! 119: { ! 120: return nrdy; ! 121: } ! 122: ! 123: /* ! 124: * this should be called in non-clock traps to implement preemptive scheduling ! 125: */ ! 126: int ! 127: anyhigher(void) ! 128: { ! 129: int x; ! 130: ! 131: x = lastreadied; ! 132: lastreadied = 0; ! 133: return nrdy && x >= u->p->priority; ! 134: } ! 135: ! 136: enum ! 137: { ! 138: Squantum = (HZ+Nrq-1)/Nrq, ! 139: }; ! 140: ! 141: void ! 142: ready(Proc *p) ! 143: { ! 144: int s, pri; ! 145: Schedq *rq; ! 146: ! 147: s = splhi(); ! 148: ! 149: /* history counts */ ! 150: if(p->state == Running){ ! 151: p->rt++; ! 152: pri = ((p->art + (p->rt<<1))>>2)/Squantum; ! 153: } else { ! 154: p->art = (p->art + (p->rt<<1))>>2; ! 155: p->rt = 0; ! 156: pri = p->art/Squantum; ! 157: } ! 158: pri = p->basepri - pri; ! 159: if(pri < 0) ! 160: pri = 0; ! 161: ! 162: /* the only intersection between the classes is at PriNormal */ ! 163: if(pri < PriNormal && p->basepri > PriNormal) ! 164: pri = PriNormal; ! 165: p->priority = pri; ! 166: rq = &runq[p->priority]; ! 167: ! 168: lock(runq); ! 169: p->rnext = 0; ! 170: if(rq->tail) ! 171: rq->tail->rnext = p; ! 172: else ! 173: rq->head = p; ! 174: rq->tail = p; ! 175: rq->n++; ! 176: nrdy++; ! 177: p->readytime = m->ticks; ! 178: p->state = Ready; ! 179: if(p->priority > lastreadied) ! 180: lastreadied = p->priority; ! 181: unlock(runq); ! 182: splx(s); ! 183: } ! 184: ! 185: /* ! 186: * Always called splhi ! 187: */ ! 188: #include "io.h" ! 189: Proc* ! 190: runproc(void) ! 191: { ! 192: int i; ! 193: Schedq *rq; ! 194: Proc *p, *l; ! 195: static ulong lastfair; ! 196: ! 197: loop: ! 198: ! 199: /* ! 200: * find a process that last ran on this processor (affinity), ! 201: * or one that hasn't moved in a while (load balancing). ! 202: */ ! 203: spllo(); ! 204: for(;;){ ! 205: /* ! 206: * Once a second we look for a long waiting process ! 207: * in the lowest priority queue to make sure nothing ! 208: * gets starved out by a malfunctioning high priority ! 209: * process. ! 210: */ ! 211: if(m->machno == 0 && m->ticks - lastfair > HZ){ ! 212: lastfair = m->ticks; ! 213: for(rq = runq; rq < &runq[Nrq]; rq++){ ! 214: p = rq->head; ! 215: if(p){ ! 216: i = m->ticks - p->readytime; ! 217: if(i > HZ){ ! 218: p->art = 0; ! 219: p->movetime = 0; ! 220: goto found; ! 221: } ! 222: break; ! 223: } ! 224: } ! 225: } ! 226: ! 227: /* ! 228: * get highest priority process that this ! 229: * processor can run given affinity constraints ! 230: */ ! 231: for(rq = &runq[Nrq-1]; rq >= runq; rq--){ ! 232: if(rq->head == 0) ! 233: continue; ! 234: for(p = rq->head; p; p = p->rnext){ ! 235: if(p->mp == m || m->ticks - p->movetime > HZ/2) ! 236: goto found; ! 237: } ! 238: } ! 239: } ! 240: ! 241: ! 242: found: ! 243: splhi(); ! 244: lock(runq); ! 245: ! 246: l = 0; ! 247: for(p = rq->head; p; p = p->rnext){ ! 248: if(p->mp == m || m->ticks - p->movetime > HZ/2) ! 249: break; ! 250: l = p; ! 251: } ! 252: ! 253: /* ! 254: * p->mach==0 only when process state is saved ! 255: */ ! 256: if(p == 0 || p->mach){ ! 257: unlock(runq); ! 258: goto loop; ! 259: } ! 260: if(p->rnext == 0) ! 261: rq->tail = l; ! 262: if(l) ! 263: l->rnext = p->rnext; ! 264: else ! 265: rq->head = p->rnext; ! 266: rq->n--; ! 267: nrdy--; ! 268: if(p->state != Ready) ! 269: print("runproc %s %d %s\n", p->text, p->pid, statename[p->state]); ! 270: unlock(runq); ! 271: ! 272: p->state = Scheding; ! 273: if(p->mp != m) ! 274: p->movetime = m->ticks; ! 275: p->mp = m; ! 276: return p; ! 277: } ! 278: ! 279: int ! 280: canpage(Proc *p) ! 281: { ! 282: int ok = 0; ! 283: ! 284: splhi(); ! 285: lock(&runq[0]); ! 286: /* Only reliable way to see if we are Running */ ! 287: if(p->mach == 0) { ! 288: p->newtlb = 1; ! 289: ok = 1; ! 290: } ! 291: unlock(&runq[0]); ! 292: spllo(); ! 293: ! 294: return ok; ! 295: } ! 296: ! 297: Proc* ! 298: newproc(void) ! 299: { ! 300: Proc *p; ! 301: ! 302: for(;;) { ! 303: lock(&procalloc); ! 304: if(p = procalloc.free){ /* assign = */ ! 305: procalloc.free = p->qnext; ! 306: p->state = Scheding; ! 307: p->psstate = "New"; ! 308: unlock(&procalloc); ! 309: p->mach = 0; ! 310: p->qnext = 0; ! 311: p->nchild = 0; ! 312: p->nwait = 0; ! 313: p->waitq = 0; ! 314: p->pgrp = 0; ! 315: p->egrp = 0; ! 316: p->fgrp = 0; ! 317: p->pdbg = 0; ! 318: p->fpstate = FPinit; ! 319: p->kp = 0; ! 320: p->procctl = 0; ! 321: p->notepending = 0; ! 322: p->mp = 0; ! 323: p->movetime = 0; ! 324: memset(p->seg, 0, sizeof p->seg); ! 325: p->pid = incref(&pidalloc); ! 326: p->noteid = incref(¬eidalloc); ! 327: if(p->pid==0 || p->noteid==0) ! 328: panic("pidalloc"); ! 329: return p; ! 330: } ! 331: unlock(&procalloc); ! 332: resrcwait("no procs"); ! 333: } ! 334: return 0; /* not reached */ ! 335: } ! 336: ! 337: void ! 338: procinit0(void) /* bad planning - clashes with devproc.c */ ! 339: { ! 340: Proc *p; ! 341: int i; ! 342: ! 343: procalloc.free = xalloc(conf.nproc*sizeof(Proc)); ! 344: procalloc.arena = procalloc.free; ! 345: ! 346: p = procalloc.free; ! 347: for(i=0; i<conf.nproc-1; i++,p++) ! 348: p->qnext = p+1; ! 349: p->qnext = 0; ! 350: } ! 351: ! 352: void ! 353: sleep1(Rendez *r, int (*f)(void*), void *arg) ! 354: { ! 355: Proc *p; ! 356: int s; ! 357: ! 358: /* ! 359: * spl is to allow lock to be called ! 360: * at interrupt time. lock is mutual exclusion ! 361: */ ! 362: s = splhi(); ! 363: p = u->p; ! 364: p->r = r; /* early so postnote knows */ ! 365: lock(r); ! 366: ! 367: /* ! 368: * if condition happened, never mind ! 369: */ ! 370: if((*f)(arg)){ ! 371: p->r = 0; ! 372: unlock(r); ! 373: splx(s); ! 374: return; ! 375: } ! 376: ! 377: /* ! 378: * now we are committed to ! 379: * change state and call scheduler ! 380: */ ! 381: if(r->p){ ! 382: print("double sleep %d %d\n", r->p->pid, p->pid); ! 383: dumpstack(); ! 384: } ! 385: p->state = Wakeme; ! 386: r->p = p; ! 387: unlock(r); ! 388: } ! 389: ! 390: void ! 391: sleep(Rendez *r, int (*f)(void*), void *arg) ! 392: { ! 393: Proc *p; ! 394: int s; ! 395: ! 396: p = u->p; ! 397: sleep1(r, f, arg); ! 398: if(p->notepending == 0) ! 399: sched(); /* notepending may go true while asleep */ ! 400: if(p->notepending){ ! 401: p->notepending = 0; ! 402: s = splhi(); ! 403: lock(r); ! 404: if(r->p == p) ! 405: r->p = 0; ! 406: unlock(r); ! 407: splx(s); ! 408: error(Eintr); ! 409: } ! 410: } ! 411: ! 412: int ! 413: tfn(void *arg) ! 414: { ! 415: Proc *p; ! 416: ! 417: p = u->p; ! 418: return MACHP(0)->ticks >= p->twhen || (*p->tfn)(arg); ! 419: } ! 420: ! 421: void ! 422: tsleep(Rendez *r, int (*fn)(void*), void *arg, int ms) ! 423: { ! 424: ulong when; ! 425: Proc *p, *f, **l; ! 426: ! 427: p = u->p; ! 428: when = MS2TK(ms)+MACHP(0)->ticks; ! 429: ! 430: lock(&talarm); ! 431: /* take out of list if checkalarm didn't */ ! 432: if(p->trend) { ! 433: l = &talarm.list; ! 434: for(f = *l; f; f = f->tlink) { ! 435: if(f == p) { ! 436: *l = p->tlink; ! 437: break; ! 438: } ! 439: l = &f->tlink; ! 440: } ! 441: } ! 442: /* insert in increasing time order */ ! 443: l = &talarm.list; ! 444: for(f = *l; f; f = f->tlink) { ! 445: if(f->twhen >= when) ! 446: break; ! 447: l = &f->tlink; ! 448: } ! 449: p->trend = r; ! 450: p->twhen = when; ! 451: p->tfn = fn; ! 452: p->tlink = *l; ! 453: *l = p; ! 454: unlock(&talarm); ! 455: ! 456: sleep(r, tfn, arg); ! 457: p->twhen = 0; ! 458: } ! 459: ! 460: /* ! 461: * Expects that only one process can call wakeup for any given Rendez ! 462: */ ! 463: void ! 464: wakeup(Rendez *r) ! 465: { ! 466: Proc *p; ! 467: int s; ! 468: ! 469: s = splhi(); ! 470: lock(r); ! 471: p = r->p; ! 472: if(p){ ! 473: r->p = 0; ! 474: if(p->state != Wakeme) ! 475: panic("wakeup: state"); ! 476: p->r = 0; ! 477: ready(p); ! 478: } ! 479: unlock(r); ! 480: splx(s); ! 481: } ! 482: ! 483: int ! 484: postnote(Proc *p, int dolock, char *n, int flag) ! 485: { ! 486: User *up; ! 487: KMap *k; ! 488: int s, ret; ! 489: Rendez *r; ! 490: Proc *d, **l; ! 491: ! 492: if(dolock) ! 493: qlock(&p->debug); ! 494: ! 495: if(p->kp) ! 496: print("sending %s to kproc %d %s\n", n, p->pid, p->text); ! 497: ! 498: if(p->upage == 0){ ! 499: if(dolock) ! 500: qunlock(&p->debug); ! 501: return 0; ! 502: } ! 503: ! 504: SET(k); ! 505: if(u == 0 || p != u->p){ ! 506: k = kmap(p->upage); ! 507: up = (User*)VA(k); ! 508: }else ! 509: up = u; ! 510: USED(k); ! 511: ! 512: if(flag!=NUser && (up->notify==0 || up->notified)) ! 513: up->nnote = 0; /* force user's hand */ ! 514: ! 515: ret = 0; ! 516: if(up->nnote < NNOTE){ ! 517: strcpy(up->note[up->nnote].msg, n); ! 518: up->note[up->nnote++].flag = flag; ! 519: ret = 1; ! 520: } ! 521: p->notepending = 1; ! 522: if(up != u) ! 523: kunmap(k); ! 524: if(dolock) ! 525: qunlock(&p->debug); ! 526: ! 527: if(r = p->r){ /* assign = */ ! 528: /* wake up; can't call wakeup itself because we're racing with it */ ! 529: for(;;) { ! 530: s = splhi(); ! 531: if(canlock(r)) ! 532: break; ! 533: splx(s); ! 534: } ! 535: if(p->r==r && r->p==p && p->state==Wakeme){ /* check we won the race */ ! 536: r->p = 0; ! 537: p->r = 0; ! 538: ready(p); ! 539: } ! 540: unlock(r); ! 541: splx(s); ! 542: } ! 543: ! 544: if(p->state != Rendezvous) ! 545: return ret; ! 546: ! 547: /* Try and pull out of a rendezvous */ ! 548: lock(p->pgrp); ! 549: if(p->state == Rendezvous) { ! 550: p->rendval = ~0; ! 551: l = &REND(p->pgrp, p->rendtag); ! 552: for(d = *l; d; d = d->rendhash) { ! 553: if(d == p) { ! 554: *l = p->rendhash; ! 555: ready(p); ! 556: break; ! 557: } ! 558: l = &d->rendhash; ! 559: } ! 560: } ! 561: unlock(p->pgrp); ! 562: return ret; ! 563: } ! 564: ! 565: /* ! 566: * weird thing: keep at most NBROKEN around ! 567: */ ! 568: #define NBROKEN 4 ! 569: struct ! 570: { ! 571: QLock; ! 572: int n; ! 573: Proc *p[NBROKEN]; ! 574: }broken; ! 575: ! 576: void ! 577: addbroken(Proc *p) ! 578: { ! 579: qlock(&broken); ! 580: if(broken.n == NBROKEN) { ! 581: ready(broken.p[0]); ! 582: memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1)); ! 583: --broken.n; ! 584: } ! 585: broken.p[broken.n++] = p; ! 586: qunlock(&broken); ! 587: ! 588: p->state = Broken; ! 589: p->psstate = 0; ! 590: sched(); ! 591: } ! 592: ! 593: void ! 594: unbreak(Proc *p) ! 595: { ! 596: int b; ! 597: ! 598: qlock(&broken); ! 599: for(b=0; b < broken.n; b++) ! 600: if(broken.p[b] == p) { ! 601: broken.n--; ! 602: memmove(&broken.p[b], &broken.p[b+1], ! 603: sizeof(Proc*)*(NBROKEN-(b+1))); ! 604: ready(p); ! 605: break; ! 606: } ! 607: qunlock(&broken); ! 608: } ! 609: ! 610: int ! 611: freebroken(void) ! 612: { ! 613: int i, n; ! 614: ! 615: qlock(&broken); ! 616: n = broken.n; ! 617: for(i=0; i<n; i++) { ! 618: ready(broken.p[i]); ! 619: broken.p[i] = 0; ! 620: } ! 621: broken.n = 0; ! 622: qunlock(&broken); ! 623: return n; ! 624: } ! 625: ! 626: void ! 627: pexit(char *exitstr, int freemem) ! 628: { ! 629: int n; ! 630: long utime, stime; ! 631: Proc *p, *c; ! 632: Segment **s, **es; ! 633: Waitq *wq, *f, *next; ! 634: ! 635: c = u->p; ! 636: c->alarm = 0; ! 637: ! 638: if(c->fgrp) ! 639: closefgrp(c->fgrp); ! 640: closepgrp(c->pgrp); ! 641: close(u->dot); ! 642: if(c->egrp) ! 643: closeegrp(c->egrp); ! 644: ! 645: /* ! 646: * if not a kernel process and have a parent, ! 647: * do some housekeeping. ! 648: */ ! 649: if(c->kp == 0) { ! 650: p = c->parent; ! 651: if(p == 0) { ! 652: if(exitstr == 0) ! 653: exitstr = "unknown"; ! 654: panic("boot process died: %s", exitstr); ! 655: } ! 656: ! 657: while(waserror()) ! 658: ; ! 659: wq = smalloc(sizeof(Waitq)); ! 660: poperror(); ! 661: ! 662: readnum(0, wq->w.pid, NUMSIZE, c->pid, NUMSIZE); ! 663: utime = c->time[TUser] + c->time[TCUser]; ! 664: stime = c->time[TSys] + c->time[TCSys]; ! 665: readnum(0, &wq->w.time[TUser*12], NUMSIZE, ! 666: TK2MS(utime), NUMSIZE); ! 667: readnum(0, &wq->w.time[TSys*12], NUMSIZE, ! 668: TK2MS(stime), NUMSIZE); ! 669: readnum(0, &wq->w.time[TReal*12], NUMSIZE, ! 670: TK2MS(MACHP(0)->ticks - c->time[TReal]), NUMSIZE); ! 671: if(exitstr && exitstr[0]){ ! 672: n = sprint(wq->w.msg, "%s %d:", c->text, c->pid); ! 673: strncpy(wq->w.msg+n, exitstr, ERRLEN-n); ! 674: wq->w.msg[ERRLEN-1] = 0; ! 675: } ! 676: else ! 677: wq->w.msg[0] = '\0'; ! 678: ! 679: lock(&p->exl); ! 680: /* My parent still alive, processes are limited to 128 Zombies to ! 681: * prevent a badly written daemon lots of wait records ! 682: */ ! 683: if(p->pid == c->parentpid && p->state != Broken && p->nwait < 128) { ! 684: p->nchild--; ! 685: p->time[TCUser] += utime; ! 686: p->time[TCSys] += stime; ! 687: ! 688: wq->next = p->waitq; ! 689: p->waitq = wq; ! 690: p->nwait++; ! 691: unlock(&p->exl); ! 692: ! 693: wakeup(&p->waitr); ! 694: } ! 695: else { ! 696: unlock(&p->exl); ! 697: free(wq); ! 698: } ! 699: } ! 700: ! 701: if(!freemem) ! 702: addbroken(c); ! 703: ! 704: es = &c->seg[NSEG]; ! 705: for(s = c->seg; s < es; s++) ! 706: if(*s) ! 707: putseg(*s); ! 708: ! 709: lock(&c->exl); /* Prevent my children from leaving waits */ ! 710: c->pid = 0; ! 711: unlock(&c->exl); ! 712: ! 713: for(f = c->waitq; f; f = next) { ! 714: next = f->next; ! 715: free(f); ! 716: } ! 717: ! 718: /* ! 719: * sched() cannot wait on these locks ! 720: */ ! 721: qlock(&c->debug); ! 722: /* release debuggers */ ! 723: if(c->pdbg) { ! 724: wakeup(&c->pdbg->sleep); ! 725: c->pdbg = 0; ! 726: } ! 727: ! 728: qunlock(&u->p->debug); ! 729: lock(&procalloc); ! 730: lock(&palloc); ! 731: ! 732: c->state = Moribund; ! 733: sched(); ! 734: panic("pexit"); ! 735: } ! 736: ! 737: int ! 738: haswaitq(void *x) ! 739: { ! 740: Proc *p; ! 741: ! 742: p = (Proc *)x; ! 743: return p->waitq != 0; ! 744: } ! 745: ! 746: ulong ! 747: pwait(Waitmsg *w) ! 748: { ! 749: Proc *p; ! 750: ulong cpid; ! 751: Waitq *wq; ! 752: ! 753: p = u->p; ! 754: ! 755: if(!canqlock(&p->qwaitr)) ! 756: error(Einuse); ! 757: ! 758: if(waserror()) { ! 759: qunlock(&p->qwaitr); ! 760: nexterror(); ! 761: } ! 762: ! 763: lock(&p->exl); ! 764: if(p->nchild == 0 && p->waitq == 0) { ! 765: unlock(&p->exl); ! 766: error(Enochild); ! 767: } ! 768: unlock(&p->exl); ! 769: ! 770: sleep(&p->waitr, haswaitq, u->p); ! 771: ! 772: lock(&p->exl); ! 773: wq = p->waitq; ! 774: p->waitq = wq->next; ! 775: p->nwait--; ! 776: unlock(&p->exl); ! 777: ! 778: qunlock(&p->qwaitr); ! 779: poperror(); ! 780: ! 781: if(w) ! 782: memmove(w, &wq->w, sizeof(Waitmsg)); ! 783: cpid = atoi(wq->w.pid); ! 784: free(wq); ! 785: return cpid; ! 786: } ! 787: ! 788: Proc* ! 789: proctab(int i) ! 790: { ! 791: return &procalloc.arena[i]; ! 792: } ! 793: ! 794: void ! 795: procdump(void) ! 796: { ! 797: int i; ! 798: char *s; ! 799: Proc *p; ! 800: ulong bss; ! 801: Schedq *rq; ! 802: ! 803: for(i=0; i<conf.nproc; i++){ ! 804: p = procalloc.arena+i; ! 805: if(p->state != Dead){ ! 806: bss = 0; ! 807: if(p->seg[BSEG]) ! 808: bss = p->seg[BSEG]->top; ! 809: ! 810: s = p->psstate; ! 811: if(s == 0) ! 812: s = "kproc"; ! 813: print("%3d:%10s %10s pc %8lux %8s (%s) ut %ld st %ld r %lux qpc %lux bss %lux\n", ! 814: p->pid, p->text, p->user, p->pc, ! 815: s, statename[p->state], p->time[0], ! 816: p->time[1], p->r, p->qlockpc, bss); ! 817: } ! 818: } ! 819: for(rq = runq; rq < &runq[Nrq]; rq++){ ! 820: if(rq->head == 0) ! 821: continue; ! 822: print("rq%d:", rq-runq); ! 823: for(p = rq->head; p; p = p->rnext) ! 824: print(" %d(%d)", p->pid, m->ticks - p->readytime); ! 825: print("\n"); ! 826: } ! 827: print("nrdy %d\n", nrdy); ! 828: } ! 829: ! 830: void ! 831: kproc(char *name, void (*func)(void *), void *arg) ! 832: { ! 833: Proc *p; ! 834: int n; ! 835: ulong upa; ! 836: User *up; ! 837: KMap *k; ! 838: static Pgrp *kpgrp; ! 839: char *user; ! 840: int lastvar; /* used to compute stack address */ ! 841: ! 842: /* ! 843: * Kernel stack ! 844: */ ! 845: p = newproc(); ! 846: p->psstate = 0; ! 847: p->procmode = 0644; ! 848: p->kp = 1; ! 849: p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF)); ! 850: k = kmap(p->upage); ! 851: upa = VA(k); ! 852: up = (User*)upa; ! 853: ! 854: /* ! 855: * Save time: only copy u-> data and useful stack ! 856: */ ! 857: memmove(up, u, sizeof(User)); ! 858: n = USERADDR+BY2PG - (ulong)&lastvar; ! 859: n = (n+32) & ~(BY2WD-1); /* be safe & word align */ ! 860: memmove((void*)(upa+BY2PG-n), (void*)(USERADDR+BY2PG-n), n); ! 861: up->p = p; ! 862: ! 863: p->basepri = PriKproc; ! 864: p->priority = p->basepri; ! 865: ! 866: /* ! 867: * Refs ! 868: */ ! 869: incref(up->dot); ! 870: kunmap(k); ! 871: ! 872: /* ! 873: * Sched ! 874: */ ! 875: if(setlabel(&p->sched)){ ! 876: p->state = Running; ! 877: p->mach = m; ! 878: m->proc = p; ! 879: spllo(); ! 880: (*func)(arg); ! 881: pexit(0, 1); ! 882: } ! 883: ! 884: user = eve; ! 885: strcpy(p->user, user); ! 886: if(kpgrp == 0){ ! 887: kpgrp = newpgrp(); ! 888: } ! 889: p->pgrp = kpgrp; ! 890: incref(kpgrp); ! 891: ! 892: strcpy(p->text, name); ! 893: ! 894: p->nchild = 0; ! 895: p->parent = 0; ! 896: memset(p->time, 0, sizeof(p->time)); ! 897: p->time[TReal] = MACHP(0)->ticks; ! 898: ready(p); ! 899: /* ! 900: * since the bss/data segments are now shareable, ! 901: * any mmu info about this process is now stale ! 902: * and has to be discarded. ! 903: */ ! 904: flushmmu(); ! 905: } ! 906: ! 907: /* ! 908: * called splhi() by notify(). See comment in notify for the ! 909: * reasoning. ! 910: */ ! 911: void ! 912: procctl(Proc *p) ! 913: { ! 914: char *state; ! 915: ulong s; ! 916: ! 917: switch(p->procctl) { ! 918: case Proc_exitme: ! 919: spllo(); /* pexit has locks in it */ ! 920: pexit("Killed", 1); ! 921: ! 922: case Proc_traceme: ! 923: if(u->nnote == 0) ! 924: return; ! 925: /* No break */ ! 926: ! 927: case Proc_stopme: ! 928: p->procctl = 0; ! 929: state = p->psstate; ! 930: p->psstate = "Stopped"; ! 931: /* free a waiting debugger */ ! 932: s = spllo(); ! 933: qlock(&p->debug); ! 934: if(p->pdbg) { ! 935: wakeup(&p->pdbg->sleep); ! 936: p->pdbg = 0; ! 937: } ! 938: qunlock(&p->debug); ! 939: splhi(); ! 940: p->state = Stopped; ! 941: sched(); ! 942: p->psstate = state; ! 943: splx(s); ! 944: return; ! 945: } ! 946: } ! 947: ! 948: #include "errstr.h" ! 949: ! 950: void ! 951: error(char *err) ! 952: { ! 953: spllo(); ! 954: strncpy(u->error, err, ERRLEN); ! 955: nexterror(); ! 956: } ! 957: ! 958: void ! 959: nexterror(void) ! 960: { ! 961: gotolabel(&u->errlab[--u->nerrlab]); ! 962: } ! 963: ! 964: void ! 965: exhausted(char *resource) ! 966: { ! 967: char buf[ERRLEN]; ! 968: ! 969: sprint(buf, "no free %s", resource); ! 970: error(buf); ! 971: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.