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 if(p->group != nil) 463 g->flags |= p->group->flags&Pprivatemem; 464 g->child = nil; 465 pg = delgrp(p); 466 g->head = g->tail = p; 467 p->group = g; 468 if(pg != nil){ 469 g->sib = pg->child; 470 pg->child = g; 471 } 472 g->parent = pg; 473 } 474 475 static void 476 addgrp(Prog *n, Prog *p) 477 { 478 Progs *g; 479 480 n->group = p->group; 481 if((g = n->group) != nil){ 482 n->grpnext = nil; 483 if(g->head != nil){ 484 n->grpprev = g->tail; 485 g->tail->grpnext = n; 486 }else{ 487 n->grpprev = nil; 488 g->head = n; 489 } 490 g->tail = n; 491 } 492 } 493 494 static Progs* 495 delgrp(Prog *p) 496 { 497 Progs *g, *pg, *cg, **l; 498 499 g = p->group; 500 if(g == nil) 501 return nil; 502 if(p->grpprev) 503 p->grpprev->grpnext = p->grpnext; 504 else 505 g->head = p->grpnext; 506 if(p->grpnext) 507 p->grpnext->grpprev = p->grpprev; 508 else 509 g->tail = p->grpprev; 510 p->grpprev = p->grpnext = nil; 511 p->group = nil; 512 513 if(g->head == nil){ 514 /* move up, giving subgroups of groups with no Progs to their parents */ 515 do{ 516 if((pg = g->parent) != nil){ 517 pg = g->parent; 518 for(l = &pg->child; *l != nil && *l != g; l = &(*l)->sib) 519 ; 520 *l = g->sib; 521 } 522 /* put subgroups in new parent group */ 523 while((cg = g->child) != nil){ 524 g->child = cg->sib; 525 cg->parent = pg; 526 if(pg != nil){ 527 cg->sib = pg->child; 528 pg->child = cg; 529 } 530 } 531 free(g); 532 }while((g = pg) != nil && g->head == nil); 533 } 534 return g; 535 } 536 537 void 538 printgrp(Prog *p, char *v) 539 { 540 Progs *g; 541 Prog *q; 542 543 g = p->group; 544 print("%s pid %d grp %d pgrp %d: [pid", v, p->pid, g->id, g->parent!=nil?g->parent->id:0); 545 for(q = g->head; q != nil; q = q->grpnext) 546 print(" %d", q->pid); 547 print(" subgrp"); 548 for(g = g->child; g != nil; g = g->sib) 549 print(" %d", g->id); 550 print("]\n"); 551 } 552 553 int 554 killgrp(Prog *p, char *msg) 555 { 556 int i, npid, *pids; 557 Prog *f; 558 Progs *g; 559 560 /* interpreter has been acquired */ 561 g = p->group; 562 if(g == nil || g->head == nil) 563 return 0; 564 while(g->flags & Pkilled){ 565 release(); 566 acquire(); 567 } 568 npid = 0; 569 for(f = g->head; f != nil; f = f->grpnext) 570 if(f->group != g) 571 panic("killgrp"); 572 else 573 npid++; 574 /* use pids not Prog* because state can change during killprog (eg, in delprog) */ 575 pids = malloc(npid*sizeof(int)); 576 if(pids == nil) 577 error(Enomem); 578 npid = 0; 579 for(f = g->head; f != nil; f = f->grpnext) 580 pids[npid++] = f->pid; 581 g->flags |= Pkilled; 582 if(waserror()) { 583 g->flags &= ~Pkilled; 584 free(pids); 585 nexterror(); 586 } 587 for(i = 0; i < npid; i++) { 588 f = progpid(pids[i]); 589 if(f != nil && f != currun()) 590 killprog(f, msg); 591 } 592 poperror(); 593 g->flags &= ~Pkilled; 594 free(pids); 595 return 1; 596 } 597 598 char changup[] = "channel hangup"; 599 600 void 601 killcomm(Progq **q) 602 { 603 Prog *p; 604 Progq *f; 605 606 for (f = *q; f != nil; f = *q) { 607 *q = f->next; 608 p = f->prog; 609 free(f); 610 if(p == nil) 611 return; 612 p->ptr = nil; 613 switch(p->state) { 614 case Prelease: 615 swiprog(p); 616 break; 617 case Psend: 618 case Precv: 619 p->kill = changup; 620 addrun(p); 621 break; 622 case Palt: 623 altgone(p); 624 break; 625 } 626 } 627 } 628 629 void 630 addprog(Proc *p) 631 { 632 Prog *n; 633 634 n = malloc(sizeof(Prog)); 635 if(n == nil) 636 panic("no memory"); 637 p->prog = n; 638 n->osenv = p->env; 639 } 640 641 static void 642 cwakeme(Prog *p) 643 { 644 Osenv *o; 645 646 p->addrun = nil; 647 o = p->osenv; 648 Wakeup(o->rend); 649 } 650 651 static int 652 cdone(void *vp) 653 { 654 Prog *p = vp; 655 656 return p->addrun == nil || p->kill != nil; 657 } 658 659 void 660 cblock(Prog *p) 661 { 662 Osenv *o; 663 664 p->addrun = cwakeme; 665 o = p->osenv; 666 o->rend = &up->sleep; 667 release(); 668 669 /* 670 * To allow cdone(p) safely after release, 671 * p must be currun before the release. 672 * Exits in the error case with the vm acquired. 673 */ 674 if(waserror()) { 675 acquire(); 676 p->addrun = nil; 677 nexterror(); 678 } 679 Sleep(o->rend, cdone, p); 680 if (p->kill != nil) 681 error(Eintr); 682 poperror(); 683 acquire(); 684 } 685 686 void 687 addrun(Prog *p) 688 { 689 if(p->addrun != 0) { 690 p->addrun(p); 691 return; 692 } 693 p->state = Pready; 694 p->link = nil; 695 if(isched.runhd == nil) 696 isched.runhd = p; 697 else 698 isched.runtl->link = p; 699 700 isched.runtl = p; 701 } 702 703 Prog* 704 delrun(int state) 705 { 706 Prog *p; 707 708 p = isched.runhd; 709 p->state = state; 710 isched.runhd = p->link; 711 if(p->link == nil) 712 isched.runtl = nil; 713 714 return p; 715 } 716 717 void 718 delrunq(Prog *p) 719 { 720 Prog *prev, *f; 721 722 prev = nil; 723 for(f = isched.runhd; f; f = f->link) { 724 if(f == p) 725 break; 726 prev = f; 727 } 728 if(f == nil) 729 return; 730 if(prev == nil) 731 isched.runhd = p->link; 732 else 733 prev->link = p->link; 734 if(p == isched.runtl) 735 isched.runtl = prev; 736 } 737 738 Prog* 739 delruntail(int state) 740 { 741 Prog *p; 742 743 p = isched.runtl; 744 delrunq(p); 745 p->state = state; 746 return p; 747 } 748 749 Prog* 750 currun(void) 751 { 752 return isched.runhd; 753 } 754 755 Prog* 756 schedmod(Module *m) 757 { 758 Heap *h; 759 Type *t; 760 Prog *p; 761 Modlink *ml; 762 Frame f, *fp; 763 764 ml = mklinkmod(m, 0); 765 766 if(m->origmp != H && m->ntype > 0) { 767 t = m->type[0]; 768 h = nheap(t->size); 769 h->t = t; 770 t->ref++; 771 ml->MP = H2D(uchar*, h); 772 newmp(ml->MP, m->origmp, t); 773 } 774 775 p = newprog(nil, ml); 776 h = D2H(ml); 777 h->ref--; 778 p->R.PC = m->entry; 779 fp = &f; 780 R.s = &fp; 781 f.t = m->entryt; 782 newstack(p); 783 initmem(m->entryt, p->R.FP); 784 785 return p; 786 } 787 788 /* 789 static char* 790 m(Prog *p) 791 { 792 if(p) 793 if(p->R.M) 794 if(p->R.M->m) 795 return p->R.M->m->name; 796 return "nil"; 797 } 798 */ 799 800 void 801 acquire(void) 802 { 803 int empty; 804 Prog *p; 805 806 lock(&isched.l); 807 if(isched.idle) { 808 isched.idle = 0; 809 unlock(&isched.l); 810 } 811 else { 812 up->qnext = nil; 813 if(isched.vmq != nil){ 814 empty = 0; 815 isched.vmqt->qnext = up; 816 }else{ 817 isched.vmq = up; 818 empty = 1; 819 } 820 isched.vmqt = up; 821 822 unlock(&isched.l); 823 strcpy(up->text, "acquire"); 824 if(empty) 825 Wakeup(&isched.irend); 826 osblock(); 827 } 828 829 if(up->type == Interp) { 830 p = up->iprog; 831 up->iprog = nil; 832 irestore(p); 833 } 834 else 835 p = up->prog; 836 837 p->state = Pready; 838 p->link = isched.runhd; 839 isched.runhd = p; 840 if(p->link == nil) 841 isched.runtl = p; 842 843 strcpy(up->text, "dis"); 844 } 845 846 void 847 release(void) 848 { 849 Proc *p, **pq; 850 int f; 851 852 if(up->type == Interp) 853 up->iprog = isave(); 854 else 855 delrun(Prelease); 856 857 lock(&isched.l); 858 if(*(pq = &isched.vmq) == nil && *(pq = &isched.idlevmq) == nil) { 859 isched.idle = 1; 860 f = isched.creating; 861 isched.creating = 1; 862 unlock(&isched.l); 863 if(f == 0) 864 kproc("dis", vmachine, nil, 0); 865 return; 866 } 867 p = *pq; 868 *pq = p->qnext; 869 unlock(&isched.l); 870 871 osready(p); /* wake up thread to run VM */ 872 strcpy(up->text, "released"); 873 } 874 875 void 876 iyield(void) 877 { 878 Proc *p; 879 880 lock(&isched.l); 881 p = isched.vmq; 882 if(p == nil) { 883 unlock(&isched.l); 884 return; 885 } 886 isched.nyield++; 887 isched.vmq = p->qnext; 888 889 if(up->iprog != nil) 890 panic("iyield but iprog, type %d", up->type); 891 if(up->type != Interp){ 892 static int once; 893 if(!once++) 894 print("tell charles: #%p->type==%d\n", up, up->type); 895 } 896 up->qnext = isched.idlevmq; 897 isched.idlevmq = up; 898 899 unlock(&isched.l); 900 osready(p); /* wake up acquiring kproc */ 901 strcpy(up->text, "yield"); 902 osblock(); /* sleep */ 903 strcpy(up->text, "dis"); 904 } 905 906 void 907 startup(void) 908 { 909 910 up->type = Interp; 911 up->iprog = nil; 912 913 lock(&isched.l); 914 isched.creating = 0; 915 if(isched.idle) { 916 isched.idle = 0; 917 unlock(&isched.l); 918 return; 919 } 920 up->qnext = isched.idlevmq; 921 isched.idlevmq = up; 922 unlock(&isched.l); 923 924 osblock(); 925 } 926 927 void 928 progexit(void) 929 { 930 Prog *r; 931 Module *m; 932 int broken; 933 char *estr, msg[ERRMAX+2*KNAMELEN]; 934 935 estr = up->env->errstr; 936 broken = 0; 937 if(estr[0] != '\0' && strcmp(estr, Eintr) != 0 && strncmp(estr, "fail:", 5) != 0) 938 broken = 1; 939 940 r = up->iprog; 941 if(r != nil) 942 acquire(); 943 else 944 r = currun(); 945 946 if(*estr == '\0' && r->flags & Pkilled) 947 estr = "killed"; 948 949 m = R.M->m; 950 if(broken){ 951 if(cflag){ /* only works on Plan9 for now */ 952 char *pc = strstr(estr, "pc="); 953 954 if(pc != nil) 955 R.PC = r->R.PC = (Inst*)strtol(pc+3, nil, 0); /* for debugging */ 956 } 957 print("[%s] Broken: \"%s\"\n", m->name, estr); 958 } 959 960 snprint(msg, sizeof(msg), "%d \"%s\":%s", r->pid, m->name, estr); 961 962 if(up->env->debug != nil) { 963 dbgexit(r, broken, estr); 964 broken = 1; 965 /* must force it to break if in debug */ 966 }else if(broken && (!keepbroken || strncmp(estr, "out of memory", 13)==0 || memusehigh())) 967 broken = 0; /* don't want them or short of memory */ 968 969 if(broken){ 970 tellsomeone(r, msg); 971 r = isave(); 972 r->state = Pbroken; 973 return; 974 } 975 976 gclock(); 977 destroystack(&R); 978 delprog(r, msg); 979 gcunlock(); 980 981 if(isched.head == nil) 982 cleanexit(0); 983 } 984 985 void 986 disfault(void *reg, char *msg) 987 { 988 Prog *p; 989 990 USED(reg); 991 992 if(strncmp(msg, Eintr, 6) == 0) 993 exits(0); 994 995 if(up == nil) { 996 print("EMU: faults: %s\n", msg); 997 cleanexit(0); 998 } 999 if(up->type != Interp) { 1000 print("SYS: process %s faults: %s\n", up->text, msg); 1001 cleanexit(0); 1002 } 1003 1004 if(up->iprog != nil) 1005 acquire(); 1006 1007 p = currun(); 1008 if(p == nil) 1009 panic("Interp faults with no dis prog"); 1010 1011 /* cause an exception in the dis prog. As for error(), but Plan 9 needs reg*/ 1012 kstrcpy(up->env->errstr, msg, ERRMAX); 1013 oslongjmp(reg, up->estack[--up->nerr], 1); 1014 } 1015 1016 void 1017 vmachine(void *a) 1018 { 1019 Prog *r; 1020 Osenv *o; 1021 int cycles; 1022 static int gccounter; 1023 1024 USED(a); 1025 1026 startup(); 1027 1028 while(waserror()) { 1029 if(up->iprog != nil) 1030 acquire(); 1031 if(handler(up->env->errstr) == 0) { 1032 propex(currun(), up->env->errstr); 1033 progexit(); 1034 } 1035 up->env = &up->defenv; 1036 } 1037 1038 cycles = 0; 1039 for(;;) { 1040 if(tready(nil) == 0) { 1041 execatidle(); 1042 strcpy(up->text, "idle"); 1043 Sleep(&isched.irend, tready, 0); 1044 strcpy(up->text, "dis"); 1045 } 1046 1047 if(isched.vmq != nil && (isched.runhd == nil || ++cycles > 2)){ 1048 iyield(); 1049 cycles = 0; 1050 } 1051 1052 r = isched.runhd; 1053 if(r != nil) { 1054 o = r->osenv; 1055 up->env = o; 1056 1057 FPrestore(&o->fpu); 1058 r->xec(r); 1059 FPsave(&o->fpu); 1060 1061 if(isched.runhd != nil) 1062 if(r == isched.runhd) 1063 if(isched.runhd != isched.runtl) { 1064 isched.runhd = r->link; 1065 r->link = nil; 1066 isched.runtl->link = r; 1067 isched.runtl = r; 1068 } 1069 up->env = &up->defenv; 1070 } 1071 if(isched.runhd != nil) 1072 if((++gccounter&0xFF) == 0 || memlow()) { 1073 gcbusy++; 1074 up->type = BusyGC; 1075 pushrun(up->prog); 1076 rungc(isched.head); 1077 up->type = Interp; 1078 delrunq(up->prog); 1079 } 1080 } 1081 } 1082 1083 void 1084 disinit(void *a) 1085 { 1086 Prog *p; 1087 Osenv *o; 1088 Module *root; 1089 char *initmod = a; 1090 1091 if(waserror()) 1092 panic("disinit error: %r"); 1093 1094 if(vflag) 1095 print("Initial Dis: \"%s\"\n", initmod); 1096 1097 fmtinstall('D', Dconv); 1098 1099 FPinit(); 1100 FPsave(&up->env->fpu); 1101 1102 opinit(); 1103 modinit(); 1104 excinit(); 1105 1106 root = load(initmod); 1107 if(root == 0) { 1108 kgerrstr(up->genbuf, sizeof up->genbuf); 1109 panic("loading \"%s\": %s", initmod, up->genbuf); 1110 } 1111 1112 p = schedmod(root); 1113 1114 memmove(p->osenv, up->env, sizeof(Osenv)); 1115 o = p->osenv; 1116 incref(&o->pgrp->r); 1117 incref(&o->fgrp->r); 1118 incref(&o->egrp->r); 1119 if(o->sigs != nil) 1120 incref(&o->sigs->r); 1121 o->user = nil; 1122 kstrdup(&o->user, up->env->user); 1123 o->errstr = o->errbuf0; 1124 o->syserrstr = o->errbuf1; 1125 1126 isched.idle = 1; 1127 poperror(); 1128 vmachine(nil); 1129 } 1130 1131 void 1132 pushrun(Prog *p) 1133 { 1134 if(p->addrun != nil) 1135 panic("pushrun addrun"); 1136 p->state = Pready; 1137 p->link = isched.runhd; 1138 isched.runhd = p; 1139 if(p->link == nil) 1140 isched.runtl = p; 1141 } 1142