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]/