URI: 
       run.c - 9base - revived minimalist port of Plan 9 userland to Unix
  HTML git clone git://git.suckless.org/9base
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR 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 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 }