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