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
main(int argc,char ** argv)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
mainlauncher(void * arg)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*
skip(char * p)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
_times(long * t)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
efork(Execargs * e)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
_schedexec(Execargs * e)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
_schedfork(Proc * p)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
_schedexit(Proc * p)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
_schedexecwait(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
_systhreadinit(void)209 _systhreadinit(void)
210 {
211 procp = privalloc();
212 }
213
214 Proc*
_threadgetproc(void)215 _threadgetproc(void)
216 {
217 return *procp;
218 }
219
220 void
_threadsetproc(Proc * p)221 _threadsetproc(Proc *p)
222 {
223 *procp = p;
224 }
225