sysproc.ed - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       sysproc.ed (10059B)
       ---
            1 1i
            2 #define        WANT_M
            3 .
            4 g/"edf.h"/d
            5 ,s/->ref =/->ref.ref =/g
            6 ,s/ref(p->dot)/ref(\&p->dot->ref)/g
            7 ,s/ref(p->fgrp)/ref(\&p->fgrp->ref)/g
            8 ,s/ref(p->pgrp)/ref(\&p->pgrp->ref)/g
            9 ,s/ref(p->egrp)/ref(\&p->egrp->ref)/g
           10 ,s/lock(img)/lock(\&img->ref.lk)/g
           11 ,s/ref(img)/ref(\&img->ref)/g
           12 ,s/return0(void\*)/return0(void *v)/g
           13 ,s/(s = up->seg\[i\])/(&)/g
           14 ,s;MACHP(0)->ticks;msec();g
           15 /ESEG.*= newseg/a
           16         flushmmu();        // Needed for Plan 9 VX
           17 .
           18 ,s;sleep(\&phore;sleep(\&phore.rendez;g
           19 ,s;lock(\&s->sema);lock(\&s->sema.rendez.lk);g
           20 ,s;wakeup(p);wakeup(\&p->rendez);g
           21 ,s;lock(up->rgrp);lock(\&up->rgrp->ref.lk);g
           22 ,s;ref(up->rgrp);ref(\&up->rgrp->ref);g
           23 /sysr1/ s/(ulong\*)/(uint32 *x)/
           24 /Admitted/,/        yield/c
           25                 yield();
           26 .
           27 /^        checkpagerefs/ c
           28         vx32sysr1();
           29 .
           30 /^sysrfork/ s/ulong/uint32/
           31 /^l2be/ s/long/uint32/
           32 -1 s/ulong/uint32/
           33 /^sysexec/ s/ulong/uint32/
           34 -1i
           35 static char Echanged[] = "exec arguments changed underfoot";
           36 
           37 .
           38 /^{/+1;/^}/-1 c
           39         char *volatile elem, *volatile file, *ufile;
           40         Chan *volatile tc;
           41 
           42         /*
           43          * Open the file, remembering the final element and the full name.
           44          */
           45         file = nil;
           46         elem = nil;
           47         tc = nil;
           48         if(waserror()){
           49                 if(file)
           50                         free(file);
           51                 if(elem)
           52                         free(elem);
           53                 if(tc)
           54                         cclose(tc);
           55                 nexterror();
           56         }
           57 
           58         ufile = uvalidaddr(arg[0], 1, 0);
           59         file = validnamedup(ufile, 1);
           60         tc = namec(file, Aopen, OEXEC, 0);
           61         kstrdup((char**)&elem, up->genbuf);
           62 
           63         /*
           64          * Read the header.  If it's a #!, fill in progarg[] with info and repeat.
           65          */
           66         int i, n, nprogarg;
           67         char *progarg[sizeof(Exec)/2+1];
           68         char *prog, *p;
           69         char line[sizeof(Exec)+1];
           70         Exec exec;
           71 
           72         nprogarg = 0;
           73         n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
           74         if(n < 2)
           75                 error(Ebadexec);
           76         p = (char*)&exec;
           77         if(p[0] == '#' && p[1] == '!'){
           78                 memmove(line, p, n);
           79                 nprogarg = shargs(line, n, progarg);
           80                 if(nprogarg == 0)
           81                         error(Ebadexec);
           82                 
           83                 /* The original file becomes an extra arg after #! line */
           84                 progarg[nprogarg++] = file;
           85                 
           86                 /*
           87                  * Take the #! $0 as a file to open, and replace
           88                  * $0 with the original path's name.
           89                  */
           90                 prog = progarg[0];
           91                 progarg[0] = elem;
           92                 cclose(tc);
           93                 tc = nil;        /* in case namec errors out */
           94                 tc = namec(prog, Aopen, OEXEC, 0);
           95                 n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
           96                 if(n < 2)
           97                         error(Ebadexec);
           98         }
           99 
          100         /* 
          101          * #! has had its chance, now we need a real binary
          102          */
          103         uint32 magic, entry, text, etext, data, edata, bss, ebss;
          104 
          105         magic = l2be(exec.magic);
          106         if(n != sizeof(Exec) || l2be(exec.magic) != AOUT_MAGIC)
          107                 error(Ebadexec);
          108 
          109         entry = l2be(exec.entry);
          110         text = l2be(exec.text);
          111         data = l2be(exec.data);
          112         bss = l2be(exec.bss);
          113         etext = ROUND(UTZERO+sizeof(Exec)+text, BY2PG);
          114         edata = ROUND(etext + data, BY2PG);
          115         ebss = ROUND(etext + data + bss, BY2PG);
          116         
          117 //iprint("entry %#lux text %#lux data %#lux bss %#lux\n", entry, text, data, bss);
          118 //iprint("etext %#lux edata %#lux ebss %#lux\n", etext, edata, ebss);
          119 
          120         if(entry < UTZERO+sizeof(Exec) || entry >= UTZERO+sizeof(Exec)+text)
          121                 error(Ebadexec);
          122         
          123         /* many overflow possibilities */
          124         if(text >= USTKTOP || data >= USTKTOP || bss >= USTKTOP
          125         || etext >= USTKTOP || edata >= USTKTOP || ebss >= USTKTOP
          126         || etext >= USTKTOP || edata < etext || ebss < edata)
          127                 error(Ebadexec);
          128 
          129         /*
          130          * Copy argv into new stack segment temporarily mapped elsewhere.
          131          * Be careful: multithreaded program could be changing argv during this.
          132          * Pass 1: count number of arguments, string bytes.
          133          */
          134         int nargv, strbytes;
          135         uint32 argp, ssize, spage;
          136 
          137         strbytes = 0;
          138         for(i=0; i<nprogarg; i++)
          139                 strbytes += strlen(progarg[i]) + 1;
          140 
          141         argp = arg[1];
          142         for(nargv=0;; nargv++, argp += BY2WD){
          143                 uint32 a;
          144                 char *str;
          145 
          146                 a = *(uint32*)uvalidaddr(argp, BY2WD, 0);
          147                 if(a == 0)
          148                         break;
          149                 str = uvalidaddr(a, 1, 0);
          150                 n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1;
          151                 if(nprogarg > 0 && nargv == 0)
          152                         continue;        /* going to skip argv[0] on #! */
          153                 strbytes += n;
          154         }
          155         if(nargv == 0)
          156                 error("exec missing argv");
          157 
          158         /* 
          159          * Skip over argv[0] if using #!.  Waited until now so that
          160          * string would still be checked for validity during loop.
          161          */
          162         if(nprogarg > 0){
          163                 nargv--;
          164                 arg[1] += BY2WD;
          165         }
          166 
          167         ssize = BY2WD*((nprogarg+nargv)+1) + ROUND(strbytes, BY2WD) + sizeof(Tos);
          168 
          169         /*
          170          * 8-byte align SP for those (e.g. sparc) that need it.
          171          * execregs() will subtract another 4 bytes for argc.
          172          */
          173         if((ssize+4) & 7)
          174                 ssize += 4;
          175         spage = (ssize+(BY2PG-1)) >> PGSHIFT;
          176 
          177         /*
          178          * Pass 2: build the stack segment, being careful not to assume
          179          * that the counts from pass 1 are still valid.
          180          */
          181         if(spage > TSTKSIZ)
          182                 error(Enovmem);
          183 
          184         qlock(&up->seglock);
          185         if(waserror()){
          186                 if(up->seg[ESEG]){
          187                         putseg(up->seg[ESEG]);
          188                         up->seg[ESEG] = nil;
          189                 }
          190                 qunlock(&up->seglock);
          191                 nexterror();
          192         }
          193         up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);
          194         flushmmu();        // Needed for Plan 9 VX  XXX really?
          195 
          196         /*
          197          * Top-of-stack structure.
          198          */
          199         uchar *uzero;
          200         uzero = up->pmmu.uzero;
          201         Tos *tos;
          202         uint32 utos;
          203         utos = USTKTOP - sizeof(Tos);
          204         tos = (Tos*)(uzero + utos + TSTKTOP - USTKTOP);
          205         tos->cyclefreq = m->cyclefreq;
          206         cycles((uvlong*)&tos->pcycles);
          207         tos->pcycles = -tos->pcycles;
          208         tos->kcycles = tos->pcycles;
          209         tos->clock = 0;
          210 
          211         /*
          212          * Argument pointers and strings, together.
          213          */
          214         char *bp, *ep;
          215         uint32 *targp;
          216         uint32 ustrp, uargp;
          217 
          218         ustrp = utos - ROUND(strbytes, BY2WD);
          219         uargp = ustrp - BY2WD*((nprogarg+nargv)+1);
          220         bp = (char*)(uzero + ustrp + TSTKTOP - USTKTOP);
          221         ep = bp + strbytes;
          222         p = bp;
          223         targp = (uint32*)(uzero + uargp + TSTKTOP - USTKTOP);
          224         
          225         /* #! args are trusted */
          226         for(i=0; i<nprogarg; i++){
          227                 n = strlen(progarg[i]) + 1;
          228                 if(n  > ep - p)
          229                         error(Echanged);
          230                 memmove(p, progarg[i], n);
          231                 p += n;
          232                 *targp++ = ustrp;
          233                 ustrp += n;
          234         }
          235         
          236         /* the rest are not */
          237         argp = arg[1];
          238         for(i=0; i<nargv; i++){
          239                 uint32 a;
          240                 char *str;
          241                 
          242                 a = *(uint32*)uvalidaddr(argp, BY2WD, 0);
          243                 argp += BY2WD;
          244                 
          245                 str = uvalidaddr(a, 1, 0);
          246                 n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1;
          247                 if(n  > ep - p)
          248                         error(Echanged);
          249                 memmove(p, str, n);
          250                 p += n;
          251                 *targp++ = ustrp;
          252                 ustrp += n;
          253         }
          254 
          255         if(*(uint32*)uvalidaddr(argp, BY2WD, 0) != 0)
          256                 error(Echanged);        
          257         *targp = 0;
          258 
          259         /*
          260          * But wait, there's more: prepare an arg copy for up->args
          261          * using the copy we just made in the temporary segment.
          262          */
          263         char *args;
          264         int nargs;
          265 
          266         n = p - bp;        /* includes NUL on last arg, so must be > 0 */
          267         if(n <= 0)        /* nprogarg+nargv > 0; checked above */
          268                 error(Egreg);
          269         if(n > 128)
          270                 n = 128;
          271         args = smalloc(n);
          272         if(waserror()){
          273                 free(args);
          274                 nexterror();
          275         }
          276         memmove(args, bp, n);
          277         /* find beginning of UTF character boundary to place final NUL */
          278         while(n > 0 && (args[n-1]&0xC0) == 0x80)
          279                 n--;
          280         args[n-1] = '\0';
          281         nargs = n;
          282 
          283         /*
          284          * Now we're ready to commit.
          285          */
          286         free(up->text);
          287         up->text = elem;
          288         free(up->args);
          289         up->args = args;
          290         up->nargs = n;
          291         elem = nil;
          292         poperror();        /* args */
          293 
          294         /*
          295          * Free old memory.  Special segments maintained across exec.
          296          */
          297         Segment *s;
          298         for(i = SSEG; i <= BSEG; i++) {
          299                 putseg(up->seg[i]);
          300                 up->seg[i] = nil;        /* in case of error */
          301         }
          302         for(i = BSEG+1; i< NSEG; i++) {
          303                 s = up->seg[i];
          304                 if(s && (s->type&SG_CEXEC)) {
          305                         putseg(s);
          306                         up->seg[i] = nil;
          307                 }
          308         }
          309         
          310         /*
          311          * Close on exec
          312          */
          313         Fgrp *f;
          314         f = up->fgrp;
          315         for(i=0; i<=f->maxfd; i++)
          316                 fdclose(i, CCEXEC);
          317 
          318         /* Text.  Shared. Attaches to cache image if possible */
          319         /* attachimage returns a locked cache image */
          320         Image *img;
          321         Segment *ts;
          322         img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (etext-UTZERO)>>PGSHIFT);
          323         ts = img->s;
          324         up->seg[TSEG] = ts;
          325         ts->flushme = 1;
          326         ts->fstart = 0;
          327         ts->flen = sizeof(Exec)+text;
          328         unlock(&img->ref.lk);
          329 
          330         /* Data. Shared. */
          331         s = newseg(SG_DATA, etext, (edata-etext)>>PGSHIFT);
          332         up->seg[DSEG] = s;
          333 
          334         /* Attached by hand */
          335         incref(&img->ref);
          336         s->image = img;
          337         s->fstart = ts->fstart+ts->flen;
          338         s->flen = data;
          339 
          340         /* BSS. Zero fill on demand */
          341         up->seg[BSEG] = newseg(SG_BSS, edata, (ebss-edata)>>PGSHIFT);
          342 
          343         /*
          344          * Move the stack
          345          */
          346         s = up->seg[ESEG];
          347         up->seg[ESEG] = 0;
          348         up->seg[SSEG] = s;
          349         qunlock(&up->seglock);
          350         poperror();        /* seglock */
          351 
          352         s->base = USTKTOP-USTKSIZE;
          353         s->top = USTKTOP;
          354         relocateseg(s, USTKTOP-TSTKTOP);
          355 
          356         /*
          357          *  '/' processes are higher priority (hack to make /ip more responsive).
          358          */
          359         if(devtab[tc->type]->dc == L'/')
          360                 up->basepri = PriRoot;
          361         up->priority = up->basepri;
          362         poperror();        /* tc, elem, file */
          363         cclose(tc);
          364         free(file);
          365         // elem is now up->text
          366 
          367         /*
          368          *  At this point, the mmu contains info about the old address
          369          *  space and needs to be flushed
          370          */
          371         flushmmu();
          372         qlock(&up->debug);
          373         up->nnote = 0;
          374         up->notify = 0;
          375         up->notified = 0;
          376         up->privatemem = 0;
          377         procsetup(up);
          378         qunlock(&up->debug);
          379         if(up->hang)
          380                 up->procctl = Proc_stopme;
          381 
          382         return execregs(entry, USTKTOP - uargp, nprogarg+nargv);
          383 .
          384 /^syssleep/s/ulong/uint32/
          385 /^sysalarm/s/ulong/uint32/
          386 /^sysexits/s/ulong/uint32/
          387 /status/;/if(status)/ c
          388         char *status;
          389         char *inval = "invalid exit string";
          390         char buf[ERRMAX];
          391 
          392         if(arg[0]){
          393 .
          394 /validaddr/c
          395                         status = uvalidaddr(arg[0], 1, 0);
          396 .
          397 /^        }/ c
          398         }else
          399                 status = nil;
          400 .
          401 /^sys_wait/s/ulong/uint32/
          402 /validaddr(arg\[0\], sizeof(OWaitmsg), 1)/ c
          403         ow = uvalidaddr(arg[0], sizeof(OWaitmsg), 1);
          404 .
          405 /ow =/d
          406 /^sysawait/s/ulong/uint32/
          407 /ulong n/ s/ulong/uint32/
          408 a
          409         char *buf;
          410 .
          411 /validaddr/ s/v/buf = uv/
          412 /i = / s/(char\*)arg\[0\]/buf/
          413 /^generrstr/ s/char \*buf/uint32 addr/
          414 /^$/i
          415         char *buf;
          416 .
          417 /validaddr/ s/v/buf = uv/
          418 s/(ulong)buf/addr/
          419 /^syserrstr/s/ulong/uint32/
          420 /return/s/(char\*)//
          421 /^sys_errstr/s/ulong/uint32/
          422 /return/s/(char\*)//
          423 /^sysnotify/s/ulong/uint32/
          424 /validaddr/;/up->notify/c
          425                 uvalidaddr(arg[0], 1, 0);
          426         up->notify = arg[0];        /* checked again when used */
          427 .
          428 /^sysnoted/s/ulong/uint32/
          429 /^syssegbrk/s/ulong/uint32/
          430 /addr/s/ulong/uint32/
          431 /^syssegattach/s/ulong/uint32/
          432 /return/s/(char\*)arg\[1\]/uvalidaddr(arg[1], 1, 0)/
          433 /^syssegdetach/s/ulong/uint32/
          434 /addr/s/ulong/uint32/
          435 /^syssegfree/s/ulong/uint32/
          436 /from/s/ulong/uint32/
          437 /^sysbrk_/s/ulong/uint32/
          438 /^sysrendezvous/s/ulong/uint32/
          439 /^syssemacquire/s/ulong/uint32/
          440 /validaddr/ s/v/addr = uv/
          441 /addr =/d
          442 /(ulong)addr/s/(ulong)addr/arg[0]/
          443 /^syssemrelease/s/ulong/uint32/
          444 /validaddr/ s/v/addr = uv/
          445 /addr =/d
          446 /(ulong)addr/s/(ulong)addr/arg[0]/