ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rc3.c
(Generate patch)

Comparing ray/src/rt/rc3.c (file contents):
Revision 2.1 by greg, Sat Jun 9 07:16:47 2012 UTC vs.
Revision 2.3 by greg, Sun Jun 10 05:25:42 2012 UTC

# Line 23 | Line 23 | static BINQ    *out_bq = NULL;         /* output bin queue */
23   static BINQ     *free_bq = NULL;        /* free queue entries */
24  
25   static SUBPROC  kida[MAXPROCESS];       /* child processes */
26 + static FILE     *inq_fp[MAXPROCESS];    /* input streams */
27  
28  
29   /* Get new (empty) bin queue entry */
# Line 122 | Line 123 | add_modbin(BINQ *dst, BINQ *src)
123   }
124  
125  
126 < /* Queue output, catching up with and freeing FIFO entries when possible */
127 < static int
126 > /* Queue values for later output */
127 > static void
128   queue_output(BINQ *bp)
129   {
129        int     nout = 0;
130          BINQ    *b_last, *b_cur;
131        int     i;
131  
132          if (accumulate <= 0) {          /* just accumulating? */
133                  if (out_bq == NULL) {
# Line 138 | Line 137 | queue_output(BINQ *bp)
137                          add_modbin(out_bq, bp);
138                          free_binq(bp);
139                  }
140 <                return(0);
140 >                return;
141          }
142          b_last = NULL;                  /* else insert in output queue */
143          for (b_cur = out_bq; b_cur != NULL && b_cur->ndx < bp->ndx;
# Line 151 | Line 150 | queue_output(BINQ *bp)
150                  bp->next = out_bq;
151                  out_bq = bp;
152          }
153 <        if (accumulate > 1) {           /* merge accumulation entries */
154 <                b_cur = out_bq;
155 <                while (b_cur->next != NULL) {
156 <                        if (b_cur->n2add <= 0 ||
157 <                                        (b_cur->ndx-1)/accumulate !=
158 <                                        (b_cur->next->ndx-1)/accumulate) {
159 <                                b_cur = b_cur->next;
160 <                                continue;
161 <                        }
163 <                        add_modbin(b_cur, b_cur->next);
164 <                        b_cur->n2add--;
165 <                        b_last = b_cur->next;
166 <                        b_cur->next = b_last->next;
167 <                        b_last->next = NULL;
168 <                        free_binq(b_last);
153 >        if (accumulate == 1)            /* no accumulation? */
154 >                return;
155 >        b_cur = out_bq;                 /* else merge accumulation entries */
156 >        while (b_cur->next != NULL) {
157 >                if (b_cur->n2add <= 0 ||
158 >                                (b_cur->ndx-1)/accumulate !=
159 >                                (b_cur->next->ndx-1)/accumulate) {
160 >                        b_cur = b_cur->next;
161 >                        continue;
162                  }
163 +                add_modbin(b_cur, b_cur->next);
164 +                b_cur->n2add--;
165 +                b_last = b_cur->next;
166 +                b_cur->next = b_last->next;
167 +                b_last->next = NULL;
168 +                free_binq(b_last);
169          }
170 <                                        /* output ready results */
170 > }
171 >
172 >
173 > /* Get current with output queue by producing ready results */
174 > static int
175 > output_catchup()
176 > {
177 >        int     nout = 0;
178 >        BINQ    *bp;
179 >        int     i;
180 >
181 >        if (accumulate <= 0)            /* just accumulating? */
182 >                return(0);
183 >                                        /* else output ready results */
184          while (out_bq != NULL && (out_bq->ndx == lastdone+1) & !out_bq->n2add) {
185 <                b_cur = out_bq;                 /* pop off first entry */
186 <                out_bq = b_cur->next;
187 <                b_cur->next = NULL;
185 >                bp = out_bq;                    /* pop off first entry */
186 >                out_bq = bp->next;
187 >                bp->next = NULL;
188                  for (i = 0; i < nmods; i++)     /* output record */
189 <                        mod_output(b_cur->mca[i]);
189 >                        mod_output(bp->mca[i]);
190                  end_record();
191 <                free_binq(b_cur);               /* free this entry */
191 >                free_binq(bp);                  /* free this entry */
192                  lastdone += accumulate;
193                  ++nout;
194          }
# Line 184 | Line 196 | queue_output(BINQ *bp)
196   }
197  
198  
199 < /* Put a zero record in results queue */
199 > /* Put a zero record in results queue & output */
200   void
201 < zero_record(int ndx)
201 > put_zero_record(int ndx)
202   {
203          BINQ    *bp = new_binq();
204          int     i;
# Line 195 | Line 207 | zero_record(int ndx)
207                  memset(bp->mca[i]->cbin, 0, sizeof(DCOLOR)*bp->mca[i]->nbins);
208          bp->ndx = ndx;
209          queue_output(bp);
210 +        output_catchup();
211   }
212  
213  
# Line 221 | Line 234 | in_rchild()
234                  int     p0[2], p1[2];
235                  int     pid;
236                                          /* prepare i/o pipes */
237 +                errno = 0;
238                  if (pipe(p0) < 0 || pipe(p1) < 0)
239                          error(SYSTEM, "pipe() call failed!");
240                  pid = fork();           /* fork parent process */
# Line 241 | Line 255 | in_rchild()
255                  }
256                  if (pid < 0)
257                          error(SYSTEM, "fork() call failed!");
258 <                                        /* connect our pipes */
258 >                                        /* connect parent's pipes */
259                  close(p0[0]); close(p1[1]);
260                  kida[nchild].r = p1[0];
261                  kida[nchild].w = p0[1];
262                  kida[nchild].pid = pid;
263                  kida[nchild].running = -1;
264 +                inq_fp[nchild] = fdopen(p1[0], "rb");
265 +                if (inq_fp[nchild] == NULL)
266 +                        error(SYSTEM, "out of memory in in_rchild()");
267 + #ifdef getc_unlocked
268 +                flockfile(inq_fp[nchild]);      /* avoid mutex overhead */
269 + #endif
270                  ++nchild;
271          }
272          return(0);                      /* parent return value */
# Line 260 | Line 280 | end_children()
280   {
281          int     status;
282          
283 <        while (nchild-- > 0)
283 >        while (nchild-- > 0) {
284 >                kida[nchild].r = -1;    /* close(-1) error is ignored */
285                  if ((status = close_process(&kida[nchild])) > 0) {
286                          sprintf(errmsg,
287                                  "rendering process returned bad status (%d)",
288                                          status);
289                          error(WARNING, errmsg);
290                  }
291 +                fclose(inq_fp[nchild]); /* performs actual close() */
292 +        }
293   }
294  
295  
296 < /* Wait for the next available child */
296 > /* Wait for the next available child, managing output queue as well */
297   static int
298   next_child_nq(int force_wait)
299   {
300 <        fd_set  readset, errset;
301 <        int     i, j, n, nr;
300 >        static struct timeval   polling;
301 >        struct timeval          *pmode = force_wait | (accumulate <= 0) ?
302 >                                        (struct timeval *)NULL : &polling;
303 >        fd_set                  readset, errset;
304 >        int                     i, j, n, nr;
305  
306          if (!force_wait)                /* see if there's one free */
307                  for (i = nchild; i--; )
# Line 293 | Line 319 | next_child_nq(int force_wait)
319                  if (kida[i].r >= n)
320                          n = kida[i].r + 1;
321          }
322 <        if (!nr)                        /* nothing going on */
322 > tryagain:
323 >        if (pmode == NULL)              /* catch up in case we block */
324 >                output_catchup();
325 >        if (!nr)                        /* nothing to wait for? */
326                  return(-1);
327 <        if (nr > 1) {                   /* call select if multiple busy */
327 >        if ((nr > 1) | (pmode == &polling)) {
328                  errno = 0;
329 <                if (select(n, &readset, NULL, &errset, NULL) < 0)
330 <                        error(SYSTEM, "select call error in next_child_nq()");
329 >                i = select(n, &readset, NULL, &errset, pmode);
330 >                if (!i) {
331 >                        pmode = NULL;   /* try again, blocking this time */
332 >                        goto tryagain;
333 >                }
334 >                if (i < 0)
335 >                        error(SYSTEM, "select() error in next_child_nq()");
336          } else
337                  FD_ZERO(&errset);
338          n = -1;                         /* read results from child(ren) */
# Line 312 | Line 346 | next_child_nq(int force_wait)
346                  bq->ndx = kida[i].running;
347                                          /* read from child */
348                  for (j = 0; j < nmods; j++) {
349 <                        n = sizeof(DCOLOR)*bq->mca[j]->nbins;
350 <                        nr = readbuf(kida[i].r, (char *)bq->mca[j]->cbin, n);
351 <                        if (nr != n)
349 >                        nr = bq->mca[j]->nbins;
350 >                        if (fread(bq->mca[j]->cbin, sizeof(DCOLOR), nr,
351 >                                                        inq_fp[i]) != nr)
352                                  error(SYSTEM, "read error from render process");
353                  }
354 <                queue_output(bq);       /* put results in output queue */
354 >                queue_output(bq);       /* add results to output queue */
355                  kida[i].running = -1;   /* mark child as available */
356                  n = i;
357          }
358 <        return(n);                      /* last available child */
358 >        return(n);                      /* first available child */
359   }
360  
361  
# Line 332 | Line 366 | parental_loop()
366          static int      ignore_warning_given = 0;
367          FVECT           orgdir[2];
368          double          d;
369 +        int             i;
370                                          /* load rays from stdin & process */
371   #ifdef getc_unlocked
372          flockfile(stdin);               /* avoid lock/unlock overhead */
# Line 347 | Line 382 | parental_loop()
382                  }
383                  if ((d == 0.0) | (lastray+1 < lastray)) {
384                          while (next_child_nq(1) >= 0)
385 <                                ;
385 >                                ;                       /* clear the queue */
386                          lastdone = lastray = 0;
387                  }
388                  if (d == 0.0) {
389                          if ((yres <= 0) | (xres <= 0))
390                                  waitflush = 1;          /* flush right after */
391 <                        zero_record(++lastray);
392 <                } else {                                /* else assign */
393 <                        int     avail = next_child_nq(0);
394 <                        if (writebuf(kida[avail].w, (char *)orgdir,
395 <                                        sizeof(FVECT)*2) != sizeof(FVECT)*2)
391 >                        put_zero_record(++lastray);
392 >                } else {                                /* else assign ray */
393 >                        i = next_child_nq(0);
394 >                        if (writebuf(kida[i].w, (char *)orgdir,
395 >                                        sizeof(orgdir)) != sizeof(orgdir))
396                                  error(SYSTEM, "pipe write error");
397 <                        kida[avail].running = ++lastray;
397 >                        kida[i].running = ++lastray;
398                  }
399                  if (raysleft && !--raysleft)
400                          break;                          /* preemptive EOI */
# Line 368 | Line 403 | parental_loop()
403                  ;
404                                                  /* output accumulated record */
405          if (accumulate <= 0 || account < accumulate) {
371                int     i;
406                  if (account < accumulate) {
407                          error(WARNING, "partial accumulation in final record");
408                          accumulate -= account;
# Line 376 | Line 410 | parental_loop()
410                  for (i = 0; i < nmods; i++)
411                          mod_output(out_bq->mca[i]);
412                  end_record();
413 +                free_binq(out_bq);
414 +                out_bq = NULL;
415          }
416          if (raysleft)
417                  error(USER, "unexpected EOF on input");

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines