shithub: drawcpu

ref: 23109a6631eb21b2d849807b470c239d71d09159
dir: /kern/syscall.c/

View raw version
#include "u.h"
#include "lib.h"
#include "dat.h"
#include "fns.h"
#include "error.h"
#include "user.h"
#include "sys.h"
#include "proc.h"

static void
setcexec(int fd, int flags)
{
	Chan *c;
	c = up->fgrp->fd[fd];   // get the Chan we just stored
	if(c != nil){
    	if(flags & OCEXEC)
        	c->flag |= CCEXEC;
    	else
        	c->flag &= ~CCEXEC;
	}
}

static void *
emalloc(int n)
{
	void *p;
	if(n==0)
		n=1;
	p = malloc(n);
	if(p == nil)
		sysfatal("out of memory");
	memset(p, 0, n);
	setmalloctag(p, getcallerpc(&n));
	return p;
}

static u32int
arg(int n)
{
	/* no locking necessary, since we're on the stack */
	return *(u32int*) vaddrnol(up->R[13] + 4 + 4 * n, 4);
}

static u64int
argv(int n)
{
	return arg(n) | ((u64int)arg(n+1) << 32);
}

u32int
noteerr(u32int x, u32int y)
{
	if(((int)x) >= ((int)y))
		return x;
	rerrstr(up->errstr, ERRMAX);
	return x;
}

void
cherrstr(char *str, ...)
{
	va_list va;
	
	va_start(va, str);
	vsnprint(up->errstr, ERRMAX, str, va);
	va_end(va);
}

static void
_sysr1(void)
{
	if(!iseve())
		error(Eperm);
	up->R[0] = 0;
}

static void
_sysopen(void)
{
	u32int name, flags;
	char *namet;
	int fd, copied;
	
	name = arg(0);
	flags = arg(1);
	namet = copyifnec(name, -1, &copied);
	fd = open(namet, flags);
#ifdef DSYSCALL
	print("sysopen: pid=%d, fd=%ld name=%s flags=%lux\n", up->pid, fd, namet, flags);
#endif
	if(copied)
		free(namet);
	if(fd < 0) {
		noteerr(0, 1);
		up->R[0] = fd;
		return;
	}
	setcexec(fd, flags & OCEXEC);
	up->R[0] = fd;
}

static void
_syscreate(void)
{
	u32int name, flags, perm;
	char *namet;
	int fd, copied;
	
	name = arg(0);
	flags = arg(1);
	perm = arg(2);
	namet = copyifnec(name, -1, &copied);
	fd = create(namet, flags, perm);
#ifdef DSYSCALL
	print("syscreate: pid=%d, fd=%ld name=%s\n", up->pid, fd, namet);
#endif
	if(copied)
		free(namet);
	if(fd < 0) {
		noteerr(0, 1);
		up->R[0] = fd;
		return;
	}
	setcexec(fd, flags & OCEXEC);
	up->R[0] = fd;
}

static void
_sysclose(void)
{
	u32int fd;
	
	fd = arg(0);
#ifdef DSYSCALL
	print("sysclose: pid=%d, fd=%ld\n",up->pid, fd);
#endif
	up->R[0] = noteerr(close(fd), 0);
	if((fd & (1<<31)) == 0)
		setcexec(fd, 0);
}

static void
_syspread(void)
{
	int buffered;
	u32int fd, size, buf;
	u64int off;
	void *targ;
	
	fd = arg(0);
	buf = arg(1);
	size = arg(2);
	off = argv(3);
#ifdef DSYSCALL
	print("syspread: pid=%d, fd=%ld size=0x%lux off=0x%lux\n", up->pid, fd, size, off);
#endif
	targ = bufifnec(buf, size, &buffered);
	up->R[0] = noteerr(pread(fd, targ, size, off), size);
	if(buffered)
		copyback(buf, up->R[0], targ);
}

