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