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