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;
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);
p = newproc();
- p->fpsave = up->fpsave;
p->scallnr = up->scallnr;
p->s = up->s;
p->nerrlab = 0;
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);
}
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
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);
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;
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);
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);
*/
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);
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);
/*
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++;
}
* 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.
/* 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;
}
/*
* 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 */
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).
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;
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;
}
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);
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
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);
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)
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);
}
s = 0;
- addr = arg[0];
for(i = 0; i < NSEG; i++)
if(s = up->seg[i]) {
qlock(&s->lk);
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) {
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);
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;
/* Going to sleep here */
up->rendtag = tag;
- up->rendval = arg[1];
+ up->rendval = new;
up->rendhash = *l;
*l = up;
up->state = Rendezvous;
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;
}