|
|
1.1 root 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;
10: typedef struct Process
11: {
12: int pid;
13: int status;
14: struct Process *b, *f;
15: } Process;
16: static Process *phead, *pfree;
17: static void pnew(), pdelete();
18: static char *envy[1024];
19: static char **special;
20: static pidslot();
21:
22: run(j)
23: Job *j;
24: {
25: register Job *jj;
26:
27: if(jobs){
28: for(jj = jobs; jj->next; jj = jj->next)
29: ;
30: jj->next = j;
31: } else
32: jobs = j;
33: j->next = 0;
34: /* this code also in waitup after parse redirect */
35: if(nrunning < nproclimit)
36: sched();
37: }
38:
39: sched()
40: {
41: register Job *j;
42: char buf[BIGBLOCK];
43: int slot, pip[2], pid;
44: Node *n;
45:
46: if(jobs == 0){
47: account();
48: return;
49: }
50: j = jobs;
51: jobs = j->next;
52: if(DEBUG(D_EXEC))
53: fprint(1, "firing up job for target %s\n", wtos(j->t));
54: slot = nextslot();
55: events[slot].job = j;
56: dovars(j, slot);
57: shprint(j->r->recipe, envy, buf);
58: if(!tflag && !mflag && (nflag || !(j->r->attr&QUIET)))
59: Fwrite(1, buf, (long)strlen(buf));
60: if(mflag){
61: for(n = j->n; n; n = n->next)
62: symlook(n->name, S_MAKEFILE, (char *)j);
63: }
64: if(nflag||tflag){
65: for(n = j->n; n; n = n->next){
66: if(tflag){
67: if(!(n->flags&VIRTUAL))
68: touch(n->name);
69: else if(explain)
70: Fprint(1, "no touch of virtual '%s'\n", n->name);
71: }
72: n->time = time((long *)0);
73: MADESET(n, MADE);
74: }
75: } else {
76: Fexit(0);
77: if(j->r->attr&RED){
78: if(pipe(pip) < 0){
79: perror("pipe");
80: Exit();
81: }
82: }
83: if((pid = fork()) < 0){
84: perror("mk fork");
85: Exit();
86: }
87: if(pid == 0){
88: if(j->r->attr&RED){
89: close(pip[0]);
90: dup2(pip[1], 1);
91: close(pip[1]);
92: }
93: if(pipe(pip) < 0){
94: perror("pipe-i");
95: Exit();
96: }
97: if((pid = fork()) < 0){
98: perror("mk fork");
99: Exit();
100: }
101: if(pid != 0){
102: close(pip[1]);
103: dup2(pip[0], 0);
104: close(pip[0]);
105: execle(SHELL, "sh", "-e", (char *)0, envy);
106: perror(SHELL);
107: _exit(1);
108: } else {
109: int k;
110: char *s, *send;
111:
112: close(pip[0]);
113: s = j->r->recipe;
114: send = s+strlen(s);
115: while(s < send){
116: if((k = write(pip[1], s, send-s)) < 0)
117: break;
118: s += k;
119: }
120: _exit(0);
121: }
122: }
123: account();
124: nrunning++;
125: if(j->r->attr&RED)
126: close(pip[1]), j->fd = pip[0];
127: else
128: j->fd = -1;
129: if(DEBUG(D_EXEC))
130: fprint(1, "pid for target %s = %d\n", wtos(j->t), pid);
131: events[slot].pid = pid;
132: }
133: }
134:
135: waitup(echildok, retstatus)
136: int *retstatus;
137: {
138: int status, pid;
139: int slot;
140: Symtab *s;
141: Word *w;
142: Job *j;
143: char buf[64];
144: char buf1[BIGBLOCK];
145: int uarg = 0;
146: int done;
147: Node *n;
148: Process *p;
149: extern int errno, runerrs;
150:
151: /* first check against the proces slist */
152: if(retstatus)
153: for(p = phead; p; p = p->f)
154: if(p->pid == *retstatus){
155: *retstatus = p->status;
156: pdelete(p);
157: return(-1);
158: }
159: again: /* rogue processes */
160: if((pid = wait(&status)) < 0){
161: if(echildok > 0){
162: return(1);
163: } else {
164: fprint(2, "mk: (waitup %d) ", echildok);
165: perror("mk wait");
166: Exit();
167: }
168: }
169: if(DEBUG(D_EXEC))
170: fprint(1, "waitup got pid=%d, status=0x%ux\n", pid, status);
171: if(retstatus && (pid == *retstatus)){
172: *retstatus = status;
173: return(-1);
174: }
175: slot = pidslot(pid);
176: if(slot < 0){
177: if(DEBUG(D_EXEC))
178: fprint(2, "mk: wait returned unexpected process %d\n", pid);
179: pnew(pid, status);
180: goto again;
181: }
182: j = events[slot].job;
183: account();
184: nrunning--;
185: events[slot].pid = -1;
186: if(status){
187: dovars(j, slot);
188: shprint(j->r->recipe, envy, buf1);
189: front(buf1);
190: Fprint(2, "mk: %s: exit status=%d", buf1, 0xFF&(status>>8));
191: status &= 0xFF;
192: if(status&0x7F)
193: Fprint(2, " signal=%d", status&0x7F);
194: if(status&0x80)
195: Fprint(2, ", core dumped");
196: for(n = j->n, done = 0; n; n = n->next)
197: if(n->flags&DELETE){
198: if(done++ == 0)
199: Fprint(2, ", deleting");
200: Fprint(2, " '%s'", n->name);
201: }
202: Fputc(2, '\n');
203: for(n = j->n, done = 0; n; n = n->next)
204: if(n->flags&DELETE){
205: if(done++ == 0)
206: Fflush(2);
207: delete(n->name);
208: }
209: if(kflag){
210: runerrs++;
211: uarg = 1;
212: Fflush(2);
213: } else {
214: jobs = 0;
215: Exit();
216: }
217: }
218: if(j->fd >= 0){
219: sprint(buf, "process %d", pid);
220: parse(buf, j->fd, 0, 0);
221: execinit(); /* reread environ */
222: nproc();
223: while(jobs && (nrunning < nproclimit))
224: sched();
225: }
226: for(w = j->t; w; w = w->next){
227: if((s = symlook(w->s, S_NODE, (char *)0)) == 0)
228: continue; /* not interested in this node */
229: update(uarg, (Node *)s->value);
230: }
231: if(nrunning < nproclimit)
232: sched();
233: return(0);
234: }
235:
236: execinit()
237: {
238: extern char **environ;
239: extern char **vardump();
240: register char *s, *ss, c;
241: Symtab *st;
242:
243: environ = envy;
244: special = vardump(envy);
245: if(st = symlook("ENVIRON", S_VAR, (char *)0))
246: for(s = st->value; *s;){
247: for(ss = s; *ss && (*ss != 1); ss++);
248: c = *ss;
249: *ss = 0;
250: *special++ = strdup(s);
251: s = ss;
252: if(*ss = c)
253: s++;
254: }
255: *special = 0;
256: }
257:
258: char *myenv[] =
259: {
260: "target", "stem", "prereq", "pid", "nproc", "newprereq",
261: "alltarget",
262: "stem1", "stem2", "stem3", "stem4", "stem5", "stem6",
263: "stem7", "stem8", "stem9", "stem0", 0
264: };
265:
266: dovars(j, slot)
267: register Job *j;
268: {
269: char buf[BIGBLOCK];
270: char *s, *t;
271: int i, n = 0;
272:
273: #define SPECIAL ((sizeof myenv)/(sizeof myenv[0])-1)
274: #define VSET(name, exp) {strcpy(buf, "name="); strcpy(strchr(buf, 0), exp);}
275:
276: for(i = 0; i < SPECIAL; i++)
277: if(special[i])
278: free(special[i]);
279: VSET(target, s = wtos(j->t));
280: special[n++] = strdup(buf);
281: free(s);
282: /* WATCH OUT; stem set below if reg exp!! */
283: VSET(stem, j->stem);
284: special[n++] = strdup(buf);
285: VSET(prereq, s = wtos(j->p));
286: special[n++] = strdup(buf);
287: free(s);
288: sprint(buf, "pid=%d", getpid());
289: special[n++] = strdup(buf);
290: sprint(buf, "nproc=%d", slot);
291: special[n++] = strdup(buf);
292: VSET(newprereq, s = wtos(j->np));
293: special[n++] = strdup(buf);
294: free(s);
295: VSET(alltarget, s = wtos(j->at));
296: special[n++] = strdup(buf);
297: free(s);
298: for(i = 0; i <= 9; i++){
299: sprint(buf, "stem%d=", i);
300: if(j->r->attr®EXP){
301: for(s = buf; *s; s++);
302: for(t = j->match[i].sp; t < j->match[i].ep; *s++ = *t++);
303: *s = 0;
304: }
305: special[n+i] = strdup(buf);
306: if((i == 1) && (j->r->attr®EXP)){
307: buf[1] = 's'; buf[2] = 't'; buf[3] = 'e'; buf[4] = 'm';
308: special[1] = strdup(buf+1);
309: }
310: }
311: special[SPECIAL] = 0;
312: }
313:
314: nproc()
315: {
316: register Symtab *sym;
317:
318: if(sym = symlook("NPROC", S_VAR, (char *)0))
319: nproclimit = atoi(sym->value);
320: if(nproclimit < 1)
321: nproclimit = 1;
322: if(DEBUG(D_EXEC))
323: fprint(1, "nprocs = %d\n", nproclimit);
324: if(nproclimit > nevents){
325: if(nevents)
326: events = (Event *)realloc((char *)events, nproclimit*sizeof(Event));
327: else
328: events = (Event *)malloc(nproclimit*sizeof(Event));
329: while(nevents < nproclimit)
330: events[nevents++].pid = 0;
331: }
332: }
333:
334: nextslot()
335: {
336: register i;
337:
338: for(i = 0; i < nproclimit; i++)
339: if(events[i].pid <= 0) return(i);
340: assert("out of slots!!", 0);
341: return(0); /* cyntax */
342: }
343:
344: static
345: pidslot(pid)
346: {
347: register i;
348:
349: for(i = 0; i < nevents; i++)
350: if(events[i].pid == pid) return(i);
351: return(-1);
352: }
353:
354: static void
355: pnew(pid, status)
356: {
357: register Process *p;
358:
359: if(pfree){
360: p = pfree;
361: pfree = p->f;
362: } else
363: p = (Process *)Malloc(sizeof(Process));
364: p->pid = pid;
365: p->status = status;
366: p->f = phead;
367: phead = p;
368: if(p->f)
369: p->f->b = p;
370: p->b = 0;
371: }
372:
373: static void
374: pdelete(p)
375: Process *p;
376: {
377: if(p->f)
378: p->f->b = p->b;
379: if(p->b)
380: p->b->f = p->f;
381: else
382: phead = p->f;
383: p->f = pfree;
384: pfree = p;
385: }
386:
387: static long tslot[1000];
388: static long tick;
389:
390: account()
391: {
392: long t;
393:
394: time(&t);
395: if(tick)
396: tslot[nrunning] += (t-tick);
397: tick = t;
398: }
399:
400: praccount()
401: {
402: int i;
403:
404: account();
405: for(i = 0; i <= nevents; i++)
406: Fprint(1, "%d: %ld\n", i, tslot[i]);
407: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.