~ubuntu-branches/ubuntu/saucy/9base/saucy

« back to all changes in this revision

Viewing changes to mk/run.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-11-07 12:25:14 UTC
  • mfrom: (6.2.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091107122514-tcw4u4ha2w2xbbnn
* Adding maintainer homepage field to control.
* Marking maintainer homepage field to be also included in binary
  packages and changelog.
* Adding README.source.
* Merging upstream version 4.
* Adding sh4 to explicit architecture list (Closes: #545772).
* Moving maintainer homepage field from control to copyright.
* Updating README.source.
* Updating homepage field in control.
* Removing manpage patch, went upstream.
* Removing kfreebsd.patch, went upstream.
* Generalizing manpage moving in rules.
* Moving base directory from /usr/lib/9base to /usr/lib/plan9 for
  consistency reasons.
* Prefixing manpages with plan9 instead of 9base for consistency
  reasons.
* Bumping versioned build-depends on debhelper.
* Making internal mkMAP and sendcover scripts executable.
* Adding patch to adjust shebang in newly included troff commands.
* Updating lintian-overrides.
* Making buildd-depends on quilt versioned.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 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'", 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->r->shellt, j->r->shellcmd);
 
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): %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 %d\n", pid);
 
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, nproclimit*sizeof(Event));
 
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", pid);
 
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
}