xref: /plan9/sys/src/libthread/main.c (revision b8b257802f7f811fbf50141a6401409bebd29327)
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