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