]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libthread/main.c
Import sources from 2011-03-30 iso image
[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 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 }