xref: /plan9/sys/src/libthread/main.c (revision b8b257802f7f811fbf50141a6401409bebd29327)
19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <thread.h>
49a747e4fSDavid du Colombier #include "threadimpl.h"
59a747e4fSDavid du Colombier 
69a747e4fSDavid du Colombier typedef struct Mainarg Mainarg;
79a747e4fSDavid du Colombier struct Mainarg
89a747e4fSDavid du Colombier {
99a747e4fSDavid du Colombier 	int	argc;
109a747e4fSDavid du Colombier 	char	**argv;
119a747e4fSDavid du Colombier };
129a747e4fSDavid du Colombier 
139a747e4fSDavid du Colombier int	mainstacksize;
149a747e4fSDavid du Colombier int	_threadnotefd;
159a747e4fSDavid du Colombier int	_threadpasserpid;
169a747e4fSDavid du Colombier static jmp_buf _mainjmp;
179a747e4fSDavid du Colombier static void mainlauncher(void*);
189a747e4fSDavid du Colombier extern void (*_sysfatal)(char*, va_list);
199a747e4fSDavid du Colombier extern void (*__assert)(char*);
20*b8b25780SDavid du Colombier extern int (*_dial)(char*, char*, char*, int*);
21*b8b25780SDavid du Colombier 
22*b8b25780SDavid du Colombier extern int _threaddial(char*, char*, char*, int*);
23*b8b25780SDavid du Colombier 
2474f16c81SDavid du Colombier static Proc **mainp;
259a747e4fSDavid du Colombier 
269a747e4fSDavid du Colombier void
main(int argc,char ** argv)279a747e4fSDavid du Colombier main(int argc, char **argv)
289a747e4fSDavid du Colombier {
299a747e4fSDavid du Colombier 	Mainarg *a;
309a747e4fSDavid du Colombier 	Proc *p;
319a747e4fSDavid du Colombier 
329a747e4fSDavid du Colombier 	rfork(RFREND);
3374f16c81SDavid du Colombier 	mainp = &p;
3474f16c81SDavid du Colombier 	if(setjmp(_mainjmp))
359a747e4fSDavid du Colombier 		_schedinit(p);
369a747e4fSDavid du Colombier 
379a747e4fSDavid du Colombier //_threaddebuglevel = (DBGSCHED|DBGCHAN|DBGREND)^~0;
389a747e4fSDavid du Colombier 	_systhreadinit();
399a747e4fSDavid du Colombier 	_qlockinit(_threadrendezvous);
409a747e4fSDavid du Colombier 	_sysfatal = _threadsysfatal;
41*b8b25780SDavid du Colombier 	_dial = _threaddial;
429a747e4fSDavid du Colombier 	__assert = _threadassert;
439a747e4fSDavid du Colombier 	notify(_threadnote);
449a747e4fSDavid du Colombier 	if(mainstacksize == 0)
459a747e4fSDavid du Colombier 		mainstacksize = 8*1024;
469a747e4fSDavid du Colombier 
479a747e4fSDavid du Colombier 	a = _threadmalloc(sizeof *a, 1);
489a747e4fSDavid du Colombier 	a->argc = argc;
499a747e4fSDavid du Colombier 	a->argv = argv;
509a747e4fSDavid du Colombier 
519a747e4fSDavid du Colombier 	p = _newproc(mainlauncher, a, mainstacksize, "threadmain", 0, 0);
529a747e4fSDavid du Colombier 	_schedinit(p);
539a747e4fSDavid du Colombier 	abort();	/* not reached */
549a747e4fSDavid du Colombier }
559a747e4fSDavid du Colombier 
569a747e4fSDavid du Colombier static void
mainlauncher(void * arg)579a747e4fSDavid du Colombier mainlauncher(void *arg)
589a747e4fSDavid du Colombier {
599a747e4fSDavid du Colombier 	Mainarg *a;
609a747e4fSDavid du Colombier 
619a747e4fSDavid du Colombier 	a = arg;
629a747e4fSDavid du Colombier 	threadmain(a->argc, a->argv);
639a747e4fSDavid du Colombier 	threadexits("threadmain");
649a747e4fSDavid du Colombier }
659a747e4fSDavid du Colombier 
669a747e4fSDavid du Colombier static char*
skip(char * p)679a747e4fSDavid du Colombier skip(char *p)
689a747e4fSDavid du Colombier {
699a747e4fSDavid du Colombier 	while(*p == ' ')
709a747e4fSDavid du Colombier 		p++;
719a747e4fSDavid du Colombier 	while(*p != ' ' && *p != 0)
729a747e4fSDavid du Colombier 		p++;
739a747e4fSDavid du Colombier 	return p;
749a747e4fSDavid du Colombier }
759a747e4fSDavid du Colombier 
769a747e4fSDavid du Colombier static long
_times(long * t)779a747e4fSDavid du Colombier _times(long *t)
789a747e4fSDavid du Colombier {
799a747e4fSDavid du Colombier 	char b[200], *p;
809a747e4fSDavid du Colombier 	int f;
819a747e4fSDavid du Colombier 	ulong r;
829a747e4fSDavid du Colombier 
839a747e4fSDavid du Colombier 	memset(b, 0, sizeof(b));
849a747e4fSDavid du Colombier 	f = open("/dev/cputime", OREAD|OCEXEC);
859a747e4fSDavid du Colombier 	if(f < 0)
869a747e4fSDavid du Colombier 		return 0;
879a747e4fSDavid du Colombier 	if(read(f, b, sizeof(b)) <= 0){
889a747e4fSDavid du Colombier 		close(f);
899a747e4fSDavid du Colombier 		return 0;
909a747e4fSDavid du Colombier 	}
919a747e4fSDavid du Colombier 	p = b;
929a747e4fSDavid du Colombier 	if(t)
939a747e4fSDavid du Colombier 		t[0] = atol(p);
949a747e4fSDavid du Colombier 	p = skip(p);
959a747e4fSDavid du Colombier 	if(t)
969a747e4fSDavid du Colombier 		t[1] = atol(p);
979a747e4fSDavid du Colombier 	p = skip(p);
989a747e4fSDavid du Colombier 	r = atol(p);
999a747e4fSDavid du Colombier 	if(t){
1009a747e4fSDavid du Colombier 		p = skip(p);
1019a747e4fSDavid du Colombier 		t[2] = atol(p);
1029a747e4fSDavid du Colombier 		p = skip(p);
1039a747e4fSDavid du Colombier 		t[3] = atol(p);
1049a747e4fSDavid du Colombier 	}
1059a747e4fSDavid du Colombier 	return r;
1069a747e4fSDavid du Colombier }
1079a747e4fSDavid du Colombier 
1089a747e4fSDavid du Colombier static void
efork(Execargs * e)1099a747e4fSDavid du Colombier efork(Execargs *e)
1109a747e4fSDavid du Colombier {
1119a747e4fSDavid du Colombier 	char buf[ERRMAX];
1129a747e4fSDavid du Colombier 
1139a747e4fSDavid du Colombier 	_threaddebug(DBGEXEC, "_schedexec %s", e->prog);
1149a747e4fSDavid du Colombier 	close(e->fd[0]);
1159a747e4fSDavid du Colombier 	exec(e->prog, e->args);
1169a747e4fSDavid du Colombier 	_threaddebug(DBGEXEC, "_schedexec failed: %r");
1179a747e4fSDavid du Colombier 	rerrstr(buf, sizeof buf);
1189a747e4fSDavid du Colombier 	if(buf[0]=='\0')
1199a747e4fSDavid du Colombier 		strcpy(buf, "exec failed");
1209a747e4fSDavid du Colombier 	write(e->fd[1], buf, strlen(buf));
1219a747e4fSDavid du Colombier 	close(e->fd[1]);
1229a747e4fSDavid du Colombier 	_exits(buf);
1239a747e4fSDavid du Colombier }
1249a747e4fSDavid du Colombier 
1259a747e4fSDavid du Colombier int
_schedexec(Execargs * e)1269a747e4fSDavid du Colombier _schedexec(Execargs *e)
1279a747e4fSDavid du Colombier {
1289a747e4fSDavid du Colombier 	int pid;
1299a747e4fSDavid du Colombier 
1309a747e4fSDavid du Colombier 	switch(pid = rfork(RFREND|RFNOTEG|RFFDG|RFMEM|RFPROC)){
1319a747e4fSDavid du Colombier 	case 0:
1329a747e4fSDavid du Colombier 		efork(e);
1339a747e4fSDavid du Colombier 	default:
1349a747e4fSDavid du Colombier 		return pid;
1359a747e4fSDavid du Colombier 	}
1369a747e4fSDavid du Colombier }
1379a747e4fSDavid du Colombier 
1389a747e4fSDavid du Colombier int
_schedfork(Proc * p)1399a747e4fSDavid du Colombier _schedfork(Proc *p)
1409a747e4fSDavid du Colombier {
1419a747e4fSDavid du Colombier 	int pid;
1429a747e4fSDavid du Colombier 
1439a747e4fSDavid du Colombier 	switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT|p->rforkflag)){
1449a747e4fSDavid du Colombier 	case 0:
14574f16c81SDavid du Colombier 		*mainp = p;	/* write to stack, so local to proc */
14674f16c81SDavid du Colombier 		longjmp(_mainjmp, 1);
1479a747e4fSDavid du Colombier 	default:
1489a747e4fSDavid du Colombier 		return pid;
1499a747e4fSDavid du Colombier 	}
1509a747e4fSDavid du Colombier }
1519a747e4fSDavid du Colombier 
1529a747e4fSDavid du Colombier void
_schedexit(Proc * p)1539a747e4fSDavid du Colombier _schedexit(Proc *p)
1549a747e4fSDavid du Colombier {
1559a747e4fSDavid du Colombier 	char ex[ERRMAX];
1569a747e4fSDavid du Colombier 	Proc **l;
1579a747e4fSDavid du Colombier 
1589a747e4fSDavid du Colombier 	lock(&_threadpq.lock);
1599a747e4fSDavid du Colombier 	for(l=&_threadpq.head; *l; l=&(*l)->next){
1609a747e4fSDavid du Colombier 		if(*l == p){
1619a747e4fSDavid du Colombier 			*l = p->next;
1629a747e4fSDavid du Colombier 			if(*l == nil)
1639a747e4fSDavid du Colombier 				_threadpq.tail = l;
1649a747e4fSDavid du Colombier 			break;
1659a747e4fSDavid du Colombier 		}
1669a747e4fSDavid du Colombier 	}
1679a747e4fSDavid du Colombier 	unlock(&_threadpq.lock);
1689a747e4fSDavid du Colombier 
1699a747e4fSDavid du Colombier 	utfecpy(ex, ex+sizeof ex, p->exitstr);
1709a747e4fSDavid du Colombier 	free(p);
1719a747e4fSDavid du Colombier 	_exits(ex);
1729a747e4fSDavid du Colombier }
1739a747e4fSDavid du Colombier 
1749a747e4fSDavid du Colombier void
_schedexecwait(void)1759a747e4fSDavid du Colombier _schedexecwait(void)
1769a747e4fSDavid du Colombier {
1779a747e4fSDavid du Colombier 	int pid;
1789a747e4fSDavid du Colombier 	Channel *c;
1799a747e4fSDavid du Colombier 	Proc *p;
1809a747e4fSDavid du Colombier 	Thread *t;
1819a747e4fSDavid du Colombier 	Waitmsg *w;
1829a747e4fSDavid du Colombier 
1839a747e4fSDavid du Colombier 	p = _threadgetproc();
1849a747e4fSDavid du Colombier 	t = p->thread;
1859a747e4fSDavid du Colombier 	pid = t->ret;
1869a747e4fSDavid du Colombier 	_threaddebug(DBGEXEC, "_schedexecwait %d", t->ret);
1879a747e4fSDavid du Colombier 
1889a747e4fSDavid du Colombier 	rfork(RFCFDG);
1899a747e4fSDavid du Colombier 	for(;;){
1909a747e4fSDavid du Colombier 		w = wait();
1919a747e4fSDavid du Colombier 		if(w == nil)
1929a747e4fSDavid du Colombier 			break;
1939a747e4fSDavid du Colombier 		if(w->pid == pid)
1949a747e4fSDavid du Colombier 			break;
1959a747e4fSDavid du Colombier 		free(w);
1969a747e4fSDavid du Colombier 	}
1979a747e4fSDavid du Colombier 	if(w != nil){
1989a747e4fSDavid du Colombier 		if((c = _threadwaitchan) != nil)
1999a747e4fSDavid du Colombier 			sendp(c, w);
2009a747e4fSDavid du Colombier 		else
2019a747e4fSDavid du Colombier 			free(w);
2029a747e4fSDavid du Colombier 	}
2039a747e4fSDavid du Colombier 	threadexits("procexec");
2049a747e4fSDavid du Colombier }
2059a747e4fSDavid du Colombier 
2069a747e4fSDavid du Colombier static Proc **procp;
2079a747e4fSDavid du Colombier 
2089a747e4fSDavid du Colombier void
_systhreadinit(void)2099a747e4fSDavid du Colombier _systhreadinit(void)
2109a747e4fSDavid du Colombier {
2119a747e4fSDavid du Colombier 	procp = privalloc();
2129a747e4fSDavid du Colombier }
2139a747e4fSDavid du Colombier 
2149a747e4fSDavid du Colombier Proc*
_threadgetproc(void)2159a747e4fSDavid du Colombier _threadgetproc(void)
2169a747e4fSDavid du Colombier {
2179a747e4fSDavid du Colombier 	return *procp;
2189a747e4fSDavid du Colombier }
2199a747e4fSDavid du Colombier 
2209a747e4fSDavid du Colombier void
_threadsetproc(Proc * p)2219a747e4fSDavid du Colombier _threadsetproc(Proc *p)
2229a747e4fSDavid du Colombier {
2239a747e4fSDavid du Colombier 	*procp = p;
2249a747e4fSDavid du Colombier }
225