Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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, nproclimit;
10
 
11
typedef struct Process
12
{
13
	int pid;
14
	int status;
15
	struct Process *b, *f;
16
} Process;
17
static Process *phead, *pfree;
18
static void sched(void);
19
static void pnew(int, int), pdelete(Process *);
20
 
21
int pidslot(int);
22
 
23
void
24
run(Job *j)
25
{
26
	Job *jj;
27
 
28
	if(jobs){
29
		for(jj = jobs; jj->next; jj = jj->next)
30
			;
31
		jj->next = j;
32
	} else 
33
		jobs = j;
34
	j->next = 0;
35
	/* this code also in waitup after parse redirect */
36
	if(nrunning < nproclimit)
37
		sched();
38
}
39
 
40
static void
41
sched(void)
42
{
43
	char *flags;
44
	Job *j;
45
	Bufblock *buf;
46
	int slot;
47
	Node *n;
48
	Envy *e;
49
 
50
	if(jobs == 0){
51
		usage();
52
		return;
53
	}
54
	j = jobs;
55
	jobs = j->next;
56
	if(DEBUG(D_EXEC))
57
		fprint(1, "firing up job for target %s\n", wtos(j->t, ' '));
58
	slot = nextslot();
59
	events[slot].job = j;
60
	buf = newbuf();
61
	e = buildenv(j, slot);
62
	shprint(j->r->recipe, e, buf);
63
	if(!tflag && (nflag || !(j->r->attr&QUIET)))
64
		Bwrite(&bout, buf->start, (long)strlen(buf->start));
65
	freebuf(buf);
66
	if(nflag||tflag){
67
		for(n = j->n; n; n = n->next){
68
			if(tflag){
69
				if(!(n->flags&VIRTUAL))
70
					touch(n->name);
71
				else if(explain)
72
					Bprint(&bout, "no touch of virtual '%s'\n", n->name);
73
			}
74
			n->time = time((long *)0);
75
			MADESET(n, MADE);
76
		}
77
	} else {
78
		if(DEBUG(D_EXEC))
79
			fprint(1, "recipe='%s'\n", j->r->recipe);	/**/
80
		Bflush(&bout);
81
		if(j->r->attr&NOMINUSE)
82
			flags = 0;
83
		else
84
			flags = "-e";
85
		events[slot].pid = execsh(flags, j->r->recipe, 0, e);
86
		usage();
87
		nrunning++;
88
		if(DEBUG(D_EXEC))
89
			fprint(1, "pid for target %s = %d\n", wtos(j->t, ' '), events[slot].pid);
90
	}
91
}
92
 
93
int
94
waitup(int echildok, int *retstatus)
95
{
96
	Envy *e;
97
	int pid;
98
	int slot;
99
	Symtab *s;
100
	Word *w;
101
	Job *j;
102
	char buf[ERRMAX];
103
	Bufblock *bp;
104
	int uarg = 0;
105
	int done;
106
	Node *n;
107
	Process *p;
108
	extern int runerrs;
109
 
110
	/* first check against the proces slist */
111
	if(retstatus)
112
		for(p = phead; p; p = p->f)
113
			if(p->pid == *retstatus){
114
				*retstatus = p->status;
115
				pdelete(p);
116
				return(-1);
117
			}
118
again:		/* rogue processes */
119
	pid = waitfor(buf);
120
	if(pid == -1){
121
		if(echildok > 0)
122
			return(1);
123
		else {
124
			fprint(2, "mk: (waitup %d) ", echildok);
125
			perror("mk wait");
126
			Exit();
127
		}
128
	}
129
	if(DEBUG(D_EXEC))
130
		fprint(1, "waitup got pid=%d, status='%s'\n", pid, buf);
131
	if(retstatus && pid == *retstatus){
132
		*retstatus = buf[0]? 1:0;
133
		return(-1);
134
	}
135
	slot = pidslot(pid);
136
	if(slot < 0){
137
		if(DEBUG(D_EXEC))
138
			fprint(2, "mk: wait returned unexpected process %d\n", pid);
139
		pnew(pid, buf[0]? 1:0);
140
		goto again;
141
	}
142
	j = events[slot].job;
143
	usage();
144
	nrunning--;
145
	events[slot].pid = -1;
146
	if(buf[0]){
147
		e = buildenv(j, slot);
148
		bp = newbuf();
149
		shprint(j->r->recipe, e, bp);
150
		front(bp->start);
151
		fprint(2, "mk: %s: exit status=%s", bp->start, buf);
152
		freebuf(bp);
153
		for(n = j->n, done = 0; n; n = n->next)
154
			if(n->flags&DELETE){
155
				if(done++ == 0)
156
					fprint(2, ", deleting");
157
				fprint(2, " '%s'", n->name);
158
				delete(n->name);
159
			}
160
		fprint(2, "\n");
161
		if(kflag){
162
			runerrs++;
163
			uarg = 1;
164
		} else {
165
			jobs = 0;
166
			Exit();
167
		}
168
	}
169
	for(w = j->t; w; w = w->next){
170
		if((s = symlook(w->s, S_NODE, 0)) == 0)
171
			continue;	/* not interested in this node */
172
		update(uarg, s->u.ptr);
173
	}
174
	if(nrunning < nproclimit)
175
		sched();
176
	return(0);
177
}
178
 
