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