Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#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);
}