179
void
180
nproc(void)
181
{
182
	Symtab *sym;
183
	Word *w;
184
 
185
	if(sym = symlook("NPROC", S_VAR, 0)) {
186
		w = sym->u.ptr;
187
		if (w && w->s && w->s[0])
188
			nproclimit = atoi(w->s);
189
	}
190
	if(nproclimit < 1)
191
		nproclimit = 1;
192
	if(DEBUG(D_EXEC))
193
		fprint(1, "nprocs = %d\n", nproclimit);
194
	if(nproclimit > nevents){
195
		if(nevents)
196
			events = (Event *)Realloc((char *)events, nproclimit*sizeof(Event));
197
		else
198
			events = (Event *)Malloc(nproclimit*sizeof(Event));
199
		while(nevents < nproclimit)
200
			events[nevents++].pid = 0;
201
	}
202
}
203
 
204
int
205
nextslot(void)
206
{
207
	int i;
208
 
209
	for(i = 0; i < nproclimit; i++)
210
		if(events[i].pid <= 0) return i;
211
	assert(/*out of slots!!*/ 0);
212
	return 0;	/* cyntax */
213
}
214
 
215
int
216
pidslot(int pid)
217
{
218
	int i;
219
 
220
	for(i = 0; i < nevents; i++)
221
		if(events[i].pid == pid) return(i);
222
	if(DEBUG(D_EXEC))
223
		fprint(2, "mk: wait returned unexpected process %d\n", pid);
224
	return(-1);
225
}
226
 
227
 
228
static void
229
pnew(int pid, int status)
230
{
231
	Process *p;
232
 
233
	if(pfree){
234
		p = pfree;
235
		pfree = p->f;
236
	} else
237
		p = (Process *)Malloc(sizeof(Process));
238
	p->pid = pid;
239
	p->status = status;
240
	p->f = phead;
241
	phead = p;
242
	if(p->f)
243
		p->f->b = p;
244
	p->b = 0;
245
}
246
 
247
static void
248
pdelete(Process *p)
249
{
250
	if(p->f)
251
		p->f->b = p->b;
252
	if(p->b)
253
		p->b->f = p->f;
254
	else
255
		phead = p->f;
256
	p->f = pfree;
257
	pfree = p;
258
}
259
 
260
void
261
killchildren(char *msg)
262
{
263
	Process *p;
264
 
265
	kflag = 1;	/* to make sure waitup doesn't exit */
266
	jobs = 0;	/* make sure no more get scheduled */
267
	for(p = phead; p; p = p->f)
268
		expunge(p->pid, msg);
269
	while(waitup(1, (int *)0) == 0)
270
		;
271
	Bprint(&bout, "mk: %s\n", msg);
272
	Exit();
273
}
274
 
275
static ulong tslot[1000];
276
static ulong tick;
277
 
278
void
279
usage(void)
280
{
281
	ulong t;
282
 
283
	t = time(0);
284
	if(tick)
285
		tslot[nrunning] += t - tick;
286
	tick = t;
287
}
288
 
289
void
290
prusage(void)
291
{
292
	int i;
293
 
294
	usage();
295
	for(i = 0; i <= nevents; i++)
296
		fprint(1, "%d: %lud\n", i, tslot[i]);
297
}