X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=sidebyside;f=sys%2Fsrc%2F9%2Fport%2Fsysproc.c;h=fbe4f2fbc24b5ba8c7ac3679d0126a22d479115b;hb=3207e8b6a4339f39e2261d1f1878e8049b65c23c;hp=9c5c8899e151404f452484b48e56ab9efc4a1744;hpb=257c7e958ef125ec12cc218519ce56f767eb112d;p=plan9front.git diff --git a/sys/src/9/port/sysproc.c b/sys/src/9/port/sysproc.c index 9c5c8899e..fbe4f2fbc 100644 --- a/sys/src/9/port/sysproc.c +++ b/sys/src/9/port/sysproc.c @@ -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); @@ -101,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); @@ -164,6 +180,8 @@ sysrfork(ulong *arg) 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 */ @@ -215,38 +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, tstk, nargs, nbytes, n, bssend; - int indir, commit; + 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; - commit = 0; - 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(commit) + if(!up->seg[SSEG]) pexit(up->errstr, 1); nexterror(); } + align = BY2PG; + indir = 0; file = file0; for(;;){ tc = namec(file, Aopen, OEXEC, 0); @@ -264,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); @@ -286,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); @@ -299,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); /* @@ -319,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++; } @@ -336,7 +361,7 @@ 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; if(PGROUND(ssize) >= USTKSIZE) @@ -370,53 +395,38 @@ sysexec(ulong *arg) argv = (char**)(tstk - ssize); charp = (char*)(tstk - nbytes); - args = charp; + a = charp; if(indir) argp = progarg; else - argp = (char**)arg[1]; + argp = argp0; for(i=0; itext); - 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; - - commit = 1; - USED(commit); /* * Committed. @@ -428,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; } @@ -439,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 */ @@ -484,11 +495,19 @@ sysexec(ulong *arg) if(devtab[tc->type]->dc == L'/') up->basepri = PriRoot; up->priority = up->basepri; - cclose(tc); poperror(); /* tc */ - poperror(); /* elem */ + 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; @@ -544,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; @@ -593,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); @@ -621,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 @@ -655,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); @@ -675,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) @@ -723,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); @@ -751,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); @@ -782,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) { @@ -803,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); @@ -828,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; @@ -840,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; @@ -1089,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; }