#include #include #include "compat.h" #include "error.h" #include "errstr.h" ulong kerndate; Proc **privup; char *eve; extern void *mainmem; void _assert(char *fmt) { panic("assert failed: %s", fmt); } int errdepth(int ed) { if(ed >= 0 && up->nerrlab != ed) panic("unbalanced error depth: expected %d got %d\n", ed, up->nerrlab); return up->nerrlab; } void newup(char *name) { up = smalloc(sizeof(Proc)); up->user = eve; strncpy(up->name, name, KNAMELEN-1); up->name[KNAMELEN-1] = '\0'; } void kproc(char *name, void (*f)(void *), void *a) { int pid; pid = rfork(RFPROC|RFMEM|RFNOWAIT); switch(pid){ case -1: panic("can't make new thread: %r"); case 0: break; default: return; } newup(name); if(!waserror()) (*f)(a); _exits(nil); } void kexit(void) { _exits(nil); } void initcompat(void) { rfork(RFREND); privup = privalloc(); kerndate = seconds(); eve = getuser(); newup("main"); } int openmode(ulong o) { o &= ~(OTRUNC|OCEXEC|ORCLOSE); if(o > OEXEC) error(Ebadarg); if(o == OEXEC) return OREAD; return o; } void panic(char *fmt, ...) { char buf[512]; char buf2[512]; va_list va; va_start(va, fmt); vseprint(buf, buf+sizeof(buf), fmt, va); va_end(va); sprint(buf2, "panic: %s\n", buf); write(2, buf2, strlen(buf2)); exits("error"); } void* smalloc(ulong n) { void *p; p = mallocz(n, 1); if(p == nil) panic("out of memory"); setmalloctag(p, getcallerpc(&n)); return p; } long seconds(void) { return time(nil); } void error(char *err) { strncpy(up->error, err, ERRMAX); nexterror(); } void nexterror(void) { longjmp(up->errlab[--up->nerrlab], 1); } int readstr(ulong off, char *buf, ulong n, char *str) { int size; size = strlen(str); if(off >= size) return 0; if(off+n > size) n = size-off; memmove(buf, str+off, n); return n; } void _rendsleep(void* tag) { void *value; for(;;){ value = rendezvous(tag, (void*)0x22a891b8); if(value == (void*)0x7f7713f9) break; if(tag != (void*)~0) panic("_rendsleep: rendezvous mismatch"); } } void _rendwakeup(void* tag) { void *value; for(;;){ value = rendezvous(tag, (void*)0x7f7713f9); if(value == (void*)0x22a891b8) break; if(tag != (void*)~0) panic("_rendwakeup: rendezvous mismatch"); } } void rendsleep(Rendez *r, int (*f)(void*), void *arg) { lock(&up->rlock); up->r = r; unlock(&up->rlock); lock(r); /* * if condition happened, never mind */ if(up->intr || f(arg)){ unlock(r); goto Done; } /* * now we are committed to * change state and call scheduler */ if(r->p) panic("double sleep"); r->p = up; unlock(r); _rendsleep(r); Done: lock(&up->rlock); up->r = 0; if(up->intr){ up->intr = 0; unlock(&up->rlock); error(Eintr); } unlock(&up->rlock); } int rendwakeup(Rendez *r) { Proc *p; int rv; lock(r); p = r->p; rv = 0; if(p){ r->p = nil; _rendwakeup(r); rv = 1; } unlock(r); return rv; } void rendintr(void *v) { Proc *p; p = v; lock(&p->rlock); p->intr = 1; if(p->r) rendwakeup(p->r); unlock(&p->rlock); } void rendclearintr(void) { lock(&up->rlock); up->intr = 0; unlock(&up->rlock); }