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