commit 0e345fe6a6994b2df8dd744e9b0e68ce9026a293
parent a3985efe6946ed22480d95497c21a5fce3d8c678
Author: yiyus <yiyu.jgl@gmail.com>
Date: Wed, 21 Jul 2010 21:20:48 +0200
all the .ed files updated, makea still needs more work
Diffstat:
9 files changed, 612 insertions(+), 17 deletions(-)
diff --git a/src/9vx/a/segment.c b/src/9vx/a/segment.c
@@ -483,8 +483,6 @@ ibrk(ulong addr, int seg)
if(ns == 0 || ns == s)
continue;
if(newtop >= ns->base && newtop < ns->top) {
-print("grow segment %d -> %p would overlap %d [%p-%p]\n",
- seg, newtop, i, ns->base, ns->top);
qunlock(&s->lk);
error(Esoverlap);
}
@@ -648,6 +646,7 @@ segattach(Proc *p, ulong attr, char *name, ulong va, ulong len)
error(Ebadarg);
vmemchr(name, 0, ~0);
+
for(sno = 0; sno < NSEG; sno++)
if(p->seg[sno] == nil && sno != ESEG)
break;
diff --git a/src/9vx/a/segment.ed b/src/9vx/a/segment.ed
@@ -1,4 +1,3 @@
-/^addphysseg/-1,/^ return/+1d
,s!Lock;!Lock lk;!
,s!lock(s)!lock(\&s->ref.lk)!g
,s!lock(i)!lock(\&i->ref.lk)!g
@@ -24,3 +23,5 @@
/^}/i
#endif
.
+/validaddr/d
+/^syssegflush/s/ulong/uint32/
diff --git a/src/9vx/a/swap.c b/src/9vx/a/swap.c
@@ -67,7 +67,7 @@ putswap(Page *p)
swapalloc.last = idx;
}
if(*idx >= 254)
- panic("putswap %lux == %ud", p, *idx);
+ panic("putswap %#p == %ud", p, *idx);
unlock(&swapalloc.lk);
}
@@ -107,7 +107,7 @@ pager(void *junk)
Proc *p, *ep;
if(waserror())
- panic("pager: os error\n");
+ panic("pager: os error");
p = proctab(0);
ep = &p[conf.nproc];
@@ -115,7 +115,6 @@ pager(void *junk)
loop:
up->psstate = "Idle";
sleep(&swapalloc.r, needpages, 0);
-print("uh oh. someone woke the pager\n");
while(needpages(junk)) {
@@ -335,7 +334,7 @@ executeio(void)
for(i = 0; i < ioptr; i++) {
if(ioptr > conf.nswppo)
- panic("executeio: ioptr %d > %d\n", ioptr, conf.nswppo);
+ panic("executeio: ioptr %d > %d", ioptr, conf.nswppo);
out = iolist[i];
k = kmap(out);
kaddr = (char*)VA(k);
diff --git a/src/9vx/a/swap.ed b/src/9vx/a/swap.ed
@@ -7,3 +7,6 @@
,s;lock(out);lock(\&out->lk);g
,s;lock(outp);lock(\&outp->lk);g
g/swopen/d
+/if(!cpuserver)/;/else/c
+ if(!cpuserver || freebroken() == 0)
+.
diff --git a/src/9vx/a/sysfile.c b/src/9vx/a/sysfile.c
@@ -175,7 +175,7 @@ sysfd2path(uint32 *arg)
{
Chan *c;
char *buf;
-
+
buf = uvalidaddr(arg[1], arg[2], 1);
c = fdtochan(arg[0], -1, 0, 1);
@@ -848,7 +848,7 @@ sseek(vlong *ret, uint32 *arg)
default:
error(Ebadarg);
}
- *ret = off; /* caller translated arg[0] already */
+ *ret = off;
c->uri = 0;
c->dri = 0;
cclose(c);
@@ -983,6 +983,7 @@ syschdir(uint32 *arg)
return 0;
}
+ // Plan 9 VX added isk parameter.
long
bindmount(int ismount, int fd, int afd, char* arg0, char* arg1, ulong flag, char* spec)
{
diff --git a/src/9vx/a/sysfile.ed b/src/9vx/a/sysfile.ed
@@ -21,17 +21,189 @@
g/^sys_/ s/ulong \*)/ulong *u)/
/^bindmount/,/^sysbind/ s/validaddr/if(!isk) validaddr/
/^bindmount/,/^sysbind/ s/spec = validnamedup/if(isk) kstrdup(\&spec, spec); else &/
+g/^[a-z]/ s/ulong/uint32/g
+/^openmode/ s/uint32/ulong/
+/^sysfd2path/ s/^//
+/validaddr/-1;+1c
+ char *buf;
+
+ buf = uvalidaddr(arg[1], arg[2], 1);
+.
+/snprint/ s/(char\*)arg\[1\]/buf/
+/^syspipe/ s/^//
+/validaddr/-1;+1c
+ int *ufd;
+
+ ufd = uvalidaddr(arg[0], 2*BY2WD, 1);
+.
+/((long\*)arg\[0\])/ s/((long\*)arg\[0\])/ufd/
+/((long\*)arg\[0\])/ s/((long\*)arg\[0\])/ufd/
+/^sysopen/ s/^//
+/^$/i
+ char *name;
+.
+/openmode/a
+ name = uvalidaddr(arg[0], 1, 0);
+ c = namec(name, Aopen, arg[1], 0);
+.
+/if(c)/d
+s/ //
+/validaddr/;/c = namec/d
+/^doread/ s/^//
+/^{/a
+ int dir;
+.
+/validaddr/;/p =/c
+ p = uvalidaddr(arg[1], n, 1);
+.
+/QTDIR/;/c->umh/c
+ dir = c->qid.type&QTDIR;
+ if(dir && mountrockread(c, p, n, &nn)){
+ /* do nothing: mountrockread filled buffer */
+ }else{
+ if(dir && c->umh)
+.
+/else{/;/}/c
+ else
+ nn = devtab[c->type]->read(c, p, n, off);
+ }
+ if(dir)
+.
+/}else/;/nnn/c
+ else
+ nnn = nn;
+.
+/^dowrite/ s/^//
+/^$/i
+ uchar *p;
+.
+/validaddr/ s/v/p = uv/
+/m = devtab/ s/(void\*)arg\[1\]/p/
+/^sseek/s/(/(vlong *ret, /
+/u\[2\]/ s/ulong/uint32/
+/arg\[0\] = off/ s/\*(vlong\*)arg\[0\]/*ret/
+/^sysseek/s/^//
+/validaddr/;/sseek/c
+ sseek(uvalidaddr(arg[0], BY2V, 1), arg);
+.
+/^sysoseek/s/^//
+/^{/;/^$/s/ulong/uint32/g
+/a\[0\]/ s/=.*/= 0;/
+/sseek/ s/(.*)/(\&o.v, a)/
+/^sysfstat/ s/^//
+/^$/i
+ uchar *p;
+.
+/validaddr/ s/v/p = uv/
+/l = devtab/ s/(.*)/(c, p, l)/
+/^sysstat/ s/^//
+/^$/i
+ uchar *p;
+.
+/validaddr/ s/v/p = uv/
+/validaddr/ s/v/name = uv/
+/c = namec/ s/(char\*)arg\[0\]/name/
+/l = devtab/ s/(.*)/(c, p, l)/
+/l = dirsetname/ s/(uchar\*)arg\[1\]/p/
+/^syschdir/ s/^//
+/^$/i
+ char *name;
+.
+/validaddr/ s/v/name = uv/
+/c = namec/ s/(char\*)arg\[0\]/name/
+/^bindmount/ s/int isk, //
+s/uint32/ulong/
+/isk/d
+/isk/s/if.*else //
+/isk/d
+/isk/d
+/^sysbind/ s/^//
+/return/ s/0, //
+s/(char\*)arg\[0\]/uvalidaddr(arg[0], 1, 0)/
+s/(char\*)arg\[1\]/uvalidaddr(arg[1], 1, 0)/
+/^sysmount/ s/^//
+/return/ s/0, //
+s/(char\*)arg\[2\]/uvalidaddr(arg[2], 1, 0)/
+s/(char\*)arg\[4\]/uvalidaddr(arg[4], 1, 0)/
+/^sys_mount/ s/^//
+/return/ s/0, //
+s/(char\*)arg\[1\]/uvalidaddr(arg[1], 1, 0)/
+s/(char\*)arg\[3\]/uvalidaddr(arg[3], 1, 0)/
+/^sysunmount/ s/^//
+/^$/i
+ char *mount, *mounted;
+.
+/validaddr/;/cmount/c
+ mount = uvalidaddr(arg[1], 1, 0);
+ cmount = namec(mount, Amount, 0, 0);
+.
+/validaddr/ s/v/mounted = uv/
+/cmounted/ s/(char\*)arg\[0\]/mounted/
+/^syscreate/ s/^//
+/^$/i
+ char *name;
+.
+/validaddr/;/c = namec/c
+ name = uvalidaddr(arg[0], 1, 0);
+ c = namec(name, Acreate, arg[1], arg[2]);
+.
+/^sysremove/ s/^//
+/^$/i
+ char *name;
+.
+/validaddr/;/c = namec/c
+ name = uvalidaddr(arg[0], 1, 0);
+ c = namec(name, Aremove, 0, 0);
+.
+/^syswstat/ s/^//
+/^$/i
+ char *name;
+ uchar *p;
+.
+/validaddr/;/return/c
+ p = uvalidaddr(arg[1], l, 0);
+ validstat(p, l);
+ name = uvalidaddr(arg[0], 1, 0);
+ c = namec(name, Aaccess, 0, 0);
+ return wstat(c, p, l);
+.
+/^sysfwstat/ s/^//
+/^$/i
+ uchar *p;
+.
+/validaddr/ s/v/p = uv/
+/validstat/ s/(uchar\*)arg\[1\]/p/
+/return/ s/(uchar\*)arg\[1\]/p/
+/^sys_stat/ s/^//
+/name/ s/;/, *elem;/
+/^$/i
+ uchar *p;
+.
+/validaddr/;/namec/c
+ p = uvalidaddr(arg[1], 116, 1);
+ name = uvalidaddr(arg[0], 1, 0);
+ c = namec(name, Aaccess, 0, 0);
+.
+/name =/;/l =/ s/name/elem/g
+/dirsetelem/ s/elem/name/
+/packoldstat/ s/(uchar\*)arg\[1\]/p/
+/^sys_fstat/ s/^//
+/^$/i
+ uchar *p;
+.
+/validaddr/ s/v/p = uv/
+/packoldstat/ s/(uchar\*)arg\[1\]/p/
$a
// Plan 9 VX additions
long
kbind(char *new, char *old, int flag)
{
- return bindmount(1, 0, -1, -1, new, old, flag, nil);
+ return bindmount(0, -1, -1, new, old, flag, nil);
}
long
-syspassfd(ulong *u)
+syspassfd(uint32 *u)
{
error("passfd unimplemented");
return -1;
diff --git a/src/9vx/a/sysproc.c b/src/9vx/a/sysproc.c
@@ -7,7 +7,7 @@
#include "fns.h"
#include "error.h"
-#include "a.out.h"
+#include "a.out.h"
int shargs(char*, int, char**);
@@ -644,6 +644,7 @@ sysexits(uint32 *arg)
}
poperror();
}
+
}else
status = nil;
pexit(status, 1);
@@ -1113,7 +1114,7 @@ syssemacquire(uint32 *arg)
evenaddr(arg[0]);
block = arg[1];
- if((s = seg(up, arg[0], 0)) == nil) /* this can't happen if validaddr succeeded, can it? */
+ if((s = seg(up, arg[0], 0)) == nil)
error(Ebadarg);
if(*addr < 0)
error(Ebadarg);
@@ -1130,7 +1131,7 @@ syssemrelease(uint32 *arg)
evenaddr(arg[0]);
delta = arg[1];
- if((s = seg(up, arg[0], 0)) == nil) /* again, this can't happen! */
+ if((s = seg(up, arg[0], 0)) == nil)
error(Ebadarg);
if(delta < 0 || *addr < 0)
error(Ebadarg);
diff --git a/src/9vx/a/sysproc.ed b/src/9vx/a/sysproc.ed
@@ -1,15 +1,16 @@
+1i
+#define WANT_M
+.
g/"edf.h"/d
,s/->ref =/->ref.ref =/g
,s/ref(p->dot)/ref(\&p->dot->ref)/g
,s/ref(p->fgrp)/ref(\&p->fgrp->ref)/g
,s/ref(p->pgrp)/ref(\&p->pgrp->ref)/g
-,s/ref(p->rgrp)/ref(\&p->rgrp->ref)/g
,s/ref(p->egrp)/ref(\&p->egrp->ref)/g
,s/lock(img)/lock(\&img->ref.lk)/g
,s/ref(img)/ref(\&img->ref)/g
,s/return0(void\*)/return0(void *v)/g
,s/(s = up->seg\[i\])/(&)/g
-/edf.*Admitted/,/else/d
,s;MACHP(0)->ticks;msec();g
/ESEG.*= newseg/a
flushmmu(); // Needed for Plan 9 VX
@@ -19,10 +20,427 @@ g/"edf.h"/d
,s;wakeup(p);wakeup(\&p->rendez);g
,s;lock(up->rgrp);lock(\&up->rgrp->ref.lk);g
,s;ref(up->rgrp);ref(\&up->rgrp->ref);g
-/sysr1/ s/(ulong\*)/(ulong *x)/
+/sysr1/ s/(ulong\*)/(uint32 *x)/
/Admitted/,/ yield/c
yield();
.
/^ checkpagerefs/ c
vx32sysr1();
.
+/^sysrfork/ s/ulong/uint32/
+/^l2be/ s/long/uint32/
+-1 s/ulong/uint32/
+/^sysexec/ s/ulong/uint32/
+-1i
+static char Echanged[] = "exec arguments changed underfoot";
+
+.
+/^{/+1;/^}/-1 c
+ char *volatile elem, *volatile file, *ufile;
+ Chan *volatile tc;
+
+ /*
+ * Open the file, remembering the final element and the full name.
+ */
+ file = nil;
+ elem = nil;
+ tc = nil;
+ if(waserror()){
+ if(file)
+ free(file);
+ if(elem)
+ free(elem);
+ if(tc)
+ cclose(tc);
+ nexterror();
+ }
+
+ ufile = uvalidaddr(arg[0], 1, 0);
+ file = validnamedup(ufile, 1);
+ tc = namec(file, Aopen, OEXEC, 0);
+ kstrdup((char**)&elem, up->genbuf);
+
+ /*
+ * Read the header. If it's a #!, fill in progarg[] with info and repeat.
+ */
+ int i, n, nprogarg;
+ char *progarg[sizeof(Exec)/2+1];
+ char *prog, *p;
+ char line[sizeof(Exec)+1];
+ Exec exec;
+
+ nprogarg = 0;
+ n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
+ if(n < 2)
+ error(Ebadexec);
+ p = (char*)&exec;
+ if(p[0] == '#' && p[1] == '!'){
+ memmove(line, p, n);
+ nprogarg = shargs(line, n, progarg);
+ if(nprogarg == 0)
+ error(Ebadexec);
+
+ /* The original file becomes an extra arg after #! line */
+ progarg[nprogarg++] = file;
+
+ /*
+ * Take the #! $0 as a file to open, and replace
+ * $0 with the original path's name.
+ */
+ prog = progarg[0];
+ progarg[0] = elem;
+ cclose(tc);
+ tc = nil; /* in case namec errors out */
+ tc = namec(prog, Aopen, OEXEC, 0);
+ n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
+ if(n < 2)
+ error(Ebadexec);
+ }
+
+ /*
+ * #! has had its chance, now we need a real binary
+ */
+ uint32 magic, entry, text, etext, data, edata, bss, ebss;
+
+ magic = l2be(exec.magic);
+ if(n != sizeof(Exec) || l2be(exec.magic) != AOUT_MAGIC)
+ error(Ebadexec);
+
+ entry = l2be(exec.entry);
+ text = l2be(exec.text);
+ data = l2be(exec.data);
+ bss = l2be(exec.bss);
+ etext = ROUND(UTZERO+sizeof(Exec)+text, BY2PG);
+ edata = ROUND(etext + data, BY2PG);
+ ebss = ROUND(etext + data + bss, BY2PG);
+
+//iprint("entry %#lux text %#lux data %#lux bss %#lux\n", entry, text, data, bss);
+//iprint("etext %#lux edata %#lux ebss %#lux\n", etext, edata, ebss);
+
+ if(entry < UTZERO+sizeof(Exec) || entry >= UTZERO+sizeof(Exec)+text)
+ error(Ebadexec);
+
+ /* many overflow possibilities */
+ if(text >= USTKTOP || data >= USTKTOP || bss >= USTKTOP
+ || etext >= USTKTOP || edata >= USTKTOP || ebss >= USTKTOP
+ || etext >= USTKTOP || edata < etext || ebss < edata)
+ error(Ebadexec);
+
+ /*
+ * Copy argv into new stack segment temporarily mapped elsewhere.
+ * Be careful: multithreaded program could be changing argv during this.
+ * Pass 1: count number of arguments, string bytes.
+ */
+ int nargv, strbytes;
+ uint32 argp, ssize, spage;
+
+ strbytes = 0;
+ for(i=0; i<nprogarg; i++)
+ strbytes += strlen(progarg[i]) + 1;
+
+ argp = arg[1];
+ for(nargv=0;; nargv++, argp += BY2WD){
+ uint32 a;
+ char *str;
+
+ a = *(uint32*)uvalidaddr(argp, BY2WD, 0);
+ if(a == 0)
+ break;
+ str = uvalidaddr(a, 1, 0);
+ n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1;
+ if(nprogarg > 0 && nargv == 0)
+ continue; /* going to skip argv[0] on #! */
+ strbytes += n;
+ }
+ if(nargv == 0)
+ error("exec missing argv");
+
+ /*
+ * Skip over argv[0] if using #!. Waited until now so that
+ * string would still be checked for validity during loop.
+ */
+ if(nprogarg > 0){
+ nargv--;
+ arg[1] += BY2WD;
+ }
+
+ ssize = BY2WD*((nprogarg+nargv)+1) + ROUND(strbytes, BY2WD) + sizeof(Tos);
+
+ /*
+ * 8-byte align SP for those (e.g. sparc) that need it.
+ * execregs() will subtract another 4 bytes for argc.
+ */
+ if((ssize+4) & 7)
+ ssize += 4;
+ spage = (ssize+(BY2PG-1)) >> PGSHIFT;
+
+ /*
+ * Pass 2: build the stack segment, being careful not to assume
+ * that the counts from pass 1 are still valid.
+ */
+ if(spage > TSTKSIZ)
+ error(Enovmem);
+
+ qlock(&up->seglock);
+ if(waserror()){
+ if(up->seg[ESEG]){
+ putseg(up->seg[ESEG]);
+ up->seg[ESEG] = nil;
+ }
+ qunlock(&up->seglock);
+ nexterror();
+ }
+ up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);
+ flushmmu(); // Needed for Plan 9 VX XXX really?
+
+ /*
+ * Top-of-stack structure.
+ */
+ uchar *uzero;
+ uzero = up->pmmu.uzero;
+ Tos *tos;
+ uint32 utos;
+ utos = USTKTOP - sizeof(Tos);
+ tos = (Tos*)(uzero + utos + TSTKTOP - USTKTOP);
+ tos->cyclefreq = m->cyclefreq;
+ cycles((uvlong*)&tos->pcycles);
+ tos->pcycles = -tos->pcycles;
+ tos->kcycles = tos->pcycles;
+ tos->clock = 0;
+
+ /*
+ * Argument pointers and strings, together.
+ */
+ char *bp, *ep;
+ uint32 *targp;
+ uint32 ustrp, uargp;
+
+ ustrp = utos - ROUND(strbytes, BY2WD);
+ uargp = ustrp - BY2WD*((nprogarg+nargv)+1);
+ bp = (char*)(uzero + ustrp + TSTKTOP - USTKTOP);
+ ep = bp + strbytes;
+ p = bp;
+ targp = (uint32*)(uzero + uargp + TSTKTOP - USTKTOP);
+
+ /* #! args are trusted */
+ for(i=0; i<nprogarg; i++){
+ n = strlen(progarg[i]) + 1;
+ if(n > ep - p)
+ error(Echanged);
+ memmove(p, progarg[i], n);
+ p += n;
+ *targp++ = ustrp;
+ ustrp += n;
+ }
+
+ /* the rest are not */
+ argp = arg[1];
+ for(i=0; i<nargv; i++){
+ uint32 a;
+ char *str;
+
+ a = *(uint32*)uvalidaddr(argp, BY2WD, 0);
+ argp += BY2WD;
+
+ str = uvalidaddr(a, 1, 0);
+ n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1;
+ if(n > ep - p)
+ error(Echanged);
+ memmove(p, str, n);
+ p += n;
+ *targp++ = ustrp;
+ ustrp += n;
+ }
+
+ if(*(uint32*)uvalidaddr(argp, BY2WD, 0) != 0)
+ error(Echanged);
+ *targp = 0;
+
+ /*
+ * But wait, there's more: prepare an arg copy for up->args
+ * using the copy we just made in the temporary segment.
+ */
+ char *args;
+ int nargs;
+
+ n = p - bp; /* includes NUL on last arg, so must be > 0 */
+ if(n <= 0) /* nprogarg+nargv > 0; checked above */
+ error(Egreg);
+ if(n > 128)
+ n = 128;
+ args = smalloc(n);
+ if(waserror()){
+ free(args);
+ nexterror();
+ }
+ memmove(args, bp, n);
+ /* find beginning of UTF character boundary to place final NUL */
+ while(n > 0 && (args[n-1]&0xC0) == 0x80)
+ n--;
+ args[n-1] = '\0';
+ nargs = n;
+
+ /*
+ * Now we're ready to commit.
+ */
+ free(up->text);
+ up->text = elem;
+ free(up->args);
+ up->args = args;
+ up->nargs = n;
+ elem = nil;
+ poperror(); /* args */
+
+ /*
+ * Free old memory. Special segments maintained across exec.
+ */
+ Segment *s;
+ for(i = SSEG; i <= BSEG; i++) {
+ putseg(up->seg[i]);
+ up->seg[i] = nil; /* in case of error */
+ }
+ for(i = BSEG+1; i< NSEG; i++) {
+ s = up->seg[i];
+ if(s && (s->type&SG_CEXEC)) {
+ putseg(s);
+ up->seg[i] = nil;
+ }
+ }
+
+ /*
+ * Close on exec
+ */
+ Fgrp *f;
+ f = up->fgrp;
+ for(i=0; i<=f->maxfd; i++)
+ fdclose(i, CCEXEC);
+
+ /* Text. Shared. Attaches to cache image if possible */
+ /* attachimage returns a locked cache image */
+ Image *img;
+ Segment *ts;
+ img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (etext-UTZERO)>>PGSHIFT);
+ ts = img->s;
+ up->seg[TSEG] = ts;
+ ts->flushme = 1;
+ ts->fstart = 0;
+ ts->flen = sizeof(Exec)+text;
+ unlock(&img->ref.lk);
+
+ /* Data. Shared. */
+ s = newseg(SG_DATA, etext, (edata-etext)>>PGSHIFT);
+ up->seg[DSEG] = s;
+
+ /* Attached by hand */
+ incref(&img->ref);
+ s->image = img;
+ s->fstart = ts->fstart+ts->flen;
+ s->flen = data;
+
+ /* BSS. Zero fill on demand */
+ up->seg[BSEG] = newseg(SG_BSS, edata, (ebss-edata)>>PGSHIFT);
+
+ /*
+ * Move the stack
+ */
+ s = up->seg[ESEG];
+ up->seg[ESEG] = 0;
+ up->seg[SSEG] = s;
+ qunlock(&up->seglock);
+ poperror(); /* seglock */
+
+ s->base = USTKTOP-USTKSIZE;
+ s->top = USTKTOP;
+ relocateseg(s, USTKTOP-TSTKTOP);
+
+ /*
+ * '/' processes are higher priority (hack to make /ip more responsive).
+ */
+ if(devtab[tc->type]->dc == L'/')
+ up->basepri = PriRoot;
+ up->priority = up->basepri;
+ poperror(); /* tc, elem, file */
+ cclose(tc);
+ free(file);
+ // elem is now up->text
+
+ /*
+ * At this point, the mmu contains info about the old address
+ * space and needs to be flushed
+ */
+ flushmmu();
+ qlock(&up->debug);
+ up->nnote = 0;
+ up->notify = 0;
+ up->notified = 0;
+ up->privatemem = 0;
+ procsetup(up);
+ qunlock(&up->debug);
+ if(up->hang)
+ up->procctl = Proc_stopme;
+
+ return execregs(entry, USTKTOP - uargp, nprogarg+nargv);
+.
+/^syssleep/s/ulong/uint32/
+/^sysalarm/s/ulong/uint32/
+/^sysexits/s/ulong/uint32/
+/status/;/if(status)/ c
+ char *status;
+ char *inval = "invalid exit string";
+ char buf[ERRMAX];
+
+ if(arg[0]){
+.
+/validaddr/c
+ status = uvalidaddr(arg[0], 1, 0);
+.
+/^ }/ c
+ }else
+ status = nil;
+.
+/^sys_wait/s/ulong/uint32/
+/validaddr(arg\[0\], sizeof(OWaitmsg), 1)/ c
+ ow = uvalidaddr(arg[0], sizeof(OWaitmsg), 1);
+.
+/ow =/d
+/^sysawait/s/ulong/uint32/
+/ulong n/ s/ulong/uint32/
+a
+ char *buf;
+.
+/validaddr/ s/v/buf = uv/
+/i = / s/(char\*)arg\[0\]/buf/
+/^generrstr/ s/char \*buf/uint32 addr/
+/^$/i
+ char *buf;
+.
+/validaddr/ s/v/buf = uv/
+s/(ulong)buf/addr/
+/^syserrstr/s/ulong/uint32/
+/return/s/(char\*)//
+/^sys_errstr/s/ulong/uint32/
+/return/s/(char\*)//
+/^sysnotify/s/ulong/uint32/
+/validaddr/;/up->notify/c
+ uvalidaddr(arg[0], 1, 0);
+ up->notify = arg[0]; /* checked again when used */
+.
+/^sysnoted/s/ulong/uint32/
+/^syssegbrk/s/ulong/uint32/
+/addr/s/ulong/uint32/
+/^syssegattach/s/ulong/uint32/
+/return/s/(char\*)arg\[1\]/uvalidaddr(arg[1], 1, 0)/
+/^syssegdetach/s/ulong/uint32/
+/addr/s/ulong/uint32/
+/^syssegfree/s/ulong/uint32/
+/from/s/ulong/uint32/
+/^sysbrk_/s/ulong/uint32/
+/^sysrendezvous/s/ulong/uint32/
+/^syssemacquire/s/ulong/uint32/
+/validaddr/ s/v/addr = uv/
+/addr =/d
+/(ulong)addr/s/(ulong)addr/arg[0]/
+/^syssemrelease/s/ulong/uint32/
+/validaddr/ s/v/addr = uv/
+/addr =/d
+/(ulong)addr/s/(ulong)addr/arg[0]/
diff --git a/src/9vx/a/systab.ed b/src/9vx/a/systab.ed
@@ -1 +1,2 @@
,s!"/sys/src/libc/9syscall/!"!
+/Syscall/s/ulong/uint32/