]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/port/sysproc.c
add _nsec() syscall 53 for binary compatibility with labs distribution
[plan9front.git] / sys / src / 9 / port / sysproc.c
index 0a9bda850b89c50be81ba4f25737234abf0c5110..fbe4f2fbc24b5ba8c7ac3679d0126a22d479115b 100644 (file)
@@ -14,15 +14,23 @@ int shargs(char*, int, char**);
 extern void checkpages(void);
 extern void checkpagerefs(void);
 
-long
-sysr1(ulong*)
+uintptr
+sysr1(va_list)
 {
+       if(!iseve())
+               error(Eperm);
        checkpagerefs();
        return 0;
 }
 
-long
-sysrfork(ulong *arg)
+static void
+abortion(void*)
+{
+       pexit("fork aborted", 1);
+}
+
+uintptr
+sysrfork(va_list list)
 {
        Proc *p;
        int n, i;
@@ -33,7 +41,7 @@ sysrfork(ulong *arg)
        ulong pid, flag;
        Mach *wm;
 
-       flag = arg[0];
+       flag = va_arg(list, ulong);
        /* Check flags before we commit */
        if((flag & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG))
                error(Ebadarg);
@@ -84,7 +92,6 @@ sysrfork(ulong *arg)
 
        p = newproc();
 
-       p->fpsave = up->fpsave;
        p->scallnr = up->scallnr;
        p->s = up->s;
        p->nerrlab = 0;
@@ -102,6 +109,14 @@ sysrfork(ulong *arg)
        p->ureg = up->ureg;
        p->dbgreg = 0;
 
+       /* Abort the child process on error */
+       if(waserror()){
+               p->kp = 1;
+               kprocchild(p, abortion, 0);
+               ready(p);
+               nexterror();
+       }
+
        /* Make a new set of memory segments */
        n = flag & RFMEM;
        qlock(&p->seglock);
@@ -162,6 +177,10 @@ sysrfork(ulong *arg)
        }
        p->hang = up->hang;
        p->procmode = up->procmode;
+       if(up->procctl == Proc_tracesyscall)
+               p->procctl = Proc_tracesyscall;
+
+       poperror();     /* abortion */
 
        /* Craft a return frame which will cause the child to pop out of
         * the scheduler in user mode with the return register zero
@@ -169,10 +188,8 @@ sysrfork(ulong *arg)
        forkchild(p, up->dbgreg);
 
        p->parent = up;
-       p->parentpid = up->pid;
-       if(flag&RFNOWAIT)
-               p->parentpid = 0;
-       else {
+       if((flag&RFNOWAIT) == 0){
+               p->parentpid = up->pid;
                lock(&up->exl);
                up->nchild++;
                unlock(&up->exl);
@@ -180,7 +197,6 @@ sysrfork(ulong *arg)
        if((flag&RFNOTEG) == 0)
                p->noteid = up->noteid;
 
-       p->fpstate = up->fpstate;
        pid = p->pid;
        memset(p->time, 0, sizeof(p->time));
        p->time[TReal] = MACHP(0)->ticks;
@@ -217,34 +233,40 @@ l2be(long l)
        return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
 }
 
-long
-sysexec(ulong *arg)
+uintptr
+sysexec(va_list list)
 {
        Segment *s, *ts;
-       ulong t, d, b;
        int i;
        Chan *tc;
-       char **argv, **argp;
+       char **argv, **argp, **argp0;
        char *a, *charp, *args, *file, *file0;
        char *progarg[sizeof(Exec)/2+1], *elem, progelem[64];
-       ulong ssize, spage, nargs, nbytes, n, bssend;
+       ulong magic, ssize, nargs, nbytes, n;
+       uintptr t, d, b, entry, bssend, text, data, bss, tstk, align;
        int indir;
        Exec exec;
        char line[sizeof(Exec)];
        Fgrp *f;
        Image *img;
-       ulong magic, text, entry, data, bss;
        Tos *tos;
 
-       indir = 0;
-       elem = nil;
-       validaddr(arg[0], 1, 0);
-       file0 = validnamedup((char*)arg[0], 1);
+       args = elem = nil;
+       file0 = va_arg(list, char*);
+       validaddr((uintptr)file0, 1, 0);
+       argp0 = va_arg(list, char**);
+       file0 = validnamedup(file0, 1);
        if(waserror()){
                free(file0);
                free(elem);
+               free(args);
+               /* Disaster after commit */
+               if(!up->seg[SSEG])
+                       pexit(up->errstr, 1);
                nexterror();
        }
