19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include "compat.h"
49a747e4fSDavid du Colombier #include "error.h"
59a747e4fSDavid du Colombier
69a747e4fSDavid du Colombier #include "errstr.h"
79a747e4fSDavid du Colombier
89a747e4fSDavid du Colombier ulong kerndate;
99a747e4fSDavid du Colombier Proc **privup;
109a747e4fSDavid du Colombier char *eve;
119a747e4fSDavid du Colombier extern void *mainmem;
129a747e4fSDavid du Colombier
139a747e4fSDavid du Colombier void
_assert(char * fmt)149a747e4fSDavid du Colombier _assert(char *fmt)
159a747e4fSDavid du Colombier {
169a747e4fSDavid du Colombier panic("assert failed: %s", fmt);
179a747e4fSDavid du Colombier }
189a747e4fSDavid du Colombier
199a747e4fSDavid du Colombier int
errdepth(int ed)209a747e4fSDavid du Colombier errdepth(int ed)
219a747e4fSDavid du Colombier {
229a747e4fSDavid du Colombier if(ed >= 0 && up->nerrlab != ed)
239a747e4fSDavid du Colombier panic("unbalanced error depth: expected %d got %d\n", ed, up->nerrlab);
249a747e4fSDavid du Colombier return up->nerrlab;
259a747e4fSDavid du Colombier }
269a747e4fSDavid du Colombier
279a747e4fSDavid du Colombier void
newup(char * name)289a747e4fSDavid du Colombier newup(char *name)
299a747e4fSDavid du Colombier {
309a747e4fSDavid du Colombier up = smalloc(sizeof(Proc));
319a747e4fSDavid du Colombier up->user = eve;
329a747e4fSDavid du Colombier strncpy(up->name, name, KNAMELEN-1);
339a747e4fSDavid du Colombier up->name[KNAMELEN-1] = '\0';
349a747e4fSDavid du Colombier }
359a747e4fSDavid du Colombier
369a747e4fSDavid du Colombier void
kproc(char * name,void (* f)(void *),void * a)379a747e4fSDavid du Colombier kproc(char *name, void (*f)(void *), void *a)
389a747e4fSDavid du Colombier {
399a747e4fSDavid du Colombier int pid;
409a747e4fSDavid du Colombier
419a747e4fSDavid du Colombier pid = rfork(RFPROC|RFMEM|RFNOWAIT);
429a747e4fSDavid du Colombier switch(pid){
439a747e4fSDavid du Colombier case -1:
449a747e4fSDavid du Colombier panic("can't make new thread: %r");
459a747e4fSDavid du Colombier case 0:
469a747e4fSDavid du Colombier break;
479a747e4fSDavid du Colombier default:
489a747e4fSDavid du Colombier return;
499a747e4fSDavid du Colombier }
509a747e4fSDavid du Colombier
519a747e4fSDavid du Colombier newup(name);
529a747e4fSDavid du Colombier if(!waserror())
539a747e4fSDavid du Colombier (*f)(a);
549a747e4fSDavid du Colombier _exits(nil);
559a747e4fSDavid du Colombier }
569a747e4fSDavid du Colombier
579a747e4fSDavid du Colombier void
kexit(void)589a747e4fSDavid du Colombier kexit(void)
599a747e4fSDavid du Colombier {
609a747e4fSDavid du Colombier _exits(nil);
619a747e4fSDavid du Colombier }
629a747e4fSDavid du Colombier
639a747e4fSDavid du Colombier void
initcompat(void)649a747e4fSDavid du Colombier initcompat(void)
659a747e4fSDavid du Colombier {
669a747e4fSDavid du Colombier rfork(RFREND);
679a747e4fSDavid du Colombier privup = privalloc();
689a747e4fSDavid du Colombier kerndate = seconds();
699a747e4fSDavid du Colombier eve = getuser();
709a747e4fSDavid du Colombier newup("main");
719a747e4fSDavid du Colombier }
729a747e4fSDavid du Colombier
739a747e4fSDavid du Colombier int
openmode(ulong o)749a747e4fSDavid du Colombier openmode(ulong o)
759a747e4fSDavid du Colombier {
769a747e4fSDavid du Colombier o &= ~(OTRUNC|OCEXEC|ORCLOSE);
779a747e4fSDavid du Colombier if(o > OEXEC)
789a747e4fSDavid du Colombier error(Ebadarg);
799a747e4fSDavid du Colombier if(o == OEXEC)
809a747e4fSDavid du Colombier return OREAD;
819a747e4fSDavid du Colombier return o;
829a747e4fSDavid du Colombier }
839a747e4fSDavid du Colombier
849a747e4fSDavid du Colombier void
panic(char * fmt,...)859a747e4fSDavid du Colombier panic(char *fmt, ...)
869a747e4fSDavid du Colombier {
879a747e4fSDavid du Colombier char buf[512];
889a747e4fSDavid du Colombier char buf2[512];
899a747e4fSDavid du Colombier va_list va;
909a747e4fSDavid du Colombier
919a747e4fSDavid du Colombier va_start(va, fmt);
929a747e4fSDavid du Colombier vseprint(buf, buf+sizeof(buf), fmt, va);
939a747e4fSDavid du Colombier va_end(va);
949a747e4fSDavid du Colombier sprint(buf2, "panic: %s\n", buf);
959a747e4fSDavid du Colombier write(2, buf2, strlen(buf2));
969a747e4fSDavid du Colombier
979a747e4fSDavid du Colombier exits("error");
989a747e4fSDavid du Colombier }
999a747e4fSDavid du Colombier
1009a747e4fSDavid du Colombier void*
smalloc(ulong n)1019a747e4fSDavid du Colombier smalloc(ulong n)
1029a747e4fSDavid du Colombier {
1039a747e4fSDavid du Colombier void *p;
1049a747e4fSDavid du Colombier
1059a747e4fSDavid du Colombier p = mallocz(n, 1);
1069a747e4fSDavid du Colombier if(p == nil)
1079a747e4fSDavid du Colombier panic("out of memory");
1089a747e4fSDavid du Colombier setmalloctag(p, getcallerpc(&n));
1099a747e4fSDavid du Colombier return p;
1109a747e4fSDavid du Colombier }
1119a747e4fSDavid du Colombier
1129a747e4fSDavid du Colombier long
seconds(void)1139a747e4fSDavid du Colombier seconds(void)
1149a747e4fSDavid du Colombier {
1159a747e4fSDavid du Colombier return time(nil);
1169a747e4fSDavid du Colombier }
1179a747e4fSDavid du Colombier
1189a747e4fSDavid du Colombier void
error(char * err)1199a747e4fSDavid du Colombier error(char *err)
1209a747e4fSDavid du Colombier {
1219a747e4fSDavid du Colombier strncpy(up->error, err, ERRMAX);
1229a747e4fSDavid du Colombier nexterror();
1239a747e4fSDavid du Colombier }
1249a747e4fSDavid du Colombier
1259a747e4fSDavid du Colombier void
nexterror(void)1269a747e4fSDavid du Colombier nexterror(void)
1279a747e4fSDavid du Colombier {
1289a747e4fSDavid du Colombier longjmp(up->errlab[--up->nerrlab], 1);
1299a747e4fSDavid du Colombier }
1309a747e4fSDavid du Colombier
1319a747e4fSDavid du Colombier int
readstr(ulong off,char * buf,ulong n,char * str)1329a747e4fSDavid du Colombier readstr(ulong off, char *buf, ulong n, char *str)
1339a747e4fSDavid du Colombier {
1349a747e4fSDavid du Colombier int size;
1359a747e4fSDavid du Colombier
1369a747e4fSDavid du Colombier size = strlen(str);
1379a747e4fSDavid du Colombier if(off >= size)
1389a747e4fSDavid du Colombier return 0;
1399a747e4fSDavid du Colombier if(off+n > size)
1409a747e4fSDavid du Colombier n = size-off;
1419a747e4fSDavid du Colombier memmove(buf, str+off, n);
1429a747e4fSDavid du Colombier return n;
1439a747e4fSDavid du Colombier }
1449a747e4fSDavid du Colombier
1459a747e4fSDavid du Colombier void
_rendsleep(void * tag)146*74f16c81SDavid du Colombier _rendsleep(void* tag)
1479a747e4fSDavid du Colombier {
148*74f16c81SDavid du Colombier void *value;
1499a747e4fSDavid du Colombier
1509a747e4fSDavid du Colombier for(;;){
151*74f16c81SDavid du Colombier value = rendezvous(tag, (void*)0x22a891b8);
152*74f16c81SDavid du Colombier if(value == (void*)0x7f7713f9)
1539a747e4fSDavid du Colombier break;
154*74f16c81SDavid du Colombier if(tag != (void*)~0)
1559a747e4fSDavid du Colombier panic("_rendsleep: rendezvous mismatch");
1569a747e4fSDavid du Colombier }
1579a747e4fSDavid du Colombier }
1589a747e4fSDavid du Colombier
1599a747e4fSDavid du Colombier void
_rendwakeup(void * tag)160*74f16c81SDavid du Colombier _rendwakeup(void* tag)
1619a747e4fSDavid du Colombier {
162*74f16c81SDavid du Colombier void *value;
1639a747e4fSDavid du Colombier
1649a747e4fSDavid du Colombier for(;;){
165*74f16c81SDavid du Colombier value = rendezvous(tag, (void*)0x7f7713f9);
166*74f16c81SDavid du Colombier if(value == (void*)0x22a891b8)
1679a747e4fSDavid du Colombier break;
168*74f16c81SDavid du Colombier if(tag != (void*)~0)
1699a747e4fSDavid du Colombier panic("_rendwakeup: rendezvous mismatch");
1709a747e4fSDavid du Colombier }
1719a747e4fSDavid du Colombier }
1729a747e4fSDavid du Colombier
1739a747e4fSDavid du Colombier void
rendsleep(Rendez * r,int (* f)(void *),void * arg)1749a747e4fSDavid du Colombier rendsleep(Rendez *r, int (*f)(void*), void *arg)
1759a747e4fSDavid du Colombier {
1769a747e4fSDavid du Colombier lock(&up->rlock);
1779a747e4fSDavid du Colombier up->r = r;
1789a747e4fSDavid du Colombier unlock(&up->rlock);
1799a747e4fSDavid du Colombier
1809a747e4fSDavid du Colombier lock(r);
1819a747e4fSDavid du Colombier
1829a747e4fSDavid du Colombier /*
1839a747e4fSDavid du Colombier * if condition happened, never mind
1849a747e4fSDavid du Colombier */
1859a747e4fSDavid du Colombier if(up->intr || f(arg)){
1869a747e4fSDavid du Colombier unlock(r);
1879a747e4fSDavid du Colombier goto Done;
1889a747e4fSDavid du Colombier }
1899a747e4fSDavid du Colombier
1909a747e4fSDavid du Colombier /*
1919a747e4fSDavid du Colombier * now we are committed to
1929a747e4fSDavid du Colombier * change state and call scheduler
1939a747e4fSDavid du Colombier */
1949a747e4fSDavid du Colombier if(r->p)
1959a747e4fSDavid du Colombier panic("double sleep");
1969a747e4fSDavid du Colombier r->p = up;
1979a747e4fSDavid du Colombier unlock(r);
1989a747e4fSDavid du Colombier
199*74f16c81SDavid du Colombier _rendsleep(r);
2009a747e4fSDavid du Colombier
2019a747e4fSDavid du Colombier Done:
2029a747e4fSDavid du Colombier lock(&up->rlock);
2039a747e4fSDavid du Colombier up->r = 0;
2049a747e4fSDavid du Colombier if(up->intr){
2059a747e4fSDavid du Colombier up->intr = 0;
2069a747e4fSDavid du Colombier unlock(&up->rlock);
2079a747e4fSDavid du Colombier error(Eintr);
2089a747e4fSDavid du Colombier }
2099a747e4fSDavid du Colombier unlock(&up->rlock);
2109a747e4fSDavid du Colombier }
2119a747e4fSDavid du Colombier
2129a747e4fSDavid du Colombier int
rendwakeup(Rendez * r)2139a747e4fSDavid du Colombier rendwakeup(Rendez *r)
2149a747e4fSDavid du Colombier {
2159a747e4fSDavid du Colombier Proc *p;
2169a747e4fSDavid du Colombier int rv;
2179a747e4fSDavid du Colombier
2189a747e4fSDavid du Colombier lock(r);
2199a747e4fSDavid du Colombier p = r->p;
2209a747e4fSDavid du Colombier rv = 0;
2219a747e4fSDavid du Colombier if(p){
2229a747e4fSDavid du Colombier r->p = nil;
223*74f16c81SDavid du Colombier _rendwakeup(r);
2249a747e4fSDavid du Colombier rv = 1;
2259a747e4fSDavid du Colombier }
2269a747e4fSDavid du Colombier unlock(r);
2279a747e4fSDavid du Colombier return rv;
2289a747e4fSDavid du Colombier }
2299a747e4fSDavid du Colombier
2309a747e4fSDavid du Colombier void
rendintr(void * v)2319a747e4fSDavid du Colombier rendintr(void *v)
2329a747e4fSDavid du Colombier {
2339a747e4fSDavid du Colombier Proc *p;
2349a747e4fSDavid du Colombier
2359a747e4fSDavid du Colombier p = v;
2369a747e4fSDavid du Colombier lock(&p->rlock);
2379a747e4fSDavid du Colombier p->intr = 1;
2389a747e4fSDavid du Colombier if(p->r)
2399a747e4fSDavid du Colombier rendwakeup(p->r);
2409a747e4fSDavid du Colombier unlock(&p->rlock);
2419a747e4fSDavid du Colombier }
2429a747e4fSDavid du Colombier
2439a747e4fSDavid du Colombier void
rendclearintr(void)2449a747e4fSDavid du Colombier rendclearintr(void)
2459a747e4fSDavid du Colombier {
2469a747e4fSDavid du Colombier lock(&up->rlock);
2479a747e4fSDavid du Colombier up->intr = 0;
2489a747e4fSDavid du Colombier unlock(&up->rlock);
2499a747e4fSDavid du Colombier }
2509a747e4fSDavid du Colombier
251