251 lines
3.1 KiB
C
251 lines
3.1 KiB
C
#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);
|
|
}
|
|
|