#include <u.h>
#include <libc.h>
#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);
}
|