+       align = BY2PG;
+       indir = 0;
        file = file0;
        for(;;){
                tc = namec(file, Aopen, OEXEC, 0);
@@ -262,7 +284,11 @@ sysexec(ulong *arg)
                text = l2be(exec.text);
                entry = l2be(exec.entry);
                if(n==sizeof(Exec) && (magic == AOUT_MAGIC)){
-                       if(text >= USTKTOP-UTZERO
+                       if(magic == S_MAGIC){
+                               text += 8;
+                               align = 0x200000ull;    /* 2MB segment alignment for amd64 */
+                       }
+                       if(text >= (USTKTOP-USTKSIZE)-(UTZERO+sizeof(Exec))
                        || entry < UTZERO+sizeof(Exec)
                        || entry >= UTZERO+sizeof(Exec)+text)
                                error(Ebadexec);
@@ -284,8 +310,7 @@ sysexec(ulong *arg)
                 */
                progarg[n++] = file;
                progarg[n] = 0;
-               validaddr(arg[1], BY2WD, 1);
-               arg[1] += BY2WD;
+               argp0++;
                file = progarg[0];
                if(strlen(elem) >= sizeof progelem)
                        error(Ebadexec);
@@ -297,11 +322,13 @@ sysexec(ulong *arg)
 
        data = l2be(exec.data);
        bss = l2be(exec.bss);
-       t = (UTZERO+sizeof(Exec)+text+(BY2PG-1)) & ~(BY2PG-1);
-       d = (t + data + (BY2PG-1)) & ~(BY2PG-1);
+       align--;
+       t = (UTZERO+sizeof(Exec)+text+align) & ~align;
+       align = BY2PG-1;
+       d = (t + data + align) & ~align;
        bssend = t + data + bss;
-       b = (bssend + (BY2PG-1)) & ~(BY2PG-1);
-       if(t >= KZERO || d >= KZERO || b >= KZERO)
+       b = (bssend + align) & ~align;
+       if(t >= (USTKTOP-USTKSIZE) || d >= (USTKTOP-USTKSIZE) || b >= (USTKTOP-USTKSIZE))
                error(Ebadexec);
 
        /*
@@ -317,14 +344,14 @@ sysexec(ulong *arg)
                        nargs++;
                }
        }
-       evenaddr(arg[1]);
-       argp = (char**)arg[1];
-       validaddr((ulong)argp, BY2WD, 0);
+       argp = argp0;
+       evenaddr((uintptr)argp);
+       validaddr((uintptr)argp, BY2WD, 0);
        while(*argp){
                a = *argp++;
-               if(((ulong)argp&(BY2PG-1)) < BY2WD)
-                       validaddr((ulong)argp, BY2WD, 0);
-               validaddr((ulong)a, 1, 0);
+               if(((uintptr)argp&(BY2PG-1)) < BY2WD)
+                       validaddr((uintptr)argp, BY2WD, 0);
+               validaddr((uintptr)a, 1, 0);
                nbytes += ((char*)vmemchr(a, 0, 0x7FFFFFFF) - a) + 1;
                nargs++;
        }
@@ -334,78 +361,72 @@ sysexec(ulong *arg)
         * 8-byte align SP for those (e.g. sparc) that need it.
         * execregs() will subtract another 4 bytes for argc.
         */
-       if((ssize+4) & 7)
+       if(BY2WD == 4 && (ssize+4) & 7)
                ssize += 4;
-       spage = (ssize+(BY2PG-1)) >> PGSHIFT;
+
+       if(PGROUND(ssize) >= USTKSIZE)
+               error(Enovmem);
 
        /*
         * Build the stack segment, putting it in kernel virtual for the moment
         */
-       if(spage > TSTKSIZ)
-               error(Enovmem);
-
        qlock(&up->seglock);
        if(waserror()){
                qunlock(&up->seglock);
                nexterror();
        }
-       up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);
+
+       s = up->seg[SSEG];
+       do {
+               tstk = s->base;
+               if(tstk <= USTKSIZE)
+                       error(Enovmem);
+       } while((s = isoverlap(up, tstk-USTKSIZE, USTKSIZE)) != nil);
+       up->seg[ESEG] = newseg(SG_STACK, tstk-USTKSIZE, USTKSIZE/BY2PG);
 
        /*
         * Args: pass 2: assemble; the pages will be faulted in
         */
-       tos = (Tos*)(TSTKTOP - sizeof(Tos));
+       tos = (Tos*)(tstk - sizeof(Tos));
        tos->cyclefreq = m->cyclefreq;
        tos->kcycles = 0;
        tos->pcycles = 0;
        tos->clock = 0;
 
-       argv = (char**)(TSTKTOP - ssize);
-       charp = (char*)(TSTKTOP - nbytes);
-       args = charp;
+       argv = (char**)(tstk - ssize);
+       charp = (char*)(tstk - nbytes);
+       a = charp;
        if(indir)
                argp = progarg;
        else
-               argp = (char**)arg[1];
+               argp = argp0;
 
        for(i=0; i<nargs; i++){
                if(indir && *argp==0) {
                        indir = 0;
-                       argp = (char**)arg[1];
+                       argp = argp0;
                }
-               *argv++ = charp + (USTKTOP-TSTKTOP);
+               *argv++ = charp + (USTKTOP-tstk);
                n = strlen(*argp) + 1;
                memmove(charp, *argp++, n);
                charp += n;
        }
-       free(file0);
-       file0 = nil;    /* so waserror() won't free file0 */
-       USED(file0);
-
-       free(up->text);
-       up->text = elem;
-       elem = nil;     /* so waserror() won't free elem */
-       USED(elem);
 
        /* copy args; easiest from new process's stack */
-       n = charp - args;
+       n = charp - a;
        if(n > 128)     /* don't waste too much space on huge arg lists */
                n = 128;
-       a = up->args;
-       up->args = nil;
-       free(a);
-       up->args = smalloc(n);
-       memmove(up->args, args, n);
-       if(n>0 && up->args[n-1]!='\0'){
+       args = smalloc(n);
+       memmove(args, a, n);
+       if(n>0 && args[n-1]!='\0'){
                /* make sure last arg is NUL-terminated */
                /* put NUL at UTF-8 character boundary */
                for(i=n-1; i>0; --i)
-                       if(fullrune(up->args+i, n-i))
+                       if(fullrune(args+i, n-i))
                                break;
-               up->args[i] = 0;
+               args[i] = 0;
                n = i+1;
        }
-       up->nargs = n;
 
        /*
         * Committed.
@@ -417,9 +438,9 @@ sysexec(ulong *arg)
                /* prevent a second free if we have an error */
                up->seg[i] = 0;
        }
-       for(i = BSEG+1; i < NSEG; i++) {
+       for(i = ESEG+1; i < NSEG; i++) {
                s = up->seg[i];
-               if(s != 0 && (s->type&SG_CEXEC)) {
+               if(s != 0 && (s->type&SG_CEXEC) != 0) {
                        putseg(s);
                        up->seg[i] = 0;
                }
@@ -428,9 +449,10 @@ sysexec(ulong *arg)
        /*
         * Close on exec
         */
-       f = up->fgrp;
-       for(i=0; i<=f->maxfd; i++)
-               fdclose(i, CCEXEC);
+       if((f = up->fgrp) != nil){
+               for(i=0; i<=f->maxfd; i++)
+                       fdclose(i, CCEXEC);
+       }
 
        /* Text.  Shared. Attaches to cache image if possible */
        /* attachimage returns a locked cache image */
@@ -462,11 +484,10 @@ sysexec(ulong *arg)
        up->seg[ESEG] = 0;
        s->base = USTKTOP-USTKSIZE;
        s->top = USTKTOP;
-       relocateseg(s, USTKTOP-TSTKTOP);
+       relocateseg(s, USTKTOP-tstk);
        up->seg[SSEG] = s;
        qunlock(&up->seglock);
        poperror();     /* seglock */
-       poperror();     /* elem */
 
        /*
         *  '/' processes are higher priority (hack to make /ip more responsive).
@@ -474,10 +495,19 @@ sysexec(ulong *arg)
        if(devtab[tc->type]->dc == L'/')
                up->basepri = PriRoot;
        up->priority = up->basepri;
-       poperror();
+       poperror();     /* tc */
        cclose(tc);
+       poperror();     /* file0 */
+       free(file0);
 
        qlock(&up->debug);
+       free(up->text);
+       up->text = elem;
+       free(up->args);
+       up->args = args;
+       up->nargs = n;
+       up->setargs = 0;
+
        up->nnote = 0;
        up->notify = 0;
        up->notified = 0;
@@ -533,45 +563,45 @@ return0(void*)
        return 0;
 }
 
-long
-syssleep(ulong *arg)
+uintptr
+syssleep(va_list list)
 {
+       long ms;
 
-       int n;
-
-       n = arg[0];
-       if(n <= 0) {
+       ms = va_arg(list, long);
+       if(ms <= 0) {
                if (up->edf && (up->edf->flags & Admitted))
                        edfyield();
                else
                        yield();
-               return 0;
+       } else {
+               if(ms < TK2MS(1))
+                       ms = TK2MS(1);
+               tsleep(&up->sleep, return0, 0, ms);
        }
-       if(n < TK2MS(1))
-               n = TK2MS(1);
-       tsleep(&up->sleep, return0, 0, n);
        return 0;
 }
 
-long
-sysalarm(ulong *arg)
+uintptr
+sysalarm(va_list list)
 {
-       return procalarm(arg[0]);
+       return procalarm(va_arg(list, ulong));
 }
 
-long
-sysexits(ulong *arg)
+
+uintptr
+sysexits(va_list list)
 {
        char *status;
        char *inval = "invalid exit string";
        char buf[ERRMAX];
 
-       status = (char*)arg[0];
+       status = va_arg(list, char*);
        if(status){
                if(waserror())
                        status = inval;
                else{
-                       validaddr((ulong)status, 1, 0);
+                       validaddr((uintptr)status, 1, 0);
                        if(vmemchr(status, 0, ERRMAX) == 0){
                                memmove(buf, status, ERRMAX);
                                buf[ERRMAX-1] = 0;
@@ -582,24 +612,25 @@ sysexits(ulong *arg)
 
        }
        pexit(status, 1);
-       return 0;               /* not reached */
+       return 0;       /* not reached */
 }
 
-long
-sys_wait(ulong *arg)
+uintptr
+sys_wait(va_list list)
 {
-       int pid;
+       ulong pid;
        Waitmsg w;
        OWaitmsg *ow;
 
-       if(arg[0] == 0)
-               return pwait(nil);
-
-       validaddr(arg[0], sizeof(OWaitmsg), 1);
-       evenaddr(arg[0]);
-       pid = pwait(&w);
-       if(pid >= 0){
-               ow = (OWaitmsg*)arg[0];
+       ow = va_arg(list, OWaitmsg*);
+       if(ow == nil)
+               pid = pwait(nil);
+       else {
+               validaddr((uintptr)ow, sizeof(OWaitmsg), 1);
+               evenaddr((uintptr)ow);
+               pid = pwait(&w);
+       }
+       if(ow != nil){
                readnum(0, ow->pid, NUMSIZE, w.pid, NUMSIZE);
                readnum(0, ow->time+TUser*NUMSIZE, NUMSIZE, w.time[TUser], NUMSIZE);
                readnum(0, ow->time+TSys*NUMSIZE, NUMSIZE, w.time[TSys], NUMSIZE);
@@ -610,25 +641,21 @@ sys_wait(ulong *arg)
        return pid;
 }
 
-long
-sysawait(ulong *arg)
+uintptr
+sysawait(va_list list)
 {
-       int i;
-       int pid;
+       char *p;
        Waitmsg w;
-       ulong n;
-
-       n = arg[1];
-       validaddr(arg[0], n, 1);
-       pid = pwait(&w);
-       if(pid < 0)
-               return -1;
-       i = snprint((char*)arg[0], n, "%d %lud %lud %lud %q",
+       uint n;
+
+       p = va_arg(list, char*);
+       n = va_arg(list, uint);
+       validaddr((uintptr)p, n, 1);
+       pwait(&w);
+       return (uintptr)snprint(p, n, "%d %lud %lud %lud %q",
                w.pid,
                w.time[TUser], w.time[TSys], w.time[TReal],
                w.msg);
-
-       return i;
 }
 
 void
@@ -644,14 +671,14 @@ werrstr(char *fmt, ...)
        va_end(va);
 }
 
-static long
+static int
 generrstr(char *buf, uint nbuf)
 {
        char tmp[ERRMAX];
 
        if(nbuf == 0)
                error(Ebadarg);
-       validaddr((ulong)buf, nbuf, 1);
+       validaddr((uintptr)buf, nbuf, 1);
        if(nbuf > sizeof tmp)
                nbuf = sizeof tmp;
        memmove(tmp, buf, nbuf);
@@ -664,44 +691,51 @@ generrstr(char *buf, uint nbuf)
        return 0;
 }
 
-long
-syserrstr(ulong *arg)
+uintptr
+syserrstr(va_list list)
 {
-       return generrstr((char*)arg[0], arg[1]);
+       char *buf;
+       uint len;
+
+       buf = va_arg(list, char*);
+       len = va_arg(list, uint);
+       return (uintptr)generrstr(buf, len);
 }
 
 /* compatibility for old binaries */
-long
-sys_errstr(ulong *arg)
+uintptr
+sys_errstr(va_list list)
 {
-       return generrstr((char*)arg[0], 64);
+       return (uintptr)generrstr(va_arg(list, char*), 64);
 }
 
-long
-sysnotify(ulong *arg)
+uintptr
+sysnotify(va_list list)
 {
-       if(arg[0] != 0)
-               validaddr(arg[0], sizeof(ulong), 0);
-       up->notify = (int(*)(void*, char*))(arg[0]);
+       int (*f)(void*, char*);
+       f = va_arg(list, void*);
+       if(f != 0)
+               validaddr((uintptr)f, sizeof(void*), 0);
+       up->notify = f;
        return 0;
 }
 
-long
-sysnoted(ulong *arg)
+uintptr
+sysnoted(va_list list)
 {
-       if(arg[0]!=NRSTR && !up->notified)
+       if(va_arg(list, int) !=NRSTR && !up->notified)
                error(Egreg);
        return 0;
 }
 
-long
-syssegbrk(ulong *arg)
+uintptr
+syssegbrk(va_list list)
 {
        int i;
-       ulong addr;
+       uintptr addr;
        Segment *s;
 
-       addr = arg[0];
+       addr = va_arg(list, uintptr);
        for(i = 0; i < NSEG; i++) {
                s = up->seg[i];
                if(s == 0 || addr < s->base || addr >= s->top)
@@ -712,27 +746,37 @@ syssegbrk(ulong *arg)
                case SG_STACK:
                        error(Ebadarg);
                default:
-                       return ibrk(arg[1], i);
+                       return (uintptr)ibrk(va_arg(list, uintptr), i);
                }
        }
-
        error(Ebadarg);
-       return 0;               /* not reached */
+       return 0;       /* not reached */
 }
 
-long
-syssegattach(ulong *arg)
+uintptr
+syssegattach(va_list list)
 {
-       return segattach(up, arg[0], (char*)arg[1], arg[2], arg[3]);
+       ulong attr;
+       char *name;
+       uintptr va;
+       ulong len;
+
+       attr = va_arg(list, ulong);
+       name = va_arg(list, char*);
+       va = va_arg(list, uintptr);
+       len = va_arg(list, ulong);
+       return segattach(up, attr, name, va, len);
 }
 
-long
-syssegdetach(ulong *arg)
+uintptr
+syssegdetach(va_list list)
 {
        int i;
-       ulong addr;
+       uintptr addr;
        Segment *s;
 
+       addr = va_arg(list, uintptr);
+
        qlock(&up->seglock);
        if(waserror()){
                qunlock(&up->seglock);
@@ -740,7 +784,6 @@ syssegdetach(ulong *arg)
        }
 
        s = 0;
-       addr = arg[0];
        for(i = 0; i < NSEG; i++)
                if(s = up->seg[i]) {
                        qlock(&s->lk);
@@ -771,17 +814,19 @@ found:
        return 0;
 }
 
-long
-syssegfree(ulong *arg)
+uintptr
+syssegfree(va_list list)
 {
        Segment *s;
-       ulong from, to;
+       uintptr from, to;
 
-       from = arg[0];
+       from = va_arg(list, uintptr);
        s = seg(up, from, 1);
        if(s == nil)
                error(Ebadarg);
-       to = (from + arg[1]) & ~(BY2PG-1);
+       to = va_arg(list, ulong);
+       to += from;
+       to &= ~(BY2PG-1);
        from = PGROUND(from);
 
        if(to > s->top) {
@@ -792,24 +837,24 @@ syssegfree(ulong *arg)
        mfreeseg(s, from, (to - from) / BY2PG);
        qunlock(&s->lk);
        flushmmu();
-
        return 0;
 }
 
 /* For binary compatibility */
-long
-sysbrk_(ulong *arg)
+uintptr
+sysbrk_(va_list list)
 {
-       return ibrk(arg[0], BSEG);
+       return (uintptr)ibrk(va_arg(list, uintptr), BSEG);
 }
 
-long
-sysrendezvous(ulong *arg)
+uintptr
+sysrendezvous(va_list list)
 {
-       uintptr tag, val;
+       uintptr tag, val, new;
        Proc *p, **l;
 
-       tag = arg[0];
+       tag = va_arg(list, uintptr);
+       new = va_arg(list, uintptr);
        l = &REND(up->rgrp, tag);
 
        lock(up->rgrp);
@@ -817,11 +862,11 @@ sysrendezvous(ulong *arg)
                if(p->rendtag == tag) {
                        *l = p->rendhash;
                        val = p->rendval;
-                       p->rendval = arg[1];
+                       p->rendval = new;
                        unlock(up->rgrp);
-                       while(p->mach != 0)
-                               ;
+
                        ready(p);
+
                        return val;
                }
                l = &p->rendhash;
@@ -829,7 +874,7 @@ sysrendezvous(ulong *arg)
 
        /* Going to sleep here */
        up->rendtag = tag;
-       up->rendval = arg[1];
+       up->rendval = new;
        up->rendhash = *l;
        *l = up;
        up->state = Rendezvous;
@@ -1078,58 +1123,75 @@ tsemacquire(Segment *s, long *addr, ulong ms)
        return 1;
 }
 
-long
-syssemacquire(ulong *arg)
+uintptr
+syssemacquire(va_list list)
 {
        int block;
        long *addr;
        Segment *s;
 
-       validaddr(arg[0], sizeof(long), 1);
-       evenaddr(arg[0]);
-       addr = (long*)arg[0];
-       block = arg[1];
-       
-       if((s = seg(up, (ulong)addr, 0)) == nil)
+       addr = va_arg(list, long*);
+       block = va_arg(list, int);
+       evenaddr((uintptr)addr);
+       s = seg(up, (uintptr)addr, 0);
+       if(s == nil || (s->type&SG_RONLY) != 0 || (uintptr)addr+sizeof(long) > s->top){
+               validaddr((uintptr)addr, sizeof(long), 1);
                error(Ebadarg);
+       }
        if(*addr < 0)
                error(Ebadarg);
-       return semacquire(s, addr, block);
+       return (uintptr)semacquire(s, addr, block);
 }
 
-long
-systsemacquire(ulong *arg)
+uintptr
+systsemacquire(va_list list)
 {
        long *addr;
        ulong ms;
        Segment *s;
 
-       validaddr(arg[0], sizeof(long), 1);
-       evenaddr(arg[0]);
-       addr = (long*)arg[0];
-       ms = arg[1];
-
-       if((s = seg(up, (ulong)addr, 0)) == nil)
+       addr = va_arg(list, long*);
+       ms = va_arg(list, ulong);
+       evenaddr((uintptr)addr);
+       s = seg(up, (uintptr)addr, 0);
+       if(s == nil || (s->type&SG_RONLY) != 0 || (uintptr)addr+sizeof(long) > s->top){
+               validaddr((uintptr)addr, sizeof(long), 1);
                error(Ebadarg);
+       }
        if(*addr < 0)
                error(Ebadarg);
-       return tsemacquire(s, addr, ms);
+       return (uintptr)tsemacquire(s, addr, ms);
 }
 
-long
-syssemrelease(ulong *arg)
+uintptr
+syssemrelease(va_list list)
 {
        long *addr, delta;
        Segment *s;
 
-       validaddr(arg[0], sizeof(long), 1);
-       evenaddr(arg[0]);
-       addr = (long*)arg[0];
-       delta = arg[1];
-
-       if((s = seg(up, (ulong)addr, 0)) == nil)
+       addr = va_arg(list, long*);
+       delta = va_arg(list, long);
+       evenaddr((uintptr)addr);
+       s = seg(up, (uintptr)addr, 0);
+       if(s == nil || (s->type&SG_RONLY) != 0 || (uintptr)addr+sizeof(long) > s->top){
+               validaddr((uintptr)addr, sizeof(long), 1);
                error(Ebadarg);
+       }
+       /* delta == 0 is a no-op, not a release */
        if(delta < 0 || *addr < 0)
                error(Ebadarg);
-       return semrelease(s, addr, arg[1]);
+       return (uintptr)semrelease(s, addr, delta);
+}
+
+/* For binary compatibility */
+uintptr
+sys_nsec(va_list list)
+{
+       vlong *v;
+
+       v = va_arg(list, vlong*);
+       evenaddr((uintptr)v);
+       validaddr((uintptr)v, sizeof(vlong), 1);
+       *v = todget(nil);
+       return 0;
 }