static void
_syspwrite(void)
{
	u32int fd, size, buf;
	u64int off;
	int copied;
	void *buft;
	
	fd = arg(0);
	buf = arg(1);
	size = arg(2);
	off = argv(3);
	buft = copyifnec(buf, size, &copied);
#ifdef DSYSCALL
	print("syspwrite: pid=%d, fd=%ld buf=%s size=%lux off=%lux\n", up->pid, fd, buft, size, off);
#endif
	up->R[0] = noteerr(pwrite(fd, buft, size, off), size);
	if(copied)
		free(buft);
}

static void
_sysseek(void)
{
	u32int fd, type;
	vlong n, *ret;
	Segment *seg;
	
	ret = vaddr(arg(0), 8, &seg);
	fd = arg(1);
	n = argv(2);
	type = arg(4);
#ifdef DSYSCALL
	print("sysseek: pid=%d, to=%d whence=%lux\n", up->pid, n, type);
#endif
	*ret = seek(fd, n, type);
	if(*ret < 0) noteerr(0, 1);
	segunlock(seg);
}

static void
_sysfd2path(void)
{
	u32int fd, buf, nbuf;
	void *buft;
	int buffered;
	
	fd = arg(0);
	buf = arg(1);
	nbuf = arg(2);
	buft = bufifnec(buf, nbuf, &buffered);
#ifdef DSYSCALL
	print("fd2path\n");
#endif
	up->R[0] = noteerr(fd2path(fd, buft, nbuf), 0);
	if(buffered)
		copyback(buf, nbuf, buft);
}

static void
_sysstat(void)
{
    u32int name, edir, nedir;
    char *namet;
    void *edirt;
    int copied, buffered;

    name = arg(0);
    namet = copyifnec(name, -1, &copied);
    edir = arg(1); 
    nedir = arg(2);
	edirt = bufifnec(edir, nedir, &buffered);
#ifdef DSYSCALL
	print("sysstat: pid=%d, name=%s, edir=%s, nedir=%d\n", up->pid, namet, edirt, nedir);
#endif
    up->R[0] = noteerr(stat(namet, edirt, nedir), nedir);
    if (copied)
        free(namet);
    if (buffered)
        copyback(edir, up->R[0], edirt);
}

static void
_sysfstat(void)
{
	u32int fd, edir, nedir;
	void *edirt;
	int buffered;

	fd = arg(0);
	edir = arg(1);
	nedir = arg(2);
	edirt = bufifnec(edir, nedir, &buffered);
#ifdef DSYSCALL
	print("sysfstat: pid=%d edir=%s, nedir=%d\n", up->pid, edirt, nedir);
#endif
	up->R[0] = noteerr(fstat(fd, edirt, nedir), nedir);
	if(buffered)
		copyback(edir, up->R[0], edirt);
}

static void
_syswstat(void)
{
	u32int name, edir, nedir;
	char *namet;
	void *edirt;
	int copied, copied2;
	
	name = arg(0);
	namet = copyifnec(name, -1, &copied);
	edir = arg(1);
	nedir = arg(2);
	edirt = copyifnec(edir, nedir, &copied2);
#ifdef DSYSCALL
	print("syswstate: pid=%d, dir=%s, name=%s\n", up->pid, edirt, namet);
#endif
	up->R[0] = noteerr(wstat(namet, edirt, nedir), nedir);
	if(copied)
		free(namet);
	if(copied2)
		free(edirt);
}

static void
_sysfwstat(void)
{
	u32int fd, edir, nedir;
	void *edirt;
	int copied;
	
	fd = arg(0);
	edir = arg(1);
	nedir = arg(2);
	edirt = copyifnec(edir, nedir, &copied);
#ifdef DSYSCALL
	print("sysfwstat: pid=%d, fd=%ld, edir=%us, nedir=%d, copied=%d\n", up->pid, fd, edirt, nedir, copied);
#endif
	up->R[0] = noteerr(fwstat(fd, edirt, nedir), nedir);
	if(copied)
		free(edirt);
}

