1 #include "dat.h" 2 #include "fns.h" 3 #include <isa.h> 4 #include <interp.h> 5 #include <kernel.h> 6 #include "error.h" 7 #include "raise.h" 8 9 struct 10 { 11 Lock l; 12 Prog* runhd; 13 Prog* runtl; 14 Prog* head; 15 Prog* tail; 16 Rendez irend; 17 int idle; 18 int nyield; 19 int creating; 20 Proc* vmq; /* queue of procs wanting vm */ 21 Proc* vmqt; 22 Proc* idlevmq; /* queue of procs wanting work */ 23 Atidle* idletasks; 24 } isched; 25 26 int bflag; 27 int cflag; 28 uvlong gcbusy; 29 uvlong gcidle; 30 uvlong gcidlepass; 31 uvlong gcpartial; 32 int keepbroken = 1; 33 extern int vflag; 34 static Prog* proghash[64]; 35 36 static Progs* delgrp(Prog*); 37 static void addgrp(Prog*, Prog*); 38 void printgrp(Prog*, char*); 39 40 static Prog** 41 pidlook(int pid) 42 { 43 ulong h; 44 Prog **l; 45 46 h = (ulong)pid % nelem(proghash); 47 for(l = &proghash[h]; *l != nil && (*l)->pid != pid; l = &(*l)->pidlink) 48 ; 49 return l; 50 } 51 52 int 53 tready(void *a) 54 { 55 USED(a); 56 return isched.runhd != nil || isched.vmq != nil; 57 } 58 59 Prog* 60 progpid(int pid) 61 { 62 return *pidlook(pid); 63 } 64 65 Prog* 66 progn(int n) 67 { 68 Prog *p; 69 70 for(p = isched.head; p && n--; p = p->next) 71 ; 72 return p; 73 } 74 75 int 76 nprog(void) 77 { 78 int n; 79 Prog *p; 80 81 n = 0; 82 for(p = isched.head; p; p = p->next) 83 n++; 84 return n; 85 } 86 87 static void 88 execatidle(void) 89 { 90 int done; 91 92 if(tready(nil)) 93 return; 94 95 gcidle++; 96 up->type = IdleGC; 97 up->iprog = nil; 98 addrun(up->prog); 99 done = gccolor+3; 100 while(gccolor < done && gcruns()) { 101 if(isched.vmq != nil || isched.runhd != isched.runtl) { 102 gcpartial++; 103 break; 104 } 105 rungc(isched.head); 106 gcidlepass++; 107 if(((ulong)gcidlepass&0xFF) == 0) 108 osyield(); 109 } 110 up->type = Interp; 111 delrunq(up->prog); 112 } 113 114 Prog* 115 newprog(Prog *p, Modlink *m) 116 { 117 Heap *h; 118 Prog *n, **ph; 119 Osenv *on, *op; 120 static int pidnum; 121 122 if(p != nil){ 123 if(p->group != nil) 124 p->flags |= p->group->flags & Pkilled; 125 if(p->kill != nil) 126 error(p->kill); 127 if(p->flags & Pkilled) 128 error(""); 129 } 130 n = malloc(sizeof(Prog)+sizeof(Osenv)); 131 if(n == 0){ 132 if(p == nil) 133 panic("no memory"); 134 else 135 error(exNomem); 136 } 137 138 n->pid = ++pidnum; 139 if(n->pid <= 0) 140 panic("no pids"); 141 n->group = nil; 142 143 if(isched.tail != nil) { 144 n->prev = isched.tail; 145 isched.tail->next = n; 146 } 147 else { 148 isched.head = n; 149 n->prev = nil; 150 } 151 isched.tail = n; 152 153 ph = pidlook(n->pid); 154 if(*ph != nil) 155 panic("dup pid"); 156 n->pidlink = nil; 157 *ph = n; 158 159 n->osenv = (Osenv*)((uchar*)n + sizeof(Prog)); 160 n->xec = xec; 161 n->quanta = PQUANTA; 162 n->flags = 0; 163 n->exval = H; 164 165 h = D2H(m); 166 h->ref++; 167 Setmark(h); 168 n->R.M = m; 169 n->R.MP = m->MP; 170 if(m->MP != H) 171 Setmark(D2H(m->MP)); 172 addrun(n); 173 174 if(p == nil){ 175 newgrp(n); 176 return n; 177 } 178 179 addgrp(n, p); 180 n->flags = p->flags; 181 if(p->flags & Prestrict) 182 n->flags |= Prestricted; 183 memmove(n->osenv, p->osenv, sizeof(Osenv)); 184 op = p->osenv; 185 on = n->osenv; 186 on->waitq = op->childq; 187 on->childq = nil; 188 on->debug = nil; 189 incref(&on->pgrp->r); 190 incref(&on->fgrp->r); 191 incref(&on->egrp->r); 192 if(on->sigs != nil) 193 incref(&on->sigs->r); 194 on->user = nil; 195 kstrdup(&on->user, op->user); 196 on->errstr = on->errbuf0; 197 on->syserrstr = on->errbuf1; 198 199 return n; 200 } 201 202 void 203 delprog(Prog *p, char *msg) 204 { 205 Osenv *o; 206 Prog **ph; 207 208 tellsomeone(p, msg); /* call before being removed from prog list */ 209 210 o = p->osenv; 211 release(); 212 closepgrp(o->pgrp); 213 closefgrp(o->fgrp); 214 closeegrp(o->egrp); 215 closesigs(o->sigs); 216 acquire(); 217 218 delgrp(p); 219 220 if(p->prev) 221 p->prev->next = p->next; 222 else 223 isched.head = p->next; 224 225 if(p->next) 226 p->next->prev = p->prev; 227 else 228 isched.tail = p->prev; 229 230 ph = pidlook(p->pid); 231 if(*ph == nil) 232 panic("lost pid"); 233 *ph = p->pidlink; 234 235 if(p == isched.runhd) { 236 isched.runhd = p->link; 237 if(p->link == nil) 238 isched.runtl = nil; 239 } 240 p->state = 0xdeadbeef; 241 free(o->user); 242 free(p->killstr); 243 free(p->exstr); 244 free(p); 245 } 246 247 void 248 renameproguser(char *old, char *new) 249 { 250 Prog *p; 251 Osenv *o; 252 253 acquire(); 254 for(p = isched.head; p; p = p->next){ 255 o = p->osenv; 256 if(o->user != nil && strcmp(o->user, old) == 0) 257 kstrdup(&o->user, new); 258 } 259 release(); 260 } 261 262 void 263 tellsomeone(Prog *p, char *buf) 264 { 265 Osenv *o; 266 267 if(waserror()) 268 return; 269 o = p->osenv; 270 if(o->childq != nil) 271 qproduce(o->childq, buf, strlen(buf)); 272 if(o->waitq != nil) 273 qproduce(o->waitq, buf, strlen(buf)); 274 poperror(); 275 } 276 277 static void 278 swiprog(Prog *p) 279 { 280 Proc *q; 281 282 lock(&procs.l); 283 for(q = procs.head; q; q = q->next) { 284 if(q->iprog == p) { 285 unlock(&procs.l); 286 swiproc(q, 1); 287 return; 288 } 289 } 290 unlock(&procs.l); 291 /*print("didn't find\n");*/ 292 } 293 294 static Prog* 295 grpleader(Prog *p) 296 { 297 Progs *g; 298 Prog *l; 299 300 g = p->group; 301 if(g != nil && (l = g->head) != nil && l->pid == g->id) 302 return l; 303 return nil; 304 } 305 306 int 307 exprog(Prog *p, char *exc) 308 { 309 /* similar code to killprog but not quite */ 310 switch(p->state) { 311 case Palt: 312 altdone(p->R.s, p, nil, -1); 313 break; 314 case Psend: 315 cqdelp(&p->chan->send, p); 316 break; 317 case Precv: 318 cqdelp(&p->chan->recv, p); 319 break; 320 case Pready: 321 break; 322 case Prelease: 323 swiprog(p); 324 break; 325 case Pexiting: 326 case Pbroken: 327 case Pdebug: 328 return 0; 329 default: 330 panic("exprog - bad state 0x%x\n", p->state); 331 } 332 if(p->state != Pready && p->state != Prelease) 333 addrun(p); 334 if(p->kill == nil){ 335 if(p->killstr == nil){ 336 p->killstr = malloc(ERRMAX); 337 if(p->killstr == nil){ 338 p->kill = Enomem; 339 return 1; 340 } 341 } 342 kstrcpy(p->killstr, exc, ERRMAX); 343 p->kill = p->killstr; 344 } 345 return 1; 346 } 347 348 static void 349 propex(Prog *p, char *estr) 350 { 351 Prog *f, *nf, *pgl; 352 353 if(!(p->flags & (Ppropagate|Pnotifyleader)) || p->group == nil) 354 return; 355 if(*estr == 0){ 356 if((p->flags & Pkilled) == 0) 357 return; 358 estr = "killed"; 359 } 360 pgl = grpleader(p); 361 if(pgl == nil) 362 pgl = p; 363 if(!(pgl->flags & (Ppropagate|Pnotifyleader))) 364 return; /* exceptions are local; don't propagate */ 365 for(f = p->group->head; f != nil; f = nf){ 366 nf = f->grpnext; 367 if(f != p && f != pgl){ 368 if(pgl->flags & Ppropagate) 369 exprog(f, estr); 370 else{ 371 f->flags &= ~(Ppropagate|Pnotifyleader); /* prevent recursion */ 372 killprog(f, "killed"); 373 } 374 } 375 } 376 if(p != pgl) 377 exprog(pgl, estr); 378 } 379 380 int 381 killprog(Prog *p, char *cause) 382 { 383 Osenv *env; 384 char msg[ERRMAX+2*KNAMELEN]; 385 386 if(p == isched.runhd) { 387 p->kill = ""; 388 p->flags |= Pkilled; 389 p->state = Pexiting; 390 return 0; 391 } 392 393 switch(p->state) { 394 case Palt: 395 altdone(p->R.s, p, nil, -1); 396 break; 397 case Psend: 398 cqdelp(&p->chan->send, p); 399 break; 400 case Precv: 401 cqdelp(&p->chan->recv, p); 402 break; 403 case Pready: 404 delrunq(p); 405 break; 406 case Prelease: 407 p->kill = ""; 408 p->flags |= Pkilled; 409 p->state = Pexiting; 410 swiprog(p); 411 /* No break */ 412 case Pexiting: 413 return 0; 414 case Pbroken: 415 case Pdebug: 416 break; 417 default: 418 panic("killprog - bad state 0x%x\n", p->state); 419 } 420 421 if(p->addrun != nil) { 422 p->kill = ""; 423 p->flags |= Pkilled; 424 p->addrun(p); 425 p->addrun = nil; 426 return 0; 427 } 428 429 env = p->osenv; 430 if(env->debug != nil) { 431 p->state = Pbroken; 432 dbgexit(p, 0, cause); 433 return 0; 434 } 435 436 propex(p, "killed"); 437 438 snprint(msg, sizeof(msg), "%d \"%s\":%s", p->pid, p->R.M->m->name, cause); 439 440 p->state = Pexiting; 441 gclock(); 442 destroystack(&p->R); 443 delprog(p, msg); 444 gcunlock(); 445 446 return 1; 447 } 448 449 void 450 newgrp(Prog *p) 451 { 452 Progs *pg, *g; 453 454 if(p->group != nil && p->group->id == p->pid) 455 return; 456 g = malloc(sizeof(*g)); 457 if(g == nil) 458 error(Enomem); 459 p->flags &= ~(Ppropagate|Pnotifyleader); 460 g->id = p->pid; 461 g->flags = 0; 462 g->child = nil; 463 pg = delgrp(p); 464 g->head = g->tail = p; 465 p->group = g; 466 if(pg != nil){ 467 g->sib = pg->child; 468 pg->child = g; 469 } 470 g->parent = pg; 471 } 472 473 static void 474 addgrp(Prog *n, Prog *p) 475 { 476 Progs *g; 477 478 n->group = p->group; 479 if((g = n->group) != nil){ 480 n->grpnext = nil; 481 if(g->head != nil){ 482 n->grpprev = g->tail; 483 g->tail->grpnext = n; 484 }else{ 485 n->grpprev = nil; 486 g->head = n; 487 } 488 g->tail = n; 489 } 490 } 491 492 static Progs* 493 delgrp(Prog *p) 494 { 495 Progs *g, *pg, *cg, **l; 496 497 g = p->group; 498 if(g == nil) 499 return nil; 500 if(p->grpprev) 501 p->grpprev->grpnext = p->grpnext; 502 else 503 g->head = p->grpnext; 504 if(p->grpnext) 505 p->grpnext->grpprev = p->grpprev; 506 else 507 g->tail = p->grpprev; 508 p->grpprev = p->grpnext = nil; 509 p->group = nil; 510 511 if(g->head == nil){ 512 /* move up, giving subgroups of groups with no Progs to their parents */ 513 do{ 514 if((pg = g->parent) != nil){ 515 pg = g->parent; 516 for(l = &pg->child; *l != nil && *l != g; l = &(*l)->sib) 517 ; 518 *l = g->sib; 519 } 520 /* put subgroups in new parent group */ 521 while((cg = g->child) != nil){ 522 g->child = cg->sib; 523 cg->parent = pg; 524 if(pg != nil){ 525 cg->sib = pg->child; 526 pg->child = cg; 527 } 528 } 529 free(g); 530 }while((g = pg) != nil && g->head == nil); 531 } 532 return g; 533 } 534 535 void 536 printgrp(Prog *p, char *v) 537 { 538 Progs *g; 539 Prog *q; 540 541 g = p->group; 542 print("%s pid %d grp %d pgrp %d: [pid", v, p->pid, g->id, g->parent!=nil?g->parent->id:0); 543 for(q = g->head; q != nil; q = q->grpnext) 544 print(" %d", q->pid); 545 print(" subgrp"); 546 for(g = g->child; g != nil; g = g->sib) 547 print(" %d", g->id); 548 print("]\n"); 549 } 550 551 int 552 killgrp(Prog *p, char *msg) 553 { 554 int i, npid, *pids; 555 Prog *f; 556 Progs *g; 557 558 /* interpreter has been acquired */ 559 g = p->group; 560 if(g == nil || g->head == nil) 561 return 0; 562 while(g->flags & Pkilled){ 563 release(); 564 acquire(); 565 } 566 npid = 0; 567 for(f = g->head; f != nil; f = f->grpnext) 568 if(f->group != g) 569 panic("killgrp"); 570 else 571 npid++; 572 /* use pids not Prog* because state can change during killprog (eg, in delprog) */ 573 pids = malloc(npid*sizeof(int)); 574 if(pids == nil) 575 error(Enomem); 576 npid = 0; 577 for(f = g->head; f != nil; f = f->grpnext) 578 pids[npid++] = f->pid; 579 g->flags |= Pkilled; 580 if(waserror()) { 581 g->flags &= ~Pkilled; 582 free(pids); 583 nexterror(); 584 } 585 for(i = 0; i < npid; i++) { 586 f = progpid(pids[i]); 587 if(f != nil && f != currun()) 588 killprog(f, msg); 589 } 590 poperror(); 591 g->flags &= ~Pkilled; 592 free(pids); 593 return 1; 594 } 595 596 char changup[] = "channel hangup"; 597 598 void 599 killcomm(Progq **q) 600 { 601 Prog *p; 602 Progq *f; 603 604 for (f = *q; f != nil; f = *q) { 605 *q = f->next; 606 p = f->prog; 607 free(f); 608 if(p == nil) 609 return; 610 p->ptr = nil; 611 switch(p->state) { 612 case Prelease: 613 swiprog(p); 614 break; 615 case Psend: 616 case Precv: 617 p->kill = changup; 618 addrun(p); 619 break; 620 case Palt: 621 altgone(p); 622 break; 623 } 624 } 625 } 626 627 void 628 addprog(Proc *p) 629 { 630 Prog *n; 631 632 n = malloc(sizeof(Prog)); 633 if(n == nil) 634 panic("no memory"); 635 p->prog = n; 636 n->osenv = p->env; 637 } 638 639 static void 640 cwakeme(Prog *p) 641 { 642 Osenv *o; 643 644 p->addrun = nil; 645 o = p->osenv; 646 Wakeup(o->rend); 647 } 648 649 static int 650 cdone(void *vp) 651 { 652 Prog *p = vp; 653 654 return p->addrun == nil || p->kill != nil; 655 } 656 657 void 658 cblock(Prog *p) 659 { 660 Osenv *o; 661 662 p->addrun = cwakeme; 663 o = p->osenv; 664 o->rend = &up->sleep; 665 release(); 666 667 /* 668 * To allow cdone(p) safely after release, 669 * p must be currun before the release. 670 * Exits in the error case with the vm acquired. 671 */ 672 if(waserror()) { 673 acquire(); 674 p->addrun = nil; 675 nexterror(); 676 } 677 Sleep(o->rend, cdone, p); 678 if (p->kill != nil) 679 error(Eintr); 680 poperror(); 681 acquire(); 682 } 683 684 void 685 addrun(Prog *p) 686 { 687 if(p->addrun != 0) { 688 p->addrun(p); 689 return; 690 } 691 p->state = Pready; 692 p->link = nil; 693 if(isched.runhd == nil) 694 isched.runhd = p; 695 else 696 isched.runtl->link = p; 697 698 isched.runtl = p; 699 } 700 701 Prog* 702 delrun(int state) 703 { 704 Prog *p; 705 706 p = isched.runhd; 707 p->state = state; 708 isched.runhd = p->link; 709 if(p->link == nil) 710 isched.runtl = nil; 711 712 return p; 713 } 714 715 void 716 delrunq(Prog *p) 717 { 718 Prog *prev, *f; 719 720 prev = nil; 721 for(f = isched.runhd; f; f = f->link) { 722 if(f == p) 723 break; 724 prev = f; 725 } 726 if(f == nil) 727 return; 728 if(prev == nil) 729 isched.runhd = p->link; 730 else 731 prev->link = p->link; 732 if(p == isched.runtl) 733 isched.runtl = prev; 734 } 735 736 Prog* 737 delruntail(int state) 738 { 739 Prog *p; 740 741 p = isched.runtl; 742 delrunq(p); 743 p->state = state; 744 return p; 745 } 746 747 Prog* 748 currun(void) 749 { 750 return isched.runhd; 751 } 752 753 Prog* 754 schedmod(Module *m) 755 { 756 Heap *h; 757 Type *t; 758 Prog *p; 759 Modlink *ml; 760 Frame f, *fp; 761 762 ml = mklinkmod(m, 0); 763 764 if(m->origmp != H && m->ntype > 0) { 765 t = m->type[0]; 766 h = nheap(t->size); 767 h->t = t; 768 t->ref++; 769 ml->MP = H2D(uchar*, h); 770 newmp(ml->MP, m->origmp, t); 771 } 772 773 p = newprog(nil, ml); 774 h = D2H(ml); 775 h->ref--; 776 p->R.PC = m->entry; 777 fp = &f; 778 R.s = &fp; 779 f.t = m->entryt; 780 newstack(p); 781 initmem(m->entryt, p->R.FP); 782 783 return p; 784 } 785 786 /* 787 static char* 788 m(Prog *p) 789 { 790 if(p) 791 if(p->R.M) 792 if(p->R.M->m) 793 return p->R.M->m->name; 794 return "nil"; 795 } 796 */ 797 798 void 799 acquire(void) 800 { 801 int empty; 802 Prog *p; 803 804 lock(&isched.l); 805 if(isched.idle) { 806 isched.idle = 0; 807 unlock(&isched.l); 808 } 809 else { 810 up->qnext = nil; 811 if(isched.vmq != nil){ 812 empty = 0; 813 isched.vmqt->qnext = up; 814 }else{ 815 isched.vmq = up; 816 empty = 1; 817 } 818 isched.vmqt = up; 819 820 unlock(&isched.l); 821 strcpy(up->text, "acquire"); 822 if(empty) 823 Wakeup(&isched.irend); 824 osblock(); 825 } 826 827 if(up->type == Interp) { 828 p = up->iprog; 829 up->iprog = nil; 830 irestore(p); 831 } 832 else 833 p = up->prog; 834 835 p->state = Pready; 836 p->link = isched.runhd; 837 isched.runhd = p; 838 if(p->link == nil) 839 isched.runtl = p; 840 841 strcpy(up->text, "dis"); 842 } 843 844 void 845 release(void) 846 { 847 Proc *p, **pq; 848 int f; 849 850 if(up->type == Interp) 851 up->iprog = isave(); 852 else 853 delrun(Prelease); 854 855 lock(&isched.l); 856 if(*(pq = &isched.vmq) == nil && *(pq = &isched.idlevmq) == nil) { 857 isched.idle = 1; 858 f = isched.creating; 859 isched.creating = 1; 860 unlock(&isched.l); 861 if(f == 0) 862 kproc("dis", vmachine, nil, 0); 863 return; 864 } 865 p = *pq; 866 *pq = p->qnext; 867 unlock(&isched.l); 868 869 osready(p); /* wake up thread to run VM */ 870 strcpy(up->text, "released"); 871 } 872 873 void 874 iyield(void) 875 { 876 Proc *p; 877 878 lock(&isched.l); 879 p = isched.vmq; 880 if(p == nil) { 881 unlock(&isched.l); 882 return; 883 } 884 isched.nyield++; 885 isched.vmq = p->qnext; 886 887 if(up->iprog != nil) 888 panic("iyield but iprog, type %d", up->type); 889 if(up->type != Interp){ 890 static int once; 891 if(!once++) 892 print("tell charles: #%p->type==%d\n", up, up->type); 893 } 894 up->qnext = isched.idlevmq; 895 isched.idlevmq = up; 896 897 unlock(&isched.l); 898 osready(p); /* wake up acquiring kproc */ 899 strcpy(up->text, "yield"); 900 osblock(); /* sleep */ 901 strcpy(up->text, "dis"); 902 } 903 904 void 905 startup(void) 906 { 907 908 up->type = Interp; 909 up->iprog = nil; 910 911 lock(&isched.l); 912 isched.creating = 0; 913 if(isched.idle) { 914 isched.idle = 0; 915 unlock(&isched.l); 916 return; 917 } 918 up->qnext = isched.idlevmq; 919 isched.idlevmq = up; 920 unlock(&isched.l); 921 922 osblock(); 923 } 924 925 void 926 progexit(void) 927 { 928 Prog *r; 929 Module *m; 930 int broken; 931 char *estr, msg[ERRMAX+2*KNAMELEN]; 932 933 estr = up->env->errstr; 934 broken = 0; 935 if(estr[0] != '\0' && strcmp(estr, Eintr) != 0 && strncmp(estr, "fail:", 5) != 0) 936 broken = 1; 937 938 r = up->iprog; 939 if(r != nil) 940 acquire(); 941 else 942 r = currun(); 943 944 if(*estr == '\0' && r->flags & Pkilled) 945 estr = "killed"; 946 947 m = R.M->m; 948 if(broken){ 949 if(cflag){ /* only works on Plan9 for now */ 950 char *pc = strstr(estr, "pc="); 951 952 if(pc != nil) 953 R.PC = r->R.PC = (Inst*)strtol(pc+3, nil, 0); /* for debugging */ 954 } 955 print("[%s] Broken: \"%s\"\n", m->name, estr); 956 } 957 958 snprint(msg, sizeof(msg), "%d \"%s\":%s", r->pid, m->name, estr); 959 960 if(up->env->debug != nil) { 961 dbgexit(r, broken, estr); 962 broken = 1; 963 /* must force it to break if in debug */ 964 }else if(broken && (!keepbroken || strncmp(estr, "out of memory", 13)==0 || memusehigh())) 965 broken = 0; /* don't want them or short of memory */ 966 967 if(broken){ 968 tellsomeone(r, msg); 969 r = isave(); 970 r->state = Pbroken; 971 return; 972 } 973 974 gclock(); 975 destroystack(&R); 976 delprog(r, msg); 977 gcunlock(); 978 979 if(isched.head == nil) 980 cleanexit(0); 981 } 982 983 void 984 disfault(void *reg, char *msg) 985 { 986 Prog *p; 987 988 USED(reg); 989 990 if(strncmp(msg, Eintr, 6) == 0) 991 exits(0); 992 993 if(up == nil) { 994 print("EMU: faults: %s\n", msg); 995 cleanexit(0); 996 } 997 if(up->type != Interp) { 998 print("SYS: process %s faults: %s\n", up->text, msg); 999 cleanexit(0); 1000 } 1001 1002 if(up->iprog != nil) 1003 acquire(); 1004 1005 p = currun(); 1006 if(p == nil) 1007 panic("Interp faults with no dis prog"); 1008 1009 /* cause an exception in the dis prog. As for error(), but Plan 9 needs reg*/ 1010 kstrcpy(up->env->errstr, msg, ERRMAX); 1011 oslongjmp(reg, up->estack[--up->nerr], 1); 1012 } 1013 1014 void 1015 vmachine(void *a) 1016 { 1017 Prog *r; 1018 Osenv *o; 1019 int cycles; 1020 static int gccounter; 1021 1022 USED(a); 1023 1024 startup(); 1025 1026 while(waserror()) { 1027 if(up->iprog != nil) 1028 acquire(); 1029 if(handler(up->env->errstr) == 0) { 1030 propex(currun(), up->env->errstr); 1031 progexit(); 1032 } 1033 up->env = &up->defenv; 1034 } 1035 1036 cycles = 0; 1037 for(;;) { 1038 if(tready(nil) == 0) { 1039 execatidle(); 1040 strcpy(up->text, "idle"); 1041 Sleep(&isched.irend, tready, 0); 1042 strcpy(up->text, "dis"); 1043 } 1044 1045 if(isched.vmq != nil && (isched.runhd == nil || ++cycles > 2)){ 1046 iyield(); 1047 cycles = 0; 1048 } 1049 1050 r = isched.runhd; 1051 if(r != nil) { 1052 o = r->osenv; 1053 up->env = o; 1054 1055 FPrestore(&o->fpu); 1056 r->xec(r); 1057 FPsave(&o->fpu); 1058 1059 if(isched.runhd != nil) 1060 if(r == isched.runhd) 1061 if(isched.runhd != isched.runtl) { 1062 isched.runhd = r->link; 1063 r->link = nil; 1064 isched.runtl->link = r; 1065 isched.runtl = r; 1066 } 1067 up->env = &up->defenv; 1068 } 1069 if(isched.runhd != nil) 1070 if((++gccounter&0xFF) == 0 || memlow()) { 1071 gcbusy++; 1072 up->type = BusyGC; 1073 pushrun(up->prog); 1074 rungc(isched.head); 1075 up->type = Interp; 1076 delrunq(up->prog); 1077 } 1078 } 1079 } 1080 1081 void 1082 disinit(void *a) 1083 { 1084 Prog *p; 1085 Osenv *o; 1086 Module *root; 1087 char *initmod = a; 1088 1089 if(waserror()) 1090 panic("disinit error: %r"); 1091 1092 if(vflag) 1093 print("Initial Dis: \"%s\"\n", initmod); 1094 1095 fmtinstall('D', Dconv); 1096 1097 FPinit(); 1098 FPsave(&up->env->fpu); 1099 1100 opinit(); 1101 modinit(); 1102 excinit(); 1103 1104 root = load(initmod); 1105 if(root == 0) { 1106 kgerrstr(up->genbuf, sizeof up->genbuf); 1107 panic("loading \"%s\": %s", initmod, up->genbuf); 1108 } 1109 1110 p = schedmod(root); 1111 1112 memmove(p->osenv, up->env, sizeof(Osenv)); 1113 o = p->osenv; 1114 incref(&o->pgrp->r); 1115 incref(&o->fgrp->r); 1116 incref(&o->egrp->r); 1117 if(o->sigs != nil) 1118 incref(&o->sigs->r); 1119 o->user = nil; 1120 kstrdup(&o->user, up->env->user); 1121 o->errstr = o->errbuf0; 1122 o->syserrstr = o->errbuf1; 1123 1124 isched.idle = 1; 1125 poperror(); 1126 vmachine(nil); 1127 } 1128 1129 void 1130 pushrun(Prog *p) 1131 { 1132 if(p->addrun != nil) 1133 panic("pushrun addrun"); 1134 p->state = Pready; 1135 p->link = isched.runhd; 1136 isched.runhd = p; 1137 if(p->link == nil) 1138 isched.runtl = p; 1139 } 1140