Introduction
Introduction Statistics Contact Development Disclaimer Help
run.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
run.c (5103B)
---
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, j->r->shellt);
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 virtu…
73 }
74 n->time = time((long *)0);
75 MADESET(n, MADE);
76 }
77 } else {
78 if(DEBUG(D_EXEC))
79 fprint(1, "recipe='%s'", 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, j->…
86 usage();
87 nrunning++;
88 if(DEBUG(D_EXEC))
89 fprint(1, "pid for target %s = %d\n", wtos(j->t,…
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): %r\n", echildok);
125 Exit();
126 }
127 }
128 if(DEBUG(D_EXEC))
129 fprint(1, "waitup got pid=%d, status='%s'\n", pid, buf);
130 if(retstatus && pid == *retstatus){
131 *retstatus = buf[0]? 1:0;
132 return(-1);
133 }
134 slot = pidslot(pid);
135 if(slot < 0){
136 if(DEBUG(D_EXEC))
137 fprint(2, "mk: wait returned unexpected process …
138 pnew(pid, buf[0]? 1:0);
139 goto again;
140 }
141 j = events[slot].job;
142 usage();
143 nrunning--;
144 events[slot].pid = -1;
145 if(buf[0]){
146 e = buildenv(j, slot);
147 bp = newbuf();
148 shprint(j->r->recipe, e, bp, j->r->shellt);
149 front(bp->start);
150 fprint(2, "mk: %s: exit status=%s", bp->start, buf);
151 freebuf(bp);
152 for(n = j->n, done = 0; n; n = n->next)
153 if(n->flags&DELETE){
154 if(done++ == 0)
155 fprint(2, ", deleting");
156 fprint(2, " '%s'", n->name);
157 delete(n->name);
158 }
159 fprint(2, "\n");
160 if(kflag){
161 runerrs++;
162 uarg = 1;
163 } else {
164 jobs = 0;
165 Exit();
166 }
167 }
168 for(w = j->t; w; w = w->next){
169 if((s = symlook(w->s, S_NODE, 0)) == 0)
170 continue; /* not interested in this node …
171 update(uarg, s->u.ptr);
172 }
173 if(nrunning < nproclimit)
174 sched();
175 return(0);
176 }
177
178 void
179 nproc(void)
180 {
181 Symtab *sym;
182 Word *w;
183
184 if(sym = symlook("NPROC", S_VAR, 0)) {
185 w = sym->u.ptr;
186 if (w && w->s && w->s[0])
187 nproclimit = atoi(w->s);
188 }
189 if(nproclimit < 1)
190 nproclimit = 1;
191 if(DEBUG(D_EXEC))
192 fprint(1, "nprocs = %d\n", nproclimit);
193 if(nproclimit > nevents){
194 if(nevents)
195 events = (Event *)Realloc((char *)events, nprocl…
196 else
197 events = (Event *)Malloc(nproclimit*sizeof(Event…
198 while(nevents < nproclimit)
199 events[nevents++].pid = 0;
200 }
201 }
202
203 int
204 nextslot(void)
205 {
206 int i;
207
208 for(i = 0; i < nproclimit; i++)
209 if(events[i].pid <= 0) return i;
210 assert("out of slots!!", 0);
211 return 0; /* cyntax */
212 }
213
214 int
215 pidslot(int pid)
216 {
217 int i;
218
219 for(i = 0; i < nevents; i++)
220 if(events[i].pid == pid) return(i);
221 if(DEBUG(D_EXEC))
222 fprint(2, "mk: wait returned unexpected process %d\n", p…
223 return(-1);
224 }
225
226
227 static void
228 pnew(int pid, int status)
229 {
230 Process *p;
231
232 if(pfree){
233 p = pfree;
234 pfree = p->f;
235 } else
236 p = (Process *)Malloc(sizeof(Process));
237 p->pid = pid;
238 p->status = status;
239 p->f = phead;
240 phead = p;
241 if(p->f)
242 p->f->b = p;
243 p->b = 0;
244 }
245
246 static void
247 pdelete(Process *p)
248 {
249 if(p->f)
250 p->f->b = p->b;
251 if(p->b)
252 p->b->f = p->f;
253 else
254 phead = p->f;
255 p->f = pfree;
256 pfree = p;
257 }
258
259 void
260 killchildren(char *msg)
261 {
262 Process *p;
263
264 kflag = 1; /* to make sure waitup doesn't exit */
265 jobs = 0; /* make sure no more get scheduled */
266 for(p = phead; p; p = p->f)
267 expunge(p->pid, msg);
268 while(waitup(1, (int *)0) == 0)
269 ;
270 Bprint(&bout, "mk: %s\n", msg);
271 Exit();
272 }
273
274 static long tslot[1000];
275 static long tick;
276
277 void
278 usage(void)
279 {
280 long t;
281
282 time(&t);
283 if(tick)
284 tslot[nrunning] += (t-tick);
285 tick = t;
286 }
287
288 void
289 prusage(void)
290 {
291 int i;
292
293 usage();
294 for(i = 0; i <= nevents; i++)
295 fprint(1, "%d: %ld\n", i, tslot[i]);
296 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.