|
|
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.