13e12c5d1SDavid du Colombier #include "mk.h"
23e12c5d1SDavid du Colombier
33e12c5d1SDavid du Colombier typedef struct Event
43e12c5d1SDavid du Colombier {
53e12c5d1SDavid du Colombier int pid;
63e12c5d1SDavid du Colombier Job *job;
73e12c5d1SDavid du Colombier } Event;
83e12c5d1SDavid du Colombier static Event *events;
97dd7cddfSDavid du Colombier static int nevents, nrunning, nproclimit;
107dd7cddfSDavid du Colombier
113e12c5d1SDavid du Colombier typedef struct Process
123e12c5d1SDavid du Colombier {
133e12c5d1SDavid du Colombier int pid;
143e12c5d1SDavid du Colombier int status;
153e12c5d1SDavid du Colombier struct Process *b, *f;
163e12c5d1SDavid du Colombier } Process;
173e12c5d1SDavid du Colombier static Process *phead, *pfree;
183e12c5d1SDavid du Colombier static void sched(void);
193e12c5d1SDavid du Colombier static void pnew(int, int), pdelete(Process *);
203e12c5d1SDavid du Colombier
217dd7cddfSDavid du Colombier int pidslot(int);
223e12c5d1SDavid du Colombier
233e12c5d1SDavid du Colombier void
run(Job * j)243e12c5d1SDavid du Colombier run(Job *j)
253e12c5d1SDavid du Colombier {
263e12c5d1SDavid du Colombier Job *jj;
273e12c5d1SDavid du Colombier
283e12c5d1SDavid du Colombier if(jobs){
293e12c5d1SDavid du Colombier for(jj = jobs; jj->next; jj = jj->next)
303e12c5d1SDavid du Colombier ;
313e12c5d1SDavid du Colombier jj->next = j;
323e12c5d1SDavid du Colombier } else
333e12c5d1SDavid du Colombier jobs = j;
343e12c5d1SDavid du Colombier j->next = 0;
353e12c5d1SDavid du Colombier /* this code also in waitup after parse redirect */
363e12c5d1SDavid du Colombier if(nrunning < nproclimit)
373e12c5d1SDavid du Colombier sched();
383e12c5d1SDavid du Colombier }
393e12c5d1SDavid du Colombier
403e12c5d1SDavid du Colombier static void
sched(void)413e12c5d1SDavid du Colombier sched(void)
423e12c5d1SDavid du Colombier {
437dd7cddfSDavid du Colombier char *flags;
443e12c5d1SDavid du Colombier Job *j;
453e12c5d1SDavid du Colombier Bufblock *buf;
467dd7cddfSDavid du Colombier int slot;
473e12c5d1SDavid du Colombier Node *n;
487dd7cddfSDavid du Colombier Envy *e;
493e12c5d1SDavid du Colombier
503e12c5d1SDavid du Colombier if(jobs == 0){
51219b2ee8SDavid du Colombier usage();
523e12c5d1SDavid du Colombier return;
533e12c5d1SDavid du Colombier }
543e12c5d1SDavid du Colombier j = jobs;
553e12c5d1SDavid du Colombier jobs = j->next;
563e12c5d1SDavid du Colombier if(DEBUG(D_EXEC))
577dd7cddfSDavid du Colombier fprint(1, "firing up job for target %s\n", wtos(j->t, ' '));
583e12c5d1SDavid du Colombier slot = nextslot();
593e12c5d1SDavid du Colombier events[slot].job = j;
603e12c5d1SDavid du Colombier buf = newbuf();
617dd7cddfSDavid du Colombier e = buildenv(j, slot);
627dd7cddfSDavid du Colombier shprint(j->r->recipe, e, buf);
633e12c5d1SDavid du Colombier if(!tflag && (nflag || !(j->r->attr&QUIET)))
647dd7cddfSDavid du Colombier Bwrite(&bout, buf->start, (long)strlen(buf->start));
653e12c5d1SDavid du Colombier freebuf(buf);
663e12c5d1SDavid du Colombier if(nflag||tflag){
673e12c5d1SDavid du Colombier for(n = j->n; n; n = n->next){
683e12c5d1SDavid du Colombier if(tflag){
693e12c5d1SDavid du Colombier if(!(n->flags&VIRTUAL))
703e12c5d1SDavid du Colombier touch(n->name);
713e12c5d1SDavid du Colombier else if(explain)
7299eb86a7SDavid du Colombier Bprint(&bout, "no touch of virtual '%s'\n", n->name);
733e12c5d1SDavid du Colombier }
743e12c5d1SDavid du Colombier n->time = time((long *)0);
753e12c5d1SDavid du Colombier MADESET(n, MADE);
763e12c5d1SDavid du Colombier }
773e12c5d1SDavid du Colombier } else {
787dd7cddfSDavid du Colombier if(DEBUG(D_EXEC))
79276e7d6dSDavid du Colombier fprint(1, "recipe='%s'\n", j->r->recipe); /**/
807dd7cddfSDavid du Colombier Bflush(&bout);
813e12c5d1SDavid du Colombier if(j->r->attr&NOMINUSE)
827dd7cddfSDavid du Colombier flags = 0;
833e12c5d1SDavid du Colombier else
847dd7cddfSDavid du Colombier flags = "-e";
857dd7cddfSDavid du Colombier events[slot].pid = execsh(flags, j->r->recipe, 0, e);
86219b2ee8SDavid du Colombier usage();
873e12c5d1SDavid du Colombier nrunning++;
883e12c5d1SDavid du Colombier if(DEBUG(D_EXEC))
8999eb86a7SDavid du Colombier fprint(1, "pid for target %s = %d\n", wtos(j->t, ' '), events[slot].pid);
903e12c5d1SDavid du Colombier }
913e12c5d1SDavid du Colombier }
923e12c5d1SDavid du Colombier
933e12c5d1SDavid du Colombier int
waitup(int echildok,int * retstatus)943e12c5d1SDavid du Colombier waitup(int echildok, int *retstatus)
953e12c5d1SDavid du Colombier {
967dd7cddfSDavid du Colombier Envy *e;
973e12c5d1SDavid du Colombier int pid;
983e12c5d1SDavid du Colombier int slot;
993e12c5d1SDavid du Colombier Symtab *s;
1003e12c5d1SDavid du Colombier Word *w;
1013e12c5d1SDavid du Colombier Job *j;
1029a747e4fSDavid du Colombier char buf[ERRMAX];
1033e12c5d1SDavid du Colombier Bufblock *bp;
1043e12c5d1SDavid du Colombier int uarg = 0;
1053e12c5d1SDavid du Colombier int done;
1063e12c5d1SDavid du Colombier Node *n;
1073e12c5d1SDavid du Colombier Process *p;
108219b2ee8SDavid du Colombier extern int runerrs;
1093e12c5d1SDavid du Colombier
1103e12c5d1SDavid du Colombier /* first check against the proces slist */
1113e12c5d1SDavid du Colombier if(retstatus)
1123e12c5d1SDavid du Colombier for(p = phead; p; p = p->f)
1133e12c5d1SDavid du Colombier if(p->pid == *retstatus){
1143e12c5d1SDavid du Colombier *retstatus = p->status;
1153e12c5d1SDavid du Colombier pdelete(p);
1163e12c5d1SDavid du Colombier return(-1);
1173e12c5d1SDavid du Colombier }
1183e12c5d1SDavid du Colombier again: /* rogue processes */
1197dd7cddfSDavid du Colombier pid = waitfor(buf);
1207dd7cddfSDavid du Colombier if(pid == -1){
1213e12c5d1SDavid du Colombier if(echildok > 0)
1223e12c5d1SDavid du Colombier return(1);
1233e12c5d1SDavid du Colombier else {
1243e12c5d1SDavid du Colombier fprint(2, "mk: (waitup %d) ", echildok);
1253e12c5d1SDavid du Colombier perror("mk wait");
1263e12c5d1SDavid du Colombier Exit();
1273e12c5d1SDavid du Colombier }
1283e12c5d1SDavid du Colombier }
1293e12c5d1SDavid du Colombier if(DEBUG(D_EXEC))
1307dd7cddfSDavid du Colombier fprint(1, "waitup got pid=%d, status='%s'\n", pid, buf);
1317dd7cddfSDavid du Colombier if(retstatus && pid == *retstatus){
132219b2ee8SDavid du Colombier *retstatus = buf[0]? 1:0;
1333e12c5d1SDavid du Colombier return(-1);
1343e12c5d1SDavid du Colombier }
1353e12c5d1SDavid du Colombier slot = pidslot(pid);
1363e12c5d1SDavid du Colombier if(slot < 0){
1373e12c5d1SDavid du Colombier if(DEBUG(D_EXEC))
1383e12c5d1SDavid du Colombier fprint(2, "mk: wait returned unexpected process %d\n", pid);
139219b2ee8SDavid du Colombier pnew(pid, buf[0]? 1:0);
1403e12c5d1SDavid du Colombier goto again;
1413e12c5d1SDavid du Colombier }
1423e12c5d1SDavid du Colombier j = events[slot].job;
143219b2ee8SDavid du Colombier usage();
1443e12c5d1SDavid du Colombier nrunning--;
1453e12c5d1SDavid du Colombier events[slot].pid = -1;
146219b2ee8SDavid du Colombier if(buf[0]){
1477dd7cddfSDavid du Colombier e = buildenv(j, slot);
1483e12c5d1SDavid du Colombier bp = newbuf();
1497dd7cddfSDavid du Colombier shprint(j->r->recipe, e, bp);
1503e12c5d1SDavid du Colombier front(bp->start);
151219b2ee8SDavid du Colombier fprint(2, "mk: %s: exit status=%s", bp->start, buf);
1523e12c5d1SDavid du Colombier freebuf(bp);
1533e12c5d1SDavid du Colombier for(n = j->n, done = 0; n; n = n->next)
1543e12c5d1SDavid du Colombier if(n->flags&DELETE){
1553e12c5d1SDavid du Colombier if(done++ == 0)
1563e12c5d1SDavid du Colombier fprint(2, ", deleting");
1573e12c5d1SDavid du Colombier fprint(2, " '%s'", n->name);
1583e12c5d1SDavid du Colombier delete(n->name);
1593e12c5d1SDavid du Colombier }
1607dd7cddfSDavid du Colombier fprint(2, "\n");
1613e12c5d1SDavid du Colombier if(kflag){
1623e12c5d1SDavid du Colombier runerrs++;
1633e12c5d1SDavid du Colombier uarg = 1;
1643e12c5d1SDavid du Colombier } else {
1653e12c5d1SDavid du Colombier jobs = 0;
1663e12c5d1SDavid du Colombier Exit();
1673e12c5d1SDavid du Colombier }
1683e12c5d1SDavid du Colombier }
1693e12c5d1SDavid du Colombier for(w = j->t; w; w = w->next){
1707dd7cddfSDavid du Colombier if((s = symlook(w->s, S_NODE, 0)) == 0)
1713e12c5d1SDavid du Colombier continue; /* not interested in this node */
1724de34a7eSDavid du Colombier update(uarg, s->u.ptr);
1733e12c5d1SDavid du Colombier }
1743e12c5d1SDavid du Colombier if(nrunning < nproclimit)
1753e12c5d1SDavid du Colombier sched();
1763e12c5d1SDavid du Colombier return(0);
1773e12c5d1SDavid du Colombier }
1783e12c5d1SDavid du Colombier
1793e12c5d1SDavid du Colombier void
nproc(void)1803e12c5d1SDavid du Colombier nproc(void)
1813e12c5d1SDavid du Colombier {
1823e12c5d1SDavid du Colombier Symtab *sym;
1833e12c5d1SDavid du Colombier Word *w;
1843e12c5d1SDavid du Colombier
1857dd7cddfSDavid du Colombier if(sym = symlook("NPROC", S_VAR, 0)) {
1864de34a7eSDavid du Colombier w = sym->u.ptr;
1873e12c5d1SDavid du Colombier if (w && w->s && w->s[0])
1883e12c5d1SDavid du Colombier nproclimit = atoi(w->s);
1893e12c5d1SDavid du Colombier }
1903e12c5d1SDavid du Colombier if(nproclimit < 1)
1913e12c5d1SDavid du Colombier nproclimit = 1;
1923e12c5d1SDavid du Colombier if(DEBUG(D_EXEC))
1933e12c5d1SDavid du Colombier fprint(1, "nprocs = %d\n", nproclimit);
1943e12c5d1SDavid du Colombier if(nproclimit > nevents){
1953e12c5d1SDavid du Colombier if(nevents)
19699eb86a7SDavid du Colombier events = (Event *)Realloc((char *)events, nproclimit*sizeof(Event));
1973e12c5d1SDavid du Colombier else
1983e12c5d1SDavid du Colombier events = (Event *)Malloc(nproclimit*sizeof(Event));
1993e12c5d1SDavid du Colombier while(nevents < nproclimit)
2003e12c5d1SDavid du Colombier events[nevents++].pid = 0;
2013e12c5d1SDavid du Colombier }
2023e12c5d1SDavid du Colombier }
2033e12c5d1SDavid du Colombier
2043e12c5d1SDavid du Colombier int
nextslot(void)2053e12c5d1SDavid du Colombier nextslot(void)
2063e12c5d1SDavid du Colombier {
2073e12c5d1SDavid du Colombier int i;
2083e12c5d1SDavid du Colombier
2093e12c5d1SDavid du Colombier for(i = 0; i < nproclimit; i++)
21099eb86a7SDavid du Colombier if(events[i].pid <= 0) return i;
2117dd7cddfSDavid du Colombier assert(/*out of slots!!*/ 0);
2123e12c5d1SDavid du Colombier return 0; /* cyntax */
2133e12c5d1SDavid du Colombier }
2143e12c5d1SDavid du Colombier
2153e12c5d1SDavid du Colombier int
pidslot(int pid)2163e12c5d1SDavid du Colombier pidslot(int pid)
2173e12c5d1SDavid du Colombier {
2183e12c5d1SDavid du Colombier int i;
2193e12c5d1SDavid du Colombier
2203e12c5d1SDavid du Colombier for(i = 0; i < nevents; i++)
22199eb86a7SDavid du Colombier if(events[i].pid == pid) return(i);
2223e12c5d1SDavid du Colombier if(DEBUG(D_EXEC))
2233e12c5d1SDavid du Colombier fprint(2, "mk: wait returned unexpected process %d\n", pid);
22499eb86a7SDavid du Colombier return(-1);
2253e12c5d1SDavid du Colombier }
2263e12c5d1SDavid du Colombier
2273e12c5d1SDavid du Colombier
2283e12c5d1SDavid du Colombier static void
pnew(int pid,int status)2293e12c5d1SDavid du Colombier pnew(int pid, int status)
2303e12c5d1SDavid du Colombier {
2313e12c5d1SDavid du Colombier Process *p;
2323e12c5d1SDavid du Colombier
2333e12c5d1SDavid du Colombier if(pfree){
2343e12c5d1SDavid du Colombier p = pfree;
2353e12c5d1SDavid du Colombier pfree = p->f;
2363e12c5d1SDavid du Colombier } else
2373e12c5d1SDavid du Colombier p = (Process *)Malloc(sizeof(Process));
2383e12c5d1SDavid du Colombier p->pid = pid;
2393e12c5d1SDavid du Colombier p->status = status;
2403e12c5d1SDavid du Colombier p->f = phead;
2413e12c5d1SDavid du Colombier phead = p;
2423e12c5d1SDavid du Colombier if(p->f)
2433e12c5d1SDavid du Colombier p->f->b = p;
2443e12c5d1SDavid du Colombier p->b = 0;
2453e12c5d1SDavid du Colombier }
2463e12c5d1SDavid du Colombier
2473e12c5d1SDavid du Colombier static void
pdelete(Process * p)2483e12c5d1SDavid du Colombier pdelete(Process *p)
2493e12c5d1SDavid du Colombier {
2503e12c5d1SDavid du Colombier if(p->f)
2513e12c5d1SDavid du Colombier p->f->b = p->b;
2523e12c5d1SDavid du Colombier if(p->b)
2533e12c5d1SDavid du Colombier p->b->f = p->f;
2543e12c5d1SDavid du Colombier else
2553e12c5d1SDavid du Colombier phead = p->f;
2563e12c5d1SDavid du Colombier p->f = pfree;
2573e12c5d1SDavid du Colombier pfree = p;
2583e12c5d1SDavid du Colombier }
2593e12c5d1SDavid du Colombier
2603e12c5d1SDavid du Colombier void
killchildren(char * msg)2613e12c5d1SDavid du Colombier killchildren(char *msg)
2623e12c5d1SDavid du Colombier {
2633e12c5d1SDavid du Colombier Process *p;
2643e12c5d1SDavid du Colombier
265219b2ee8SDavid du Colombier kflag = 1; /* to make sure waitup doesn't exit */
266219b2ee8SDavid du Colombier jobs = 0; /* make sure no more get scheduled */
2677dd7cddfSDavid du Colombier for(p = phead; p; p = p->f)
2687dd7cddfSDavid du Colombier expunge(p->pid, msg);
269219b2ee8SDavid du Colombier while(waitup(1, (int *)0) == 0)
270219b2ee8SDavid du Colombier ;
2717dd7cddfSDavid du Colombier Bprint(&bout, "mk: %s\n", msg);
272219b2ee8SDavid du Colombier Exit();
2733e12c5d1SDavid du Colombier }
274219b2ee8SDavid du Colombier
275*7f49a7ffSDavid du Colombier static ulong tslot[1000];
276*7f49a7ffSDavid du Colombier static ulong tick;
277219b2ee8SDavid du Colombier
278219b2ee8SDavid du Colombier void
usage(void)279219b2ee8SDavid du Colombier usage(void)
280219b2ee8SDavid du Colombier {
281*7f49a7ffSDavid du Colombier ulong t;
282219b2ee8SDavid du Colombier
283*7f49a7ffSDavid du Colombier t = time(0);
284219b2ee8SDavid du Colombier if(tick)
285*7f49a7ffSDavid du Colombier tslot[nrunning] += t - tick;
286219b2ee8SDavid du Colombier tick = t;
287219b2ee8SDavid du Colombier }
288219b2ee8SDavid du Colombier
289219b2ee8SDavid du Colombier void
prusage(void)290219b2ee8SDavid du Colombier prusage(void)
291219b2ee8SDavid du Colombier {
292219b2ee8SDavid du Colombier int i;
293219b2ee8SDavid du Colombier
294219b2ee8SDavid du Colombier usage();
295219b2ee8SDavid du Colombier for(i = 0; i <= nevents; i++)
296*7f49a7ffSDavid du Colombier fprint(1, "%d: %lud\n", i, tslot[i]);
297219b2ee8SDavid du Colombier }
298