static void
_sysexits(void)
{
	if(arg(0) == 0) {
#ifdef DSYSCALL
		print("sysexits: pid=%d\n", up->pid);
#endif
		pexit("", 0);
	} else {
#ifdef DSYSCALL
		print("sysexits: pid=%d, status=%s\n", up->pid, vaddrnol(arg(0), 0));
#endif
		pexit(vaddrnol(arg(0), 0), 0);		
	}
}

static void
_sysbrk(void)
{
	ulong v;
	Segment *s;

	v = arg(0);
	v = (v + 7) & -8;
#ifdef DSYSCALL
	print("sysbrk: pid=%d v=%#lux\n", up->pid, v);
#endif
	if(v >= up->seg[ESEG]->start)
		panic("bss > stack, wtf?");
	if(v < up->seg[BSEG]->start)
		panic("bss length < 0, wtf?");
	s = up->seg[BSEG];
	wlock(&s->rw);
	s->dref = realloc(s->dref, v - s->start + sizeof(Ref));
	if(s->dref == nil)
		panic("error reallocating");
	s->data = s->dref + 1;
	if(s->size < v - s->start)
		memset((char*)s->data + s->size, 0, v - s->start - s->size);
	s->size = v - s->start;
	up->R[0] = 0;
	wunlock(&s->rw);
}

static void
_sys_errstr(void)
{
	/* Old binaries, implement if needed */
}

static void
_syserrstr(void)
{
	char buf[ERRMAX], *srct;
	u32int src, len;
	int copied;

	src = arg(0);
	len = arg(1);
	srct = copyifnec(src, len, &copied);
	strcpy(buf, up->errstr);
	utfecpy(up->errstr, up->errstr + ERRMAX, srct);
	utfecpy(srct, srct + len, buf);
	if(copied)
		copyback(src, len, srct);
#ifdef DSYSCALL
	print("syserrstr: pid=%d, buf=%s\n", up->pid, buf);
#endif
	up->R[0] = 0;
}

static void
_syschdir(void)
{
	u32int dir;
	char *dirt;
	int copied;
	
	dir = arg(0);
	dirt = copyifnec(dir, -1, &copied);
#ifdef DSYSCALL
	print("syschdir: pid=%d\n", up->pid);
#endif
	up->R[0] = noteerr(chdir(dirt), 0);
	if(copied)
		free(dirt);
}

static void
_sysnotify(void)
{
	u32int ft;
	Segment *s;
	int (*f)(void*, char*);

#ifdef DSYSCALL
	print("sysnotify: pid=%d\n", up->pid);
#endif
	ft = arg(0);
	f = vaddr(ft, 0, &s);
	up->notify = f;
	up->R[0] = 0;
	segunlock(s);
}

int
donotify(Ureg *ureg)
{
	char *msg;

	//if(up->procctl)
	//	procctl();
	if(up->nnote == 0)
		return 0;

	qlock(&up->debug);
	msg = popnote(ureg);
	if(msg == nil){
		qunlock(&up->debug);
		return 0;
	}
	qunlock(&up->debug);

	if(up->notify == nil){
		if(up->lastnote->flag == NDebug)
			pprint("suicide: %s\n", msg);
		pexit(msg, up->lastnote->flag!=NDebug);
	}

	return 1;
}

