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**
pidlook(int pid)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
tready(void * a)57 tready(void *a)
58 {
59 USED(a);
60 return isched.runhd != nil || isched.vmq != nil;
61 }
62
63 Prog*
progpid(int pid)64 progpid(int pid)
65 {
66 return *pidlook(pid);
67 }
68
69 Prog*
progn(int n)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
nprog(void)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
accountant(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
execatidle(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*
newprog(Prog * p,Modlink * m)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
delprog(Prog * p,char * msg)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
renameproguser(char * old,char * new)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
tellsomeone(Prog * p,char * buf)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
swiprog(Prog * p)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*
grpleader(Prog * p)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
exprog(Prog * p,char * exc)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
propex(Prog * p,char * estr)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
killprog(Prog * p,char * cause)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
newgrp(Prog * p)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
addgrp(Prog * n,Prog * p)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*
delgrp(Prog * p)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
printgrp(Prog * p,char * v)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
killgrp(Prog * p,char * msg)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
killcomm(Progq ** q)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
addprog(Proc * p)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
cwakeme(Prog * p)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
cdone(void * vp)667 cdone(void *vp)
668 {
669 Prog *p = vp;
670
671 return p->addrun == nil || p->kill != nil;
672 }
673
674 void
cblock(Prog * p)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
addrun(Prog * p)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*
delrun(int state)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
delrunq(Prog * p)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*
delruntail(int state)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*
currun(void)767 currun(void)
768 {
769 return isched.runhd;
770 }
771
772 Prog*
schedmod(Module * m)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
acquire(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
release(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
iyield(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
startup(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
progexit(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
disfault(void * reg,char * msg)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
vmachine(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
disinit(void * a)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
pushrun(Prog * p)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