trun.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
trun.c (5102B) | |
--- | |
1 #include "mk.h" | |
2 | |
3 typedef struct Event | |
4 { | |
5 int pid; | |
6 Job *job; | |
7 } Event; | |
8 static Event *events; | |
9 static int nevents, nrunning, nproclimit; | |
10 | |
11 typedef struct Process | |
12 { | |
13 int pid; | |
14 int status; | |
15 struct Process *b, *f; | |
16 } Process; | |
17 static Process *phead, *pfree; | |
18 static void sched(void); | |
19 static void pnew(int, int), pdelete(Process *); | |
20 | |
21 int pidslot(int); | |
22 | |
23 void | |
24 run(Job *j) | |
25 { | |
26 Job *jj; | |
27 | |
28 if(jobs){ | |
29 for(jj = jobs; jj->next; jj = jj->next) | |
30 ; | |
31 jj->next = j; | |
32 } else | |
33 jobs = j; | |
34 j->next = 0; | |
35 /* this code also in waitup after parse redirect */ | |
36 if(nrunning < nproclimit) | |
37 sched(); | |
38 } | |
39 | |
40 static void | |
41 sched(void) | |
42 { | |
43 char *flags; | |
44 Job *j; | |
45 Bufblock *buf; | |
46 int slot; | |
47 Node *n; | |
48 Envy *e; | |
49 | |
50 if(jobs == 0){ | |
51 usage(); | |
52 return; | |
53 } | |
54 j = jobs; | |
55 jobs = j->next; | |
56 if(DEBUG(D_EXEC)) | |
57 fprint(1, "firing up job for target %s\n", wtos(j->t, ' … | |
58 slot = nextslot(); | |
59 events[slot].job = j; | |
60 buf = newbuf(); | |
61 e = buildenv(j, slot); | |
62 shprint(j->r->recipe, e, buf, j->r->shellt); | |
63 if(!tflag && (nflag || !(j->r->attr&QUIET))) | |
64 Bwrite(&bout, buf->start, (long)strlen(buf->start)); | |
65 freebuf(buf); | |
66 if(nflag||tflag){ | |
67 for(n = j->n; n; n = n->next){ | |
68 if(tflag){ | |
69 if(!(n->flags&VIRTUAL)) | |
70 touch(n->name); | |
71 else if(explain) | |
72 Bprint(&bout, "no touch of virtu… | |
73 } | |
74 n->time = time((long *)0); | |
75 MADESET(n, MADE); | |
76 } | |
77 } else { | |
78 if(DEBUG(D_EXEC)) | |
79 fprint(1, "recipe='%s'", j->r->recipe);/**/ | |
80 Bflush(&bout); | |
81 if(j->r->attr&NOMINUSE) | |
82 flags = 0; | |
83 else | |
84 flags = "-e"; | |
85 events[slot].pid = execsh(flags, j->r->recipe, 0, e, j->… | |
86 usage(); | |
87 nrunning++; | |
88 if(DEBUG(D_EXEC)) | |
89 fprint(1, "pid for target %s = %d\n", wtos(j->t,… | |
90 } | |
91 } | |
92 | |
93 int | |
94 waitup(int echildok, int *retstatus) | |
95 { | |
96 Envy *e; | |
97 int pid; | |
98 int slot; | |
99 Symtab *s; | |
100 Word *w; | |
101 Job *j; | |
102 char buf[ERRMAX]; | |
103 Bufblock *bp; | |
104 int uarg = 0; | |
105 int done; | |
106 Node *n; | |
107 Process *p; | |
108 extern int runerrs; | |
109 | |
110 /* first check against the proces slist */ | |
111 if(retstatus) | |
112 for(p = phead; p; p = p->f) | |
113 if(p->pid == *retstatus){ | |
114 *retstatus = p->status; | |
115 pdelete(p); | |
116 return(-1); | |
117 } | |
118 again: /* rogue processes */ | |
119 pid = waitfor(buf); | |
120 if(pid == -1){ | |
121 if(echildok > 0) | |
122 return(1); | |
123 else { | |
124 fprint(2, "mk: (waitup %d): %r\n", echildok); | |
125 Exit(); | |
126 } | |
127 } | |
128 if(DEBUG(D_EXEC)) | |
129 fprint(1, "waitup got pid=%d, status='%s'\n", pid, buf); | |
130 if(retstatus && pid == *retstatus){ | |
131 *retstatus = buf[0]? 1:0; | |
132 return(-1); | |
133 } | |
134 slot = pidslot(pid); | |
135 if(slot < 0){ | |
136 if(DEBUG(D_EXEC)) | |
137 fprint(2, "mk: wait returned unexpected process … | |
138 pnew(pid, buf[0]? 1:0); | |
139 goto again; | |
140 } | |
141 j = events[slot].job; | |
142 usage(); | |
143 nrunning--; | |
144 events[slot].pid = -1; | |
145 if(buf[0]){ | |
146 e = buildenv(j, slot); | |
147 bp = newbuf(); | |
148 shprint(j->r->recipe, e, bp, j->r->shellt); | |
149 front(bp->start); | |
150 fprint(2, "mk: %s: exit status=%s", bp->start, buf); | |
151 freebuf(bp); | |
152 for(n = j->n, done = 0; n; n = n->next) | |
153 if(n->flags&DELETE){ | |
154 if(done++ == 0) | |
155 fprint(2, ", deleting"); | |
156 fprint(2, " '%s'", n->name); | |
157 delete(n->name); | |
158 } | |
159 fprint(2, "\n"); | |
160 if(kflag){ | |
161 runerrs++; | |
162 uarg = 1; | |
163 } else { | |
164 jobs = 0; | |
165 Exit(); | |
166 } | |
167 } | |
168 for(w = j->t; w; w = w->next){ | |
169 if((s = symlook(w->s, S_NODE, 0)) == 0) | |
170 continue; /* not interested in this node … | |
171 update(uarg, s->u.ptr); | |
172 } | |
173 if(nrunning < nproclimit) | |
174 sched(); | |
175 return(0); | |
176 } | |
177 | |
178 void | |
179 nproc(void) | |
180 { | |
181 Symtab *sym; | |
182 Word *w; | |
183 | |
184 if(sym = symlook("NPROC", S_VAR, 0)) { | |
185 w = sym->u.ptr; | |
186 if (w && w->s && w->s[0]) | |
187 nproclimit = atoi(w->s); | |
188 } | |
189 if(nproclimit < 1) | |
190 nproclimit = 1; | |
191 if(DEBUG(D_EXEC)) | |
192 fprint(1, "nprocs = %d\n", nproclimit); | |
193 if(nproclimit > nevents){ | |
194 if(nevents) | |
195 events = (Event *)Realloc((char *)events, nprocl… | |
196 else | |
197 events = (Event *)Malloc(nproclimit*sizeof(Event… | |
198 while(nevents < nproclimit) | |
199 events[nevents++].pid = 0; | |
200 } | |
201 } | |
202 | |
203 int | |
204 nextslot(void) | |
205 { | |
206 int i; | |
207 | |
208 for(i = 0; i < nproclimit; i++) | |
209 if(events[i].pid <= 0) return i; | |
210 assert("out of slots!!", 0); | |
211 return 0; /* cyntax */ | |
212 } | |
213 | |
214 int | |
215 pidslot(int pid) | |
216 { | |
217 int i; | |
218 | |
219 for(i = 0; i < nevents; i++) | |
220 if(events[i].pid == pid) return(i); | |
221 if(DEBUG(D_EXEC)) | |
222 fprint(2, "mk: wait returned unexpected process %d\n", p… | |
223 return(-1); | |
224 } | |
225 | |
226 | |
227 static void | |
228 pnew(int pid, int status) | |
229 { | |
230 Process *p; | |
231 | |
232 if(pfree){ | |
233 p = pfree; | |
234 pfree = p->f; | |
235 } else | |
236 p = (Process *)Malloc(sizeof(Process)); | |
237 p->pid = pid; | |
238 p->status = status; | |
239 p->f = phead; | |
240 phead = p; | |
241 if(p->f) | |
242 p->f->b = p; | |
243 p->b = 0; | |
244 } | |
245 | |
246 static void | |
247 pdelete(Process *p) | |
248 { | |
249 if(p->f) | |
250 p->f->b = p->b; | |
251 if(p->b) | |
252 p->b->f = p->f; | |
253 else | |
254 phead = p->f; | |
255 p->f = pfree; | |
256 pfree = p; | |
257 } | |
258 | |
259 void | |
260 killchildren(char *msg) | |
261 { | |
262 Process *p; | |
263 | |
264 kflag = 1; /* to make sure waitup doesn't exit */ | |
265 jobs = 0; /* make sure no more get scheduled */ | |
266 for(p = phead; p; p = p->f) | |
267 expunge(p->pid, msg); | |
268 while(waitup(1, (int *)0) == 0) | |
269 ; | |
270 Bprint(&bout, "mk: %s\n", msg); | |
271 Exit(); | |
272 } | |
273 | |
274 static long tslot[1000]; | |
275 static long tick; | |
276 | |
277 void | |
278 usage(void) | |
279 { | |
280 long t; | |
281 | |
282 time(&t); | |
283 if(tick) | |
284 tslot[nrunning] += (t-tick); | |
285 tick = t; | |
286 } | |
287 | |
288 void | |
289 prusage(void) | |
290 { | |
291 int i; | |
292 | |
293 usage(); | |
294 for(i = 0; i <= nevents; i++) | |
295 fprint(1, "%d: %ld\n", i, tslot[i]); | |
296 } |