static void
_sysnoted(void)
{
	u32int v;
	// TODO: Move to Ureg structure outright

	v = arg(0);
#ifdef DSYSCALL
	print("sysnoted: pid=%d\n", up->pid);
#endif

	switch(v){
	case NCONT: /* Resume at point where notified */
	case NRSTR: /* Restore from NSAVE point*/
		/* word under Ureg is old ureg */
		//up->noteureg = *(Ureg**)((uintptr)nureg-8);
		/* wet floor */
	case NSAVE: /* Set save point to return to */
		//if(noted(up->dbgreg, nureg, arg)){
		//	pprint("suicide: trap in noted\n");
		//	pexit("Suicide", 0);
		//}
		break;
	default:
		up->lastnote->flag = NDebug;
		/* fall through */
	case NDFLT: /* Perform default action */
		//noted(up->dbgreg, nureg, v);	/* for debugging */
		if(up->lastnote->flag == NDebug)
			pprint("suicide: %s\n", up->lastnote->msg);
		pexit(up->lastnote->msg, up->lastnote->flag!=NDebug);
	}
}

static void
_sysrfork(void)
{
	u32int flags;

	flags = arg(0);
#ifdef DSYSCALL
	print("sysrfork(%#o) for proc pid=%lud\n", flags, up->pid);
#endif
	up->R[0] = noteerr(rfork(flags), 0);
}

static void
_sysexec(void)
{
	u32int name, argv, *argvt;
	char *namet, **argvv;
	int i, argc, rc;
	Segment *seg1, *seg2;
	
	name = arg(0);
	argv = arg(1);
	namet = strdup(vaddr(name, 0, &seg1));
	segunlock(seg1);
	argvt = vaddr(argv, 0, &seg1);
#ifdef DSYSCALL
	print("sysexec(%#ux=\"%s\", %#ux) pid=%d\n", name, namet, argv, up->pid);
#endif
	for(argc = 0; argvt[argc]; argc++)
		;
	argvv = emalloc(sizeof(char *) * argc);
	for(i = 0; i < argc; i++) {
		argvv[i] = strdup(vaddr(argvt[i], 0, &seg2));
		segunlock(seg2);
	}
	segunlock(seg1);

	/* Close files marked close-on-exec */
    if(up->fgrp != nil) {
        Chan *c;
        lock(&up->fgrp->lk);
        for(i = 2; i <= up->fgrp->maxfd; i++) {
            c = up->fgrp->fd[i];
            if(c != nil && (c->flag & CCEXEC)) {
                up->fgrp->fd[i] = nil;
                cclose(c);
            }
        }
        unlock(&up->fgrp->lk);
    }

	rc = loadtext(namet, argc, argvv);

	for(i = 0; i < argc; i++)
		free(argvv[i]);
	free(argvv);
	if(rc < 0)
		up->R[0] = noteerr(rc, 0);
	free(namet);
}

static void
_syssegbrk(void)
{
    uintptr newbrk;
    Segment *s;
    uintptr base, oldbrk, oldsize, newsize;
    Ref *newdref;

    newbrk = arg(0);  /* requested new break address */

    /* Case: segbrk(0) → return current break (like sbrk(0)) */
    if(newbrk == 0) {
        s = up->seg[BSEG];
        if(s == nil || s->start == 0) {
            werrstr("no data segment");
            up->R[0] = (int)-1;
            return;
        }
        up->R[0] = s->start + s->size;
        return;
    }

    /*
     * Find the segment containing the address 'newbrk'.
     * We reuse vaddr() with len=1 — it locks the segment if needed.
     */
    s = nil;
    vaddr(newbrk, 1, &s);  /* will panic on segfault, which is fine */

    /* Now s is valid and properly locked (rlock if SEGFLLOCK) */

    /* Only allow growing BSS or attached memory segments */
    if((s->type & SG_TYPE) != SG_BSS && s->type != SG_PHYSICAL) {
        segunlock(s);
        werrstr("segment not growable");
        up->R[0] = (int)-1;
        return;
    }

    base = s->start;
    oldbrk = base + s->size;
    oldsize = s->size;

    /* Must be trying to grow (or stay the same) */
    if(newbrk < oldbrk) {
        segunlock(s);
        werrstr("shrinking not supported");
        up->R[0] = (int)-1;
        return;
    }

    if(newbrk == oldbrk) {
        /* No change — just return current break */
        up->R[0] = oldbrk;
        segunlock(s);
        return;
    }

    /* Round up to 8-byte alignment (like your original _sysbrk) */
    newsize = (newbrk - base + 7) & ~7;

    /* Reallocate the data buffer */
    newdref = realloc(s->dref, newsize + sizeof(Ref));
    if(newdref == nil) {
        segunlock(s);
        werrstr("out of memory");
        up->R[0] = (int)-1;
        return;
    }

    /* Zero the new portion */
    memset((char*)(newdref + 1) + oldsize, 0, newsize - oldsize);

    /* Update segment */
    s->dref = newdref;
    s->data = newdref + 1;
    s->size = newsize;

    /* Success: return old break */
    up->R[0] = oldbrk;

    segunlock(s);
}

static void
_sysawait(void)
{
	u32int p, n;
	Waitmsg w;
	char *pt;
	int copied;

	p = arg(0);
	n = arg(1);
	pt = copyifnec(p, 1, &copied);
#ifdef DSYSCALL
	print("sysawait: pid=%d, n=%ux, pt=%s\n", up->pid, n, pt);
#endif
	pwait(&w);
	up->R[0] = (uintptr)snprint(pt, n, "%d %lud %lud %lud %q",
		w.pid,
	 	1000, 1000, 1000,
		//w.time[TUser], w.time[TSys], w.time[TReal],
		w.msg);
	if(copied)
		free(pt);
}

static void
_syspipe(void)
{
	u32int fd, *fdt;
	int buffered;
	
	fd = arg(0);
	fdt = bufifnec(fd, 8, &buffered);
#ifdef DSYSCALL
	print("syspipe: pid=%d\n", up->pid);
#endif
	up->R[0] = noteerr(pipe((int *) fdt), 0);
	if(buffered)
		copyback(fd, 8, fdt);
}

static void
_sysdup(void)
{
	u32int oldfd, newfd;
	
	oldfd = arg(0);
	newfd = arg(1);
#ifdef DSYSCALL
	print("sysdup: pid=%d\n", up->pid);
#endif
	up->R[0] = noteerr(dup(oldfd, newfd), 0);
}

static void
_syssleep(void)
{
	u32int n;
	
	n = arg(0);
#ifdef DSYSCALL
	print("syssleep: pid=%d nsec=%.8ux\n", up->pid, n);
#endif
	if(n <= 0)
		osyield();
	else
		osmsleep(n*1000);
	up->R[0] = 0;
}

static void
_sysrendezvous(void)
{
	uintptr_t tag, value;
	
	tag = arg(0);
	value = arg(1);
#ifdef DSYSCALL
	print("sysrendezvous: pid=%d, tag=%.8ux, value=%.8ux\n", up->pid, tag, value);
#endif
	up->R[0] = (u32int)(uintptr_t)(rendezvous((void*)(uintptr_t)tag, (void*)(uintptr_t)value));
	if(up->R[0] == ~0)
		noteerr(0, 1);
}

static void
_sysmount(void)
{
	u32int fd, afd, old, flag, aname;
	char *oldt, *anamet;
	int copiedold, copiedaname;
	
	fd = arg(0);
	afd = arg(1);
	old = arg(2);
	flag = arg(3);
	aname = arg(4);
	oldt = copyifnec(old, -1, &copiedold);
	if(aname) {
		anamet = copyifnec(aname, -1, &copiedaname);
		if(!anamet) 
			anamet = "";
#ifdef DSYSCALL
		print("sysmount: pid=%d, fd=%ld, afd=%ld, aname=%s, oldt=%s\n", up->pid, fd, afd, anamet, oldt);
#endif
	} else {
		anamet = nil;
		copiedaname = 0;
#ifdef DSYSCALL
		print("sysmount: pid=%d, fd=%ld, afd=%ld, oldt=%s\n", fd, afd, up->pid, oldt);
#endif
	}
	up->R[0] = noteerr(mount(fd, afd, oldt, flag, anamet), 0);
	if(copiedold)
		free(oldt);
	if(copiedaname)
		free(anamet);
}

static void
_sysbind(void)
{
	u32int name, old, flags;
	char *namet, *oldt;
	int copiedname, copiedold;
	
	name = arg(0);
	old = arg(1);
	flags = arg(2);
	namet = copyifnec(name, -1, &copiedname);
	oldt = copyifnec(old, -1, &copiedold);
#ifdef DSYSCALL
	print("sysbind: pid=%d, name=%s, old=%s\n", up->pid, namet, oldt);
#endif
	up->R[0] = noteerr(bind(namet, oldt, flags), 0);
	if(copiedname)
		free(namet);
	if(copiedold)
		free(oldt);
}

static void
_sysunmount(void)
{
	u32int name, old;
	char *namet, *oldt;
	int copiedname, copiedold;
	
	name = arg(0);
	old = arg(1);
	oldt = copyifnec(old, -1, &copiedold);
#ifdef DSYSCALL
	print("sysunmount: pid=%d, name=%s, old=%s\n", up->pid, name, oldt);
#endif
	if(name == 0) {
		namet = nil;
		copiedname = 0;
		up->R[0] = noteerr(unmount(nil, oldt), 0);
	} else {
		namet = copyifnec(name, -1, &copiedname);
		up->R[0] = noteerr(unmount(namet, oldt), 0);
	}
	if(copiedold)
		free(oldt);
	if(copiedname)
		free(namet);
}

static void
_sys_fsession(void)
{
	/* deprecated; backwards compatibility only */
}


static void
_sysfauth(void)
{
	u32int name;
	Chan *c, *ac;
	char *aname;
	int fd, afd, copied;

	fd = arg(0);
	name = arg(1);
	aname = copyifnec(name, -1, &copied);
	if(!aname || aname[0] == '\0') {
		up->R[0] = -1;
		return;
	}
	c = fdtochan(fd, ORDWR, 0, 1);
	if(waserror()){
		cclose(c);
		nexterror();
	}
#ifdef DSYSCALL
	print("sysfauth: pid=%d\n", up->pid);
#endif
	ac = mntauth(c, aname);
	/* at this point ac is responsible for keeping c alive */
	poperror();	/* c */
	cclose(c);

	if(waserror()){
		cclose(ac);
		nexterror();
	}

	afd = newfd(ac);
	print("afd: %d\n", afd);
	up->R[0] = afd;
	poperror(); /* ac */
}

static void
_sys_wait(void)
{
	ulong pid;
	Waitmsg w;
	u32int ow;
	OWaitmsg *owt;
	Segment *seg;

	ow = arg(0);
	print("SYSWAIT\n");
	owt = vaddr(ow, 0, &seg);
	if(owt == nil)
		pid = pwait(nil);
	else {
		validaddr((uintptr)owt, sizeof(OWaitmsg), 1);
		pid = pwait(&w);
	}
	if(owt != nil){
		readnum(0, owt->pid, NUMSIZE, w.pid, NUMSIZE);
		//readnum(0, owt->time+TUser*NUMSIZE, NUMSIZE, w.time[TUser], NUMSIZE);
		//readnum(0, owt->time+TSys*NUMSIZE, NUMSIZE, w.time[TSys], NUMSIZE);
		//readnum(0, owt->time+TReal*NUMSIZE, NUMSIZE, w.time[TReal], NUMSIZE);
		strncpy(owt->msg, w.msg, sizeof(owt->msg)-1);
		owt->msg[sizeof(owt->msg)-1] = '\0';
	}
	up->R[0] = pid;
	segunlock(seg);
}

static void
_sysremove(void)
{
	u32int file;
	char *filet;
	int copied;
	
	file = arg(0);
	filet = copyifnec(file, -1, &copied);
#ifdef DSYSCALL
	print("sysremove: pid=%d, file=%s\n", up->pid, filet);
#endif
	up->R[0] = noteerr(remove(filet), 0);
	if(copied)
		free(filet);
}

static void
_sysalarm(void)
{
	u32int msec;
	
	msec = arg(0);
#ifdef DSYSCALL
	print("sysalarm: pid=%d, msec=%.8ux\n", up->pid, msec);
#endif
	up->R[0] = alarm(msec);
}

static void
_syssemacquire(void)
{
	u32int addr, block;
	long *addrt;

	addr = arg(0);
	block = arg(1);
	addrt = vaddrnol(addr, 4);
#ifdef DSYSCALL
	print("syssemacquire: pid=%d, addr=%s, block=%.8ux\n", up->pid, addrt, block);
#endif
	up->R[0] = noteerr(semacquire(addrt, block), 0);
}

static void
_syssemrelease(void)
{
	u32int addr, count;
	long *addrt;
	Segment *seg;

	addr = arg(0);
	count = arg(1);
	addrt = vaddr(addr, 4, &seg);
#ifdef DSYSCALL
		print("syssemrelease: pid=%d, addr=%s, count=%.8ux\n", up->pid, addrt, count);
#endif
	up->R[0] = noteerr(semrelease(addrt, count), 0);
	segunlock(seg);
}

void
_syscall(void)
{

    u32int n;
    static void (*calls[])(void) = {
		[SYSR1]			= _sysr1,
		[_ERRSTR]		= _sys_errstr,
		[BIND]			= _sysbind,
		[CHDIR]			= _syschdir,
		[CLOSE]			= _sysclose,
		[DUP]			= _sysdup,
		[ALARM]			= _sysalarm,
		[EXEC]			= _sysexec,
		[EXITS] 		= _sysexits,
		[_FSESSION]		= _sys_fsession,
		[FAUTH]			= _sysfauth,
		//[_FSTAT]		= _sys_fstat,
		[SEGBRK]		= _syssegbrk,
		//[_MOUNT]		= _sys_mount,
		[OPEN]			= _sysopen,
		//[_READ]			= _sys_read,
		//[OSEEK]			= _sysoseek,
		[SLEEP]			= _syssleep,
		//[_STAT]			= _sys_stat,
		[RFORK]			= _sysrfork,
		//[_WRITE]			= _sys_write,
		[PIPE]			= _syspipe,
		[CREATE]		= _syscreate,
		[FD2PATH]		= _sysfd2path,
		[BRK_]			= _sysbrk,
		[REMOVE]		= _sysremove,
		//[_WSTAT]		= _sys_wstat,
		//[_FWSTAT]		= _sys_fwstat,
		[NOTIFY] 		= _sysnotify,
		[NOTED]			= _sysnoted,
		//[SEGATTACH]		= _syssegattach,
		//[SEGDETACH]		= _syssegdetach,
		//[SEGFREE]			= _syssegfree,
		//[SEGFLUSH]		= _syssegflush,
		[RENDEZVOUS]	= _sysrendezvous,
		[UNMOUNT]		= _sysunmount,
		[_WAIT]			= _sys_wait,
		[SEMACQUIRE]	= _syssemacquire,
		[SEMRELEASE]	= _syssemrelease,
		[SEEK]			= _sysseek,
		//[FVERSION]		= _sysfversion,
		[ERRSTR]		= _syserrstr,
		[STAT]			= _sysstat,
		[FSTAT]			= _sysfstat,
		[WSTAT]			= _syswstat,
		[FWSTAT]		= _sysfwstat,
		[MOUNT]			= _sysmount,
		[AWAIT]			= _sysawait,
		[PREAD]			= _syspread,
		[PWRITE]		= _syspwrite,
		//[TSEMACQUIRE]	= _systsemacquire,
		//[_NSEC]			= _sys_nsec,
    };

    n = up->R[0];
    calls[n]();
}