]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libthread/main.c
threadimpl.h: remove Printsize as well (unused)
[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 void
73 efork(Execargs *e)
74 {
75         char buf[ERRMAX];
76
77         _threaddebug(DBGEXEC, "_schedexec %s", e->prog);
78         close(e->fd[0]);
79         exec(e->prog, e->args);
80         _threaddebug(DBGEXEC, "_schedexec failed: %r");
81         rerrstr(buf, sizeof buf);
82         if(buf[0]=='\0')
83                 strcpy(buf, "exec failed");
84         write(e->fd[1], buf, strlen(buf));
85         _exits(buf);
86 }
87
88 int
89 _schedexec(Execargs *e)
90 {
91         int pid, flag;
92
93         flag = (_threadwaitchan == nil) ? RFNOWAIT : 0;
94         switch(pid = rfork(RFREND|RFNOTEG|RFFDG|RFMEM|RFPROC|flag)){
95         case 0:
96                 efork(e);
97         default:
98                 return pid;
99         }
100 }
101
102 int
103 _schedfork(Proc *p)
104 {
105         int pid;
106
107         switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT|p->rforkflag)){
108         case 0:
109                 *mainp = p;     /* write to stack, so local to proc */
110                 longjmp(_mainjmp, 1);
111         default:
112                 return pid;
113         }
114 }
115
116 void
117 _schedexit(Proc *p)
118 {
119         char ex[ERRMAX];
120         Proc **l;
121
122         lock(&_threadpq.lock);
123         for(l=&_threadpq.head; *l; l=&(*l)->next){
124                 if(*l == p){
125                         *l = p->next;
126                         if(*l == nil)
127                                 _threadpq.tail = l;
128                         break;
129                 }
130         }
131         unlock(&_threadpq.lock);
132
133         utfecpy(ex, ex+sizeof ex, p->exitstr);
134         free(p);
135         _exits(ex);
136 }
137
138 void
139 _schedexecwait(void)
140 {
141         int pid;
142         Channel *c;
143         Proc *p;
144         Thread *t;
145         Waitmsg *w;
146
147         p = _threadgetproc();
148         t = p->thread;
149         pid = t->ret;
150         _threaddebug(DBGEXEC, "_schedexecwait %d", t->ret);
151
152         rfork(RFCFDG);
153         for(;;){
154                 w = wait();
155                 if(w == nil)
156                         break;
157                 if(w->pid == pid)
158                         break;
159                 free(w);
160         }
161         if(w != nil){
162                 if((c = _threadwaitchan) != nil)
163                         sendp(c, w);
164                 else
165                         free(w);
166         }
167         threadexits("procexec");
168 }
169
170 static Proc **procp;
171
172 void
173 _systhreadinit(void)
174 {
175         procp = privalloc();
176 }
177
178 Proc*
179 _threadgetproc(void)
180 {
181         return *procp;
182 }
183
184 void
185 _threadsetproc(Proc *p)
186 {
187         *procp = p;
188 }