xref: /plan9/sys/src/cmd/mk/run.c (revision 7f49a7ff54b1fd29a638d67350c7ceb952fbe2d6)
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