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.5 by greg, Tue Jun 12 01:06:59 2012 UTC vs.
Revision 2.9 by greg, Thu Jun 14 05:13:25 2012 UTC

# Line 13 | Line 13 | static const char RCSid[] = "$Id$";
13  
14   /* Modifier contribution queue (results waiting to be output) */
15   typedef struct s_binq {
16 <        int             ndx;            /* index for this entry */
17 <        int             nadded;         /* accumulated so far */
16 >        RNUMBER         ndx;            /* index for this entry */
17 >        RNUMBER         nadded;         /* accumulated so far */
18          struct s_binq   *next;          /* next in queue */
19          MODCONT         *mca[1];        /* contrib. array (extends struct) */
20   } BINQ;
# Line 22 | Line 22 | typedef struct s_binq {
22   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 */
25 > static struct {
26 >        RNUMBER r1;                     /* assigned ray starting index */
27 >        SUBPROC pr;                     /* PID, i/o descriptors */
28 >        FILE    *infp;                  /* file pointer to read from process */
29 >        int     nr;                     /* number rays to sum (0 if free) */
30 > } kida[MAXPROCESS];             /* our child processes */
31  
32  
33   /* Get new bin queue entry */
# Line 37 | Line 41 | new_binq()
41                  bp = free_bq;
42                  free_bq = bp->next;
43                  bp->next = NULL;
44 <                bp->nadded = 1;
44 >                bp->nadded = 0;
45                  return(bp);
46          }
47                                          /* else allocate fresh */
# Line 54 | Line 58 | new_binq()
58                  /* memset(bp->mca[i]->cbin, 0, sizeof(DCOLOR)*mp->nbins); */
59          }
60          bp->ndx = 0;
61 <        bp->nadded = 1;
61 >        bp->nadded = 0;
62          bp->next = NULL;
63          return(bp);
64   memerr:
# Line 231 | Line 235 | put_zero_record(int ndx)
235          for (i = nmods; i--; )
236                  memset(bp->mca[i]->cbin, 0, sizeof(DCOLOR)*bp->mca[i]->nbins);
237          bp->ndx = ndx;
238 +        bp->nadded = 1;
239          queue_output(bp);
240          output_catchup(0);
241   }
242  
243  
244 + /* Get results from child process and add to queue */
245 + static void
246 + queue_results(int k)
247 + {
248 +        BINQ    *bq = new_binq();       /* get results holder */
249 +        int     j;
250 +
251 +        bq->ndx = kida[k].r1;
252 +        bq->nadded = kida[k].nr;
253 +                                        /* read from child */
254 +        for (j = 0; j < nmods; j++)
255 +                if (fread(bq->mca[j]->cbin, sizeof(DCOLOR), bq->mca[j]->nbins,
256 +                                        kida[k].infp) != bq->mca[j]->nbins)
257 +                        error(SYSTEM, "read error from render process");
258 +                        
259 +        queue_output(bq);               /* put results in output queue */
260 +        kida[k].nr = 0;                 /* mark child as available */
261 + }
262 +
263 +
264   /* callback to set output spec to NULL (stdout) */
265   static int
266   set_stdout(const LUENT *le, void *p)
# Line 249 | Line 274 | set_stdout(const LUENT *le, void *p)
274   int
275   in_rchild()
276   {
277 < #ifdef _WIN32
278 <        error(WARNING, "multiprocessing unsupported -- running solo");
279 <        nproc = 1;
255 <        return(1);
256 < #else
257 <                                        /* try to fork ourselves */
258 <        while (nchild < nproc) {
259 <                int     p0[2], p1[2];
260 <                int     pid;
261 <                                        /* prepare i/o pipes */
277 >        int     rval;
278 >
279 >        while (nchild < nproc) {        /* fork until target reached */
280                  errno = 0;
281 <                if (pipe(p0) < 0 || pipe(p1) < 0)
282 <                        error(SYSTEM, "pipe() call failed!");
283 <                pid = fork();           /* fork parent process */
284 <                if (pid == 0) {         /* if in child, set up & return true */
267 <                        close(p0[1]); close(p1[0]);
281 >                rval = open_process(&kida[nchild].pr, NULL);
282 >                if (rval < 0)
283 >                        error(SYSTEM, "open_process() call failed");
284 >                if (rval == 0) {        /* if in child, set up & return true */
285                          lu_doall(&modconttab, set_stdout, NULL);
286                          lu_done(&ofiletab);
287                          while (nchild--) {      /* don't share other pipes */
288 <                                close(kida[nchild].w);
289 <                                fclose(inq_fp[nchild]);
288 >                                close(kida[nchild].pr.w);
289 >                                fclose(kida[nchild].infp);
290                          }
274                        dup2(p0[0], 0); close(p0[0]);
275                        dup2(p1[1], 1); close(p1[1]);
291                          inpfmt = (sizeof(RREAL)==sizeof(double)) ? 'd' : 'f';
292                          outfmt = 'd';
293                          header = 0;
279                        waitflush = xres = 1;
294                          yres = 0;
295                          raysleft = 0;
296 <                        account = accumulate = 1;
297 <                        return(1);      /* child return value */
296 >                        if (accumulate == 1) {
297 >                                waitflush = xres = 1;
298 >                                account = accumulate = 1;
299 >                        } else {        /* parent controls accumulation */
300 >                                waitflush = xres = 0;
301 >                                account = accumulate = 0;
302 >                        }
303 >                        return(1);      /* return "true" in child */
304                  }
305 <                if (pid < 0)
306 <                        error(SYSTEM, "fork() call failed!");
307 <                                        /* connect parent's pipes */
308 <                close(p0[0]); close(p1[1]);
309 <                kida[nchild].r = p1[0];
290 <                kida[nchild].w = p0[1];
291 <                kida[nchild].pid = pid;
292 <                kida[nchild].running = -1;
293 <                inq_fp[nchild] = fdopen(p1[0], "rb");
294 <                if (inq_fp[nchild] == NULL)
305 >                if (rval != PIPE_BUF)
306 >                        error(CONSISTENCY, "bad value from open_process()");
307 >                                        /* connect to child's output */
308 >                kida[nchild].infp = fdopen(kida[nchild].pr.r, "rb");
309 >                if (kida[nchild].infp == NULL)
310                          error(SYSTEM, "out of memory in in_rchild()");
311   #ifdef getc_unlocked
312 <                flockfile(inq_fp[nchild]);      /* avoid mutex overhead */
312 >                flockfile(kida[nchild].infp);   /* avoid mutex overhead */
313   #endif
314 <                ++nchild;
314 >                kida[nchild++].nr = 0;  /* mark as available */
315          }
316 <        return(0);                      /* parent return value */
302 < #endif
316 >        return(0);                      /* return "false" in parent */
317   }
318  
319  
# Line 311 | Line 325 | end_children()
325          
326          while (nchild > 0) {
327                  nchild--;
328 <                kida[nchild].r = -1;    /* close(-1) error is ignored */
315 <                if ((status = close_process(&kida[nchild])) > 0) {
328 >                if ((status = close_process(&kida[nchild].pr)) > 0) {
329                          sprintf(errmsg,
330                                  "rendering process returned bad status (%d)",
331                                          status);
332                          error(WARNING, errmsg);
333                  }
334 <                fclose(inq_fp[nchild]); /* performs actual close() */
334 >                fclose(kida[nchild].infp);
335          }
336   }
337  
# Line 330 | Line 343 | next_child_nq(int flushing)
343          static struct timeval   polling;
344          struct timeval          *pmode;
345          fd_set                  readset, errset;
346 <        int                     i, j, n, nr, nqr;
346 >        int                     i, n, nr, nqr;
347  
348          if (!flushing)                  /* see if there's one free */
349                  for (i = nchild; i--; )
350 <                        if (kida[i].running < 0)
350 >                        if (!kida[i].nr)
351                                  return(i);
352  
353          nqr = queue_ready();            /* choose blocking mode or polling */
# Line 352 | Line 365 | tryagain:                              /* catch up with output? */
365          FD_ZERO(&readset); FD_ZERO(&errset);
366          n = nr = 0;
367          for (i = nchild; i--; ) {
368 <                if (kida[i].running > 0) {
369 <                        FD_SET(kida[i].r, &readset);
368 >                if (kida[i].nr) {
369 >                        FD_SET(kida[i].pr.r, &readset);
370                          ++nr;
371                  }
372 <                FD_SET(kida[i].r, &errset);
373 <                if (kida[i].r >= n)
374 <                        n = kida[i].r + 1;
372 >                FD_SET(kida[i].pr.r, &errset);
373 >                if (kida[i].pr.r >= n)
374 >                        n = kida[i].pr.r + 1;
375          }
376          if (!nr)                        /* nothing to wait for? */
377                  return(-1);
# Line 375 | Line 388 | tryagain:                              /* catch up with output? */
388                  FD_ZERO(&errset);
389          n = -1;                         /* read results from child(ren) */
390          for (i = nchild; i--; ) {
391 <                BINQ    *bq;
379 <                if (FD_ISSET(kida[i].r, &errset))
391 >                if (FD_ISSET(kida[i].pr.r, &errset))
392                          error(USER, "rendering process died");
393 <                if (!FD_ISSET(kida[i].r, &readset))
394 <                        continue;
383 <                bq = new_binq();        /* get results holder */
384 <                bq->ndx = kida[i].running;
385 <                                        /* read from child */
386 <                for (j = 0; j < nmods; j++) {
387 <                        nr = bq->mca[j]->nbins;
388 <                        if (fread(bq->mca[j]->cbin, sizeof(DCOLOR), nr,
389 <                                                        inq_fp[i]) != nr)
390 <                                error(SYSTEM, "read error from render process");
391 <                }
392 <                queue_output(bq);       /* add results to output queue */
393 <                kida[i].running = -1;   /* mark child as available */
394 <                n = i;
393 >                if (FD_ISSET(kida[i].pr.r, &readset))
394 >                        queue_results(n = i);
395          }
396          return(n);                      /* first available child */
397   }
# Line 401 | Line 401 | tryagain:                              /* catch up with output? */
401   void
402   parental_loop()
403   {
404 + #define MAXIQ           (int)(PIPE_BUF/(sizeof(FVECT)*2))
405          static int      ignore_warning_given = 0;
406 <        FVECT           orgdir[2];
407 <        double          d;
408 <        int             i;
406 >        int             qlimit = (accumulate == 1) ? 1 : MAXIQ-1;
407 >        int             ninq = 0;
408 >        FVECT           orgdir[2*MAXIQ];
409 >        int             i, n;
410                                          /* load rays from stdin & process */
411   #ifdef getc_unlocked
412          flockfile(stdin);               /* avoid lock/unlock overhead */
413   #endif
414 <        while (getvec(orgdir[0]) == 0 && getvec(orgdir[1]) == 0) {
415 <                d = normalize(orgdir[1]);
416 <                                                        /* asking for flush? */
417 <                if ((d == 0.0) & (accumulate != 1)) {
418 <                        if (!ignore_warning_given++)
419 <                                error(WARNING,
414 >        while (getvec(orgdir[2*ninq]) == 0 && getvec(orgdir[2*ninq+1]) == 0) {
415 >                if (orgdir[2*ninq+1][0] == 0.0 &&       /* asking for flush? */
416 >                                (orgdir[2*ninq+1][1] == 0.0) &
417 >                                (orgdir[2*ninq+1][2] == 0.0)) {
418 >                        if (accumulate != 1) {
419 >                                if (!ignore_warning_given++)
420 >                                        error(WARNING,
421                                  "dummy ray(s) ignored during accumulation\n");
422 <                        continue;
423 <                }
421 <                if ((d == 0.0) | (lastray+1 < lastray)) {
422 >                                continue;
423 >                        }
424                          while (next_child_nq(1) >= 0)
425                                  ;                       /* clear the queue */
426                          lastdone = lastray = 0;
425                }
426                if (d == 0.0) {
427                          if ((yres <= 0) | (xres <= 0))
428                                  waitflush = 1;          /* flush next */
429                          put_zero_record(++lastray);
430 <                } else {                                /* else assign ray */
430 >                } else if (++ninq >= qlimit || accumulate > 1 &&
431 >                            lastray/accumulate != (lastray+ninq)/accumulate) {
432                          i = next_child_nq(0);           /* manages output */
433 <                        if (writebuf(kida[i].w, (char *)orgdir,
434 <                                        sizeof(orgdir)) != sizeof(orgdir))
433 >                        n = ninq;
434 >                        if (accumulate != 1)            /* request flush? */
435 >                                memset(orgdir[2*n++], 0, sizeof(FVECT)*2);
436 >                        n *= sizeof(FVECT)*2;           /* send assignment */
437 >                        if (writebuf(kida[i].pr.w, (char *)orgdir, n) != n)
438                                  error(SYSTEM, "pipe write error");
439 <                        kida[i].running = ++lastray;    /* busy now */
439 >                        kida[i].r1 = lastray+1;
440 >                        lastray += kida[i].nr = ninq;   /* mark as busy */
441 >                        ninq = 0;
442 >                        if (lastray < lastdone) {       /* RNUMBER wrapped? */
443 >                                while (next_child_nq(1) >= 0)
444 >                                        ;
445 >                                lastdone = lastray = 0;
446 >                        }
447                  }
448                  if (raysleft && !--raysleft)
449                          break;                          /* preemptive EOI */
# Line 456 | Line 467 | parental_loop()
467                  error(USER, "unexpected EOF on input");
468          free_binq(NULL);                        /* clean up */
469          lu_done(&ofiletab);
470 + #undef MAXIQ
471   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines