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; 9*7dd7cddfSDavid du Colombier static int nevents, nrunning, nproclimit; 10*7dd7cddfSDavid 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 21*7dd7cddfSDavid du Colombier int pidslot(int); 223e12c5d1SDavid du Colombier 233e12c5d1SDavid du Colombier void 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 413e12c5d1SDavid du Colombier sched(void) 423e12c5d1SDavid du Colombier { 43*7dd7cddfSDavid du Colombier char *flags; 443e12c5d1SDavid du Colombier Job *j; 453e12c5d1SDavid du Colombier Bufblock *buf; 46*7dd7cddfSDavid du Colombier int slot; 473e12c5d1SDavid du Colombier Node *n; 48*7dd7cddfSDavid 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)) 57*7dd7cddfSDavid 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(); 61*7dd7cddfSDavid du Colombier e = buildenv(j, slot); 62*7dd7cddfSDavid du Colombier shprint(j->r->recipe, e, buf); 633e12c5d1SDavid du Colombier if(!tflag && (nflag || !(j->r->attr&QUIET))) 64*7dd7cddfSDavid 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) 72*7dd7cddfSDavid 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 { 78*7dd7cddfSDavid du Colombier if(DEBUG(D_EXEC)) 79*7dd7cddfSDavid du Colombier fprint(1, "recipe='%s'", j->r->recipe);/**/ 80*7dd7cddfSDavid du Colombier Bflush(&bout); 813e12c5d1SDavid du Colombier if(j->r->attr&NOMINUSE) 82*7dd7cddfSDavid du Colombier flags = 0; 833e12c5d1SDavid du Colombier else 84*7dd7cddfSDavid du Colombier flags = "-e"; 85*7dd7cddfSDavid 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)) 89*7dd7cddfSDavid 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 943e12c5d1SDavid du Colombier waitup(int echildok, int *retstatus) 953e12c5d1SDavid du Colombier { 96*7dd7cddfSDavid 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; 102219b2ee8SDavid du Colombier char buf[ERRLEN]; 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 */ 119*7dd7cddfSDavid du Colombier pid = waitfor(buf); 120*7dd7cddfSDavid 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)) 130*7dd7cddfSDavid du Colombier fprint(1, "waitup got pid=%d, status='%s'\n", pid, buf); 131*7dd7cddfSDavid 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]){ 147*7dd7cddfSDavid du Colombier e = buildenv(j, slot); 1483e12c5d1SDavid du Colombier bp = newbuf(); 149*7dd7cddfSDavid 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 } 160*7dd7cddfSDavid 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){ 170*7dd7cddfSDavid du Colombier if((s = symlook(w->s, S_NODE, 0)) == 0) 1713e12c5d1SDavid du Colombier continue; /* not interested in this node */ 1723e12c5d1SDavid du Colombier update(uarg, (Node *)s->value); 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 1803e12c5d1SDavid du Colombier nproc(void) 1813e12c5d1SDavid du Colombier { 1823e12c5d1SDavid du Colombier Symtab *sym; 1833e12c5d1SDavid du Colombier Word *w; 1843e12c5d1SDavid du Colombier 185*7dd7cddfSDavid du Colombier if(sym = symlook("NPROC", S_VAR, 0)) { 1863e12c5d1SDavid du Colombier w = (Word *) sym->value; 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) 1963e12c5d1SDavid 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 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++) 2103e12c5d1SDavid du Colombier if(events[i].pid <= 0) return i; 211*7dd7cddfSDavid du Colombier assert(/*out of slots!!*/ 0); 2123e12c5d1SDavid du Colombier return 0; /* cyntax */ 2133e12c5d1SDavid du Colombier } 2143e12c5d1SDavid du Colombier 2153e12c5d1SDavid du Colombier int 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++) 2213e12c5d1SDavid 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); 2243e12c5d1SDavid du Colombier return(-1); 2253e12c5d1SDavid du Colombier } 2263e12c5d1SDavid du Colombier 2273e12c5d1SDavid du Colombier 2283e12c5d1SDavid du Colombier static void 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 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 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 */ 267*7dd7cddfSDavid du Colombier for(p = phead; p; p = p->f) 268*7dd7cddfSDavid du Colombier expunge(p->pid, msg); 269219b2ee8SDavid du Colombier while(waitup(1, (int *)0) == 0) 270219b2ee8SDavid du Colombier ; 271*7dd7cddfSDavid du Colombier Bprint(&bout, "mk: %s\n", msg); 272219b2ee8SDavid du Colombier Exit(); 2733e12c5d1SDavid du Colombier } 274219b2ee8SDavid du Colombier 275219b2ee8SDavid du Colombier static long tslot[1000]; 276219b2ee8SDavid du Colombier static long tick; 277219b2ee8SDavid du Colombier 278219b2ee8SDavid du Colombier void 279219b2ee8SDavid du Colombier usage(void) 280219b2ee8SDavid du Colombier { 281219b2ee8SDavid du Colombier long t; 282219b2ee8SDavid du Colombier 283219b2ee8SDavid du Colombier time(&t); 284219b2ee8SDavid du Colombier if(tick) 285219b2ee8SDavid du Colombier tslot[nrunning] += (t-tick); 286219b2ee8SDavid du Colombier tick = t; 287219b2ee8SDavid du Colombier } 288219b2ee8SDavid du Colombier 289219b2ee8SDavid du Colombier 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++) 296219b2ee8SDavid du Colombier fprint(1, "%d: %ld\n", i, tslot[i]); 297219b2ee8SDavid du Colombier } 298