1*9a747e4fSDavid du Colombier #include <u.h> 2*9a747e4fSDavid du Colombier #include <libc.h> 3*9a747e4fSDavid du Colombier #include <thread.h> 4*9a747e4fSDavid du Colombier #include "threadimpl.h" 5*9a747e4fSDavid du Colombier 6*9a747e4fSDavid du Colombier typedef struct Mainarg Mainarg; 7*9a747e4fSDavid du Colombier struct Mainarg 8*9a747e4fSDavid du Colombier { 9*9a747e4fSDavid du Colombier int argc; 10*9a747e4fSDavid du Colombier char **argv; 11*9a747e4fSDavid du Colombier }; 12*9a747e4fSDavid du Colombier 13*9a747e4fSDavid du Colombier int mainstacksize; 14*9a747e4fSDavid du Colombier int _threadnotefd; 15*9a747e4fSDavid du Colombier int _threadpasserpid; 16*9a747e4fSDavid du Colombier static jmp_buf _mainjmp; 17*9a747e4fSDavid du Colombier static void mainlauncher(void*); 18*9a747e4fSDavid du Colombier extern void (*_sysfatal)(char*, va_list); 19*9a747e4fSDavid du Colombier extern void (*__assert)(char*); 20*9a747e4fSDavid du Colombier 21*9a747e4fSDavid du Colombier void 22*9a747e4fSDavid du Colombier main(int argc, char **argv) 23*9a747e4fSDavid du Colombier { 24*9a747e4fSDavid du Colombier Mainarg *a; 25*9a747e4fSDavid du Colombier Proc *p; 26*9a747e4fSDavid du Colombier 27*9a747e4fSDavid du Colombier rfork(RFREND); 28*9a747e4fSDavid du Colombier if(p = (Proc*)setjmp(_mainjmp)) 29*9a747e4fSDavid du Colombier _schedinit(p); 30*9a747e4fSDavid du Colombier 31*9a747e4fSDavid du Colombier //_threaddebuglevel = (DBGSCHED|DBGCHAN|DBGREND)^~0; 32*9a747e4fSDavid du Colombier _systhreadinit(); 33*9a747e4fSDavid du Colombier _qlockinit(_threadrendezvous); 34*9a747e4fSDavid du Colombier _sysfatal = _threadsysfatal; 35*9a747e4fSDavid du Colombier __assert = _threadassert; 36*9a747e4fSDavid du Colombier notify(_threadnote); 37*9a747e4fSDavid du Colombier if(mainstacksize == 0) 38*9a747e4fSDavid du Colombier mainstacksize = 8*1024; 39*9a747e4fSDavid du Colombier 40*9a747e4fSDavid du Colombier a = _threadmalloc(sizeof *a, 1); 41*9a747e4fSDavid du Colombier a->argc = argc; 42*9a747e4fSDavid du Colombier a->argv = argv; 43*9a747e4fSDavid du Colombier 44*9a747e4fSDavid du Colombier p = _newproc(mainlauncher, a, mainstacksize, "threadmain", 0, 0); 45*9a747e4fSDavid du Colombier _schedinit(p); 46*9a747e4fSDavid du Colombier abort(); /* not reached */ 47*9a747e4fSDavid du Colombier } 48*9a747e4fSDavid du Colombier 49*9a747e4fSDavid du Colombier static void 50*9a747e4fSDavid du Colombier mainlauncher(void *arg) 51*9a747e4fSDavid du Colombier { 52*9a747e4fSDavid du Colombier Mainarg *a; 53*9a747e4fSDavid du Colombier 54*9a747e4fSDavid du Colombier a = arg; 55*9a747e4fSDavid du Colombier threadmain(a->argc, a->argv); 56*9a747e4fSDavid du Colombier threadexits("threadmain"); 57*9a747e4fSDavid du Colombier } 58*9a747e4fSDavid du Colombier 59*9a747e4fSDavid du Colombier static char* 60*9a747e4fSDavid du Colombier skip(char *p) 61*9a747e4fSDavid du Colombier { 62*9a747e4fSDavid du Colombier while(*p == ' ') 63*9a747e4fSDavid du Colombier p++; 64*9a747e4fSDavid du Colombier while(*p != ' ' && *p != 0) 65*9a747e4fSDavid du Colombier p++; 66*9a747e4fSDavid du Colombier return p; 67*9a747e4fSDavid du Colombier } 68*9a747e4fSDavid du Colombier 69*9a747e4fSDavid du Colombier static long 70*9a747e4fSDavid du Colombier _times(long *t) 71*9a747e4fSDavid du Colombier { 72*9a747e4fSDavid du Colombier char b[200], *p; 73*9a747e4fSDavid du Colombier int f; 74*9a747e4fSDavid du Colombier ulong r; 75*9a747e4fSDavid du Colombier 76*9a747e4fSDavid du Colombier memset(b, 0, sizeof(b)); 77*9a747e4fSDavid du Colombier f = open("/dev/cputime", OREAD|OCEXEC); 78*9a747e4fSDavid du Colombier if(f < 0) 79*9a747e4fSDavid du Colombier return 0; 80*9a747e4fSDavid du Colombier if(read(f, b, sizeof(b)) <= 0){ 81*9a747e4fSDavid du Colombier close(f); 82*9a747e4fSDavid du Colombier return 0; 83*9a747e4fSDavid du Colombier } 84*9a747e4fSDavid du Colombier p = b; 85*9a747e4fSDavid du Colombier if(t) 86*9a747e4fSDavid du Colombier t[0] = atol(p); 87*9a747e4fSDavid du Colombier p = skip(p); 88*9a747e4fSDavid du Colombier if(t) 89*9a747e4fSDavid du Colombier t[1] = atol(p); 90*9a747e4fSDavid du Colombier p = skip(p); 91*9a747e4fSDavid du Colombier r = atol(p); 92*9a747e4fSDavid du Colombier if(t){ 93*9a747e4fSDavid du Colombier p = skip(p); 94*9a747e4fSDavid du Colombier t[2] = atol(p); 95*9a747e4fSDavid du Colombier p = skip(p); 96*9a747e4fSDavid du Colombier t[3] = atol(p); 97*9a747e4fSDavid du Colombier } 98*9a747e4fSDavid du Colombier return r; 99*9a747e4fSDavid du Colombier } 100*9a747e4fSDavid du Colombier 101*9a747e4fSDavid du Colombier static void 102*9a747e4fSDavid du Colombier efork(Execargs *e) 103*9a747e4fSDavid du Colombier { 104*9a747e4fSDavid du Colombier char buf[ERRMAX]; 105*9a747e4fSDavid du Colombier 106*9a747e4fSDavid du Colombier _threaddebug(DBGEXEC, "_schedexec %s", e->prog); 107*9a747e4fSDavid du Colombier close(e->fd[0]); 108*9a747e4fSDavid du Colombier exec(e->prog, e->args); 109*9a747e4fSDavid du Colombier _threaddebug(DBGEXEC, "_schedexec failed: %r"); 110*9a747e4fSDavid du Colombier rerrstr(buf, sizeof buf); 111*9a747e4fSDavid du Colombier if(buf[0]=='\0') 112*9a747e4fSDavid du Colombier strcpy(buf, "exec failed"); 113*9a747e4fSDavid du Colombier write(e->fd[1], buf, strlen(buf)); 114*9a747e4fSDavid du Colombier close(e->fd[1]); 115*9a747e4fSDavid du Colombier _exits(buf); 116*9a747e4fSDavid du Colombier } 117*9a747e4fSDavid du Colombier 118*9a747e4fSDavid du Colombier int 119*9a747e4fSDavid du Colombier _schedexec(Execargs *e) 120*9a747e4fSDavid du Colombier { 121*9a747e4fSDavid du Colombier int pid; 122*9a747e4fSDavid du Colombier 123*9a747e4fSDavid du Colombier switch(pid = rfork(RFREND|RFNOTEG|RFFDG|RFMEM|RFPROC)){ 124*9a747e4fSDavid du Colombier case 0: 125*9a747e4fSDavid du Colombier efork(e); 126*9a747e4fSDavid du Colombier default: 127*9a747e4fSDavid du Colombier return pid; 128*9a747e4fSDavid du Colombier } 129*9a747e4fSDavid du Colombier } 130*9a747e4fSDavid du Colombier 131*9a747e4fSDavid du Colombier int 132*9a747e4fSDavid du Colombier _schedfork(Proc *p) 133*9a747e4fSDavid du Colombier { 134*9a747e4fSDavid du Colombier int pid; 135*9a747e4fSDavid du Colombier 136*9a747e4fSDavid du Colombier switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT|p->rforkflag)){ 137*9a747e4fSDavid du Colombier case 0: 138*9a747e4fSDavid du Colombier longjmp(_mainjmp, (int)p); 139*9a747e4fSDavid du Colombier default: 140*9a747e4fSDavid du Colombier return pid; 141*9a747e4fSDavid du Colombier } 142*9a747e4fSDavid du Colombier } 143*9a747e4fSDavid du Colombier 144*9a747e4fSDavid du Colombier void 145*9a747e4fSDavid du Colombier _schedexit(Proc *p) 146*9a747e4fSDavid du Colombier { 147*9a747e4fSDavid du Colombier char ex[ERRMAX]; 148*9a747e4fSDavid du Colombier Proc **l; 149*9a747e4fSDavid du Colombier 150*9a747e4fSDavid du Colombier lock(&_threadpq.lock); 151*9a747e4fSDavid du Colombier for(l=&_threadpq.head; *l; l=&(*l)->next){ 152*9a747e4fSDavid du Colombier if(*l == p){ 153*9a747e4fSDavid du Colombier *l = p->next; 154*9a747e4fSDavid du Colombier if(*l == nil) 155*9a747e4fSDavid du Colombier _threadpq.tail = l; 156*9a747e4fSDavid du Colombier break; 157*9a747e4fSDavid du Colombier } 158*9a747e4fSDavid du Colombier } 159*9a747e4fSDavid du Colombier unlock(&_threadpq.lock); 160*9a747e4fSDavid du Colombier 161*9a747e4fSDavid du Colombier utfecpy(ex, ex+sizeof ex, p->exitstr); 162*9a747e4fSDavid du Colombier free(p); 163*9a747e4fSDavid du Colombier _exits(ex); 164*9a747e4fSDavid du Colombier } 165*9a747e4fSDavid du Colombier 166*9a747e4fSDavid du Colombier void 167*9a747e4fSDavid du Colombier _schedexecwait(void) 168*9a747e4fSDavid du Colombier { 169*9a747e4fSDavid du Colombier int pid; 170*9a747e4fSDavid du Colombier Channel *c; 171*9a747e4fSDavid du Colombier Proc *p; 172*9a747e4fSDavid du Colombier Thread *t; 173*9a747e4fSDavid du Colombier Waitmsg *w; 174*9a747e4fSDavid du Colombier 175*9a747e4fSDavid du Colombier p = _threadgetproc(); 176*9a747e4fSDavid du Colombier t = p->thread; 177*9a747e4fSDavid du Colombier pid = t->ret; 178*9a747e4fSDavid du Colombier _threaddebug(DBGEXEC, "_schedexecwait %d", t->ret); 179*9a747e4fSDavid du Colombier 180*9a747e4fSDavid du Colombier rfork(RFCFDG); 181*9a747e4fSDavid du Colombier for(;;){ 182*9a747e4fSDavid du Colombier w = wait(); 183*9a747e4fSDavid du Colombier if(w == nil) 184*9a747e4fSDavid du Colombier break; 185*9a747e4fSDavid du Colombier if(w->pid == pid) 186*9a747e4fSDavid du Colombier break; 187*9a747e4fSDavid du Colombier free(w); 188*9a747e4fSDavid du Colombier } 189*9a747e4fSDavid du Colombier if(w != nil){ 190*9a747e4fSDavid du Colombier if((c = _threadwaitchan) != nil) 191*9a747e4fSDavid du Colombier sendp(c, w); 192*9a747e4fSDavid du Colombier else 193*9a747e4fSDavid du Colombier free(w); 194*9a747e4fSDavid du Colombier } 195*9a747e4fSDavid du Colombier threadexits("procexec"); 196*9a747e4fSDavid du Colombier } 197*9a747e4fSDavid du Colombier 198*9a747e4fSDavid du Colombier static Proc **procp; 199*9a747e4fSDavid du Colombier 200*9a747e4fSDavid du Colombier void 201*9a747e4fSDavid du Colombier _systhreadinit(void) 202*9a747e4fSDavid du Colombier { 203*9a747e4fSDavid du Colombier procp = privalloc(); 204*9a747e4fSDavid du Colombier } 205*9a747e4fSDavid du Colombier 206*9a747e4fSDavid du Colombier Proc* 207*9a747e4fSDavid du Colombier _threadgetproc(void) 208*9a747e4fSDavid du Colombier { 209*9a747e4fSDavid du Colombier return *procp; 210*9a747e4fSDavid du Colombier } 211*9a747e4fSDavid du Colombier 212*9a747e4fSDavid du Colombier void 213*9a747e4fSDavid du Colombier _threadsetproc(Proc *p) 214*9a747e4fSDavid du Colombier { 215*9a747e4fSDavid du Colombier *procp = p; 216*9a747e4fSDavid du Colombier } 217