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