]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/5e/proc.c
5e: added semacquire/semrelease
[plan9front.git] / sys / src / cmd / 5e / proc.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <bio.h>
5 #include <mach.h>
6 #include <ctype.h>
7 #include <tos.h>
8 #include "dat.h"
9 #include "fns.h"
10
11 Process plist;
12 Lock plistlock;
13
14 void
15 initproc(void)
16 {
17         P = emallocz(sizeof(Process));
18         P->pid = getpid();
19         P->fd = newfd();
20         incref(&nproc);
21         plist.prev = P;
22         plist.next = P;
23         P->prev = &plist;
24         P->next = &plist;
25         resetfpa();
26 }
27
28 void
29 addproc(Process *p)
30 {
31         lock(&plistlock);
32         p->prev = plist.prev;
33         p->next = &plist;
34         plist.prev->next = p;
35         plist.prev = p;
36         unlock(&plistlock);
37 }
38
39 void
40 remproc(Process *p)
41 {
42         lock(&plistlock);
43         p->prev->next = p->next;
44         p->next->prev = p->prev;
45         unlock(&plistlock);
46 }
47
48 Process *
49 findproc(int pid)
50 {
51         Process *p;
52
53         lock(&plistlock);
54         for(p = plist.next; p != &plist; p = p->next)
55                 if(p->pid == pid)
56                         break;
57         unlock(&plistlock);
58         if(p != &plist)
59                 return p;
60         return nil;
61 }
62
63 static void
64 copyname(char *file)
65 {
66         char *p;
67         
68         p = strrchr(file, '/');
69         if(p == nil)
70                 p = file;
71         else
72                 p++;
73         strncpy(P->name, p, NAMEMAX);
74
75         if(P->path != nil && decref(P->path) == 0)
76                 free(P->path);
77         P->path = emallocz(5 + strlen(file));
78         incref(P->path);
79         strcpy((char*)(P->path + 1), file);
80 }
81
82 static void
83 initstack(int argc, char **argv)
84 {
85         ulong tos, sp, ap, size, i, len;
86         
87         tos = mach->utop - sizeof(Tos) * 2;
88         sp = tos;
89         
90         size = 8;
91         for(i = 0; i < argc; i++)
92                 size += strlen(argv[i]) + 5;
93         
94         sp -= size;
95         sp &= ~7;
96         P->R[0] = tos;
97         P->R[1] = mach->utop - 4;
98         P->R[13] = sp;
99         
100         *(ulong *) vaddrnol(sp, 4) = argc;
101         sp += 4;
102         ap = sp + (argc + 1) * 4;
103         for(i = 0; i < argc; i++) {
104                 *(ulong *) vaddrnol(sp, 4) = ap;
105                 sp += 4;
106                 len = strlen(argv[i]) + 1;
107                 memcpy(vaddrnol(ap, len), argv[i], len);
108                 ap += len;
109         }
110         *(ulong *) vaddrnol(sp, 4) = 0;
111         inittos();
112 }
113
114 void
115 inittos(void)
116 {
117         ulong tos;
118
119         tos = mach->utop - sizeof(Tos) * 2;
120         ((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = P->pid;
121 }
122
123 static int
124 loadscript(int fd, char *file, int argc, char **argv)
125 {
126         char buf[513], *p, **q, **nargv;
127         int rc, nargc, i;
128         
129         seek(fd, 0, 0);
130         rc = readn(fd, buf, 512);
131         if(rc <= 0)
132                 goto invalid;
133         close(fd);
134         buf[rc] = 0;
135         p = strchr(buf, '\n');
136         if(p == nil)
137                 goto invalid;
138         *p = 0;
139         while(isspace(*--p))
140                 *p = 0;
141         nargc = 0;
142         p = buf + 2;
143         while(*p) {
144                 while(*p && isspace(*p))
145                         p++;
146                 nargc++;
147                 while(*p && !isspace(*p))
148                         p++;
149         }
150         if(nargc == 0)
151                 goto invalid;
152         nargv = emallocz(sizeof(char *) * (nargc + argc));
153         q = nargv;
154         p = buf + 2;
155         while(*p) {
156                 while(*p && isspace(*p))
157                         p++;
158                 *(p-1) = 0;
159                 *q++ = p;
160                 while(*p && !isspace(*p))
161                         p++;
162         }
163         *q++ = file;
164         for(i = 1; i < argc; i++)
165                 *q++ = argv[i];
166         rc = loadtext(*nargv, argc + nargc, nargv);
167         free(nargv);
168         return rc;
169
170 invalid:
171         werrstr("exec header invalid");
172         return -1;
173 }
174
175 int
176 loadtext(char *file, int argc, char **argv)
177 {
178         int fd;
179         Fhdr fp;
180         Segment *text, *data, *bss;
181         char buf[2];
182         
183         fd = open(file, OREAD);
184         if(fd < 0) return -1;
185         if(pread(fd, buf, 2, 0) == 2 && buf[0] == '#' && buf[1] == '!')
186                 return loadscript(fd, file, argc, argv);
187         seek(fd, 0, 0);
188         if(crackhdr(fd, &fp) == 0 || fp.magic != E_MAGIC) {
189                 werrstr("exec header invalid");
190                 return -1;
191         }
192         copyname(file);
193         P->notehandler = P->innote = P->notein = P->noteout = 0;
194         freesegs();
195         memset(P->R, 0, sizeof(P->R));
196         P->CPSR = 0;
197         text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT);
198         data = newseg(fp.dataddr, fp.datsz, SEGDATA);
199         bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS);
200         newseg(mach->utop - STACKSIZE, STACKSIZE, SEGSTACK);
201         seek(fd, fp.txtoff - fp.hdrsz, 0);
202         if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz)
203                 sysfatal("%r");
204         seek(fd, fp.datoff, 0);
205         if(readn(fd, data->data, fp.datsz) < fp.datsz)
206                 sysfatal("%r");
207         memset(bss->data, 0, bss->size);
208         P->R[15] = fp.entry;
209         if(havesymbols && syminit(fd, &fp) < 0)
210                 fprint(2, "initializing symbol table: %r\n");
211         close(fd);
212         fdclear(P->fd);
213         initstack(argc, argv);
214         resetfpa();
215         return 0;
216 }
217
218 void
219 cherrstr(char *str, ...)
220 {
221         va_list va;
222         
223         va_start(va, str);
224         vsnprint(P->errbuf, ERRMAX, str, va);
225         va_end(va);
226 }
227
228 u32int
229 noteerr(u32int x, u32int y)
230 {
231         if(((int)x) >= ((int)y))
232                 return x;
233         rerrstr(P->errbuf, ERRMAX);
234         return x;
235 }
236
237 Fd *
238 newfd(void)
239 {
240         Fd *fd;
241         
242         fd = emallocz(sizeof(*fd));
243         incref(fd);
244         return fd;
245 }
246
247 Fd *
248 copyfd(Fd *old)
249 {
250         Fd *new;
251         
252         rlock(old);
253         new = newfd();
254         if(old->nfds > 0) {
255                 new->nfds = old->nfds;
256                 new->fds = emalloc(old->nfds);
257                 memcpy(new->fds, old->fds, old->nfds);
258         }
259         runlock(old);
260         return new;
261 }
262
263 void
264 fddecref(Fd *fd)
265 {
266         if(decref(fd) == 0) {
267                 free(fd->fds);
268                 free(fd);
269         }
270 }
271
272 int
273 iscexec(Fd *fd, int n)
274 {
275         int r;
276
277         r = 0;
278         rlock(fd);
279         if(n / 8 < fd->nfds)
280                 r = (fd->fds[n / 8] & (1 << (n % 8))) != 0;
281         runlock(fd);
282         return r;
283 }
284
285 void
286 setcexec(Fd *fd, int n, int status)
287 {
288         int old;
289
290         wlock(fd);
291         if(n / 8 >= fd->nfds) {
292                 if(status == 0) {
293                         wunlock(fd);
294                         return;
295                 }
296                 old = fd->nfds;
297                 fd->nfds = (n / 8) + 1;
298                 fd->fds = erealloc(fd->fds, fd->nfds);
299                 memset(fd->fds + old, 0, fd->nfds - old);
300         }
301         if(status == 0)
302                 fd->fds[n / 8] &= ~(1 << (n % 8));
303         else
304                 fd->fds[n / 8] |= (1 << (n % 8));
305         wunlock(fd);
306 }
307
308 void
309 fdclear(Fd *fd)
310 {
311         int i, j, k;
312
313         wlock(fd);
314         if(fd->nfds == 0) {
315                 wunlock(fd);
316                 return;
317         }
318         for(i = 0; i < fd->nfds; i++) {
319                 j = fd->fds[i];
320                 for(k = 0; k < 8; k++)
321                         if(j & (1<<k))
322                                 close(8 * i + k);
323         }
324         free(fd->fds);
325         fd->nfds = 0;
326         fd->fds = nil;
327         wunlock(fd);
328 }
329
330 /* call this from a notehandler if you don't want the front to fall off */
331 void
332 addnote(char *msg)
333 {
334         int new;
335         
336         new = P->notein + 1;
337         if((new - P->noteout) % NNOTE == 0)
338                 return;
339
340         strncpy(P->notes[P->notein % NNOTE], msg, ERRMAX - 1);
341         P->notein = new;
342 }
343
344 /* the following code is not for the weak of heart */
345 void
346 donote(char *msg, ulong type)
347 {
348         int rc;
349         u32int *ureg, *sp, uregp, msgp;
350         char *msgb;
351
352         if(P->notehandler == 0)
353                 exits(msg);
354
355         uregp = P->R[13] - 18 * 4;
356         ureg = vaddrnol(uregp, 18 * 4);
357         memcpy(ureg, P->R, 15 * 4);
358         ureg[15] = type;
359         ureg[16] = P->CPSR;
360         ureg[17] = P->R[15];
361         P->R[13] = uregp;
362         msgp = P->R[13] -= strlen(msg) + 1;
363         msgb = vaddrnol(msgp, strlen(msg) + 1);
364         strcpy(msgb, msg);
365         P->R[13] -= 3 * 4;
366         sp = vaddrnol(P->R[13], 3 * 4);
367         sp[0] = 0;
368         sp[2] = msgp;
369         P->R[0] = uregp;
370         P->R[15] = P->notehandler;
371         P->innote = 1;
372         switch(rc = setjmp(P->notejmp) - 1) {
373         case -1:
374                 for(;;) {
375                         if(ultraverbose)
376                                 dump();
377                         step();
378                 }
379         case NDFLT:
380                 exits(msg);
381         case NCONT:
382                 break;
383         default:
384                 sysfatal("unhandled noted argument %d", rc);
385         }
386         P->innote = 0;
387         ureg = vaddrnol(uregp, 18 * 4); /* just to be sure */
388         memcpy(P->R, ureg, 15 * 4);
389         P->CPSR = ureg[16];
390         P->R[15] = ureg[17];
391 }