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.9 by greg, Thu Jun 14 05:13:25 2012 UTC vs.
Revision 2.17 by greg, Thu Nov 15 15:26:52 2012 UTC

# Line 6 | Line 6 | static const char RCSid[] = "$Id$";
6   * Controlling process for multiple children
7   */
8  
9 + #include <signal.h>
10   #include "rcontrib.h"
10 #include "platform.h"
11 #include "rtprocess.h"
11   #include "selcall.h"
12  
13 + #define MAXIQ           (int)(PIPE_BUF/(sizeof(FVECT)*2))
14 +
15   /* Modifier contribution queue (results waiting to be output) */
16   typedef struct s_binq {
17          RNUMBER         ndx;            /* index for this entry */
# Line 26 | Line 27 | static struct {
27          RNUMBER r1;                     /* assigned ray starting index */
28          SUBPROC pr;                     /* PID, i/o descriptors */
29          FILE    *infp;                  /* file pointer to read from process */
30 <        int     nr;                     /* number rays to sum (0 if free) */
30 >        int     nr;                     /* number of rays to sum (0 if free) */
31   } kida[MAXPROCESS];             /* our child processes */
32  
33  
# Line 94 | Line 95 | free_binq(BINQ *bp)
95  
96  
97   /* Add modifier values to accumulation record in queue and clear */
98 < void
98 > static void
99   queue_modifiers()
100   {
101          MODCONT *mpin, *mpout;
# Line 146 | Line 147 | queue_output(BINQ *bp)
147                  }
148                  return;
149          }
150 <        b_last = NULL;                  /* else insert in output queue */
150 >        b_last = NULL;                  /* insert in output queue */
151          for (b_cur = out_bq; b_cur != NULL && b_cur->ndx < bp->ndx;
152                                  b_cur = b_cur->next)
153                  b_last = b_cur;
# Line 184 | Line 185 | queue_ready()
185          int     nready = 0;
186          BINQ    *bp;
187  
187        if (accumulate <= 0)            /* just accumulating? */
188                return(0);
189
188          for (bp = out_bq; bp != NULL && bp->nadded >= accumulate &&
189                                  bp->ndx == lastdone+nready*accumulate+1;
190                                  bp = bp->next)
# Line 203 | Line 201 | output_catchup(int nmax)
201          int     nout = 0;
202          BINQ    *bp;
203          int     i;
204 <
207 <        if (accumulate <= 0)            /* just accumulating? */
208 <                return(0);
209 <                                        /* else output ready results */
204 >                                        /* output ready results */
205          while (out_bq != NULL && out_bq->nadded >= accumulate
206                                  && out_bq->ndx == lastdone+1) {
207                  if ((nmax > 0) & (nout >= nmax))
# Line 319 | Line 314 | in_rchild()
314  
315   /* Close child processes */
316   void
317 < end_children()
317 > end_children(int immed)
318   {
319          int     status;
320          
321          while (nchild > 0) {
322                  nchild--;
323 <                if ((status = close_process(&kida[nchild].pr)) > 0) {
323 > #ifdef SIGKILL
324 >                if (immed)              /* error mode -- quick exit */
325 >                        kill(kida[nchild].pr.pid, SIGKILL);
326 > #endif
327 >                if ((status = close_process(&kida[nchild].pr)) > 0 && !immed) {
328                          sprintf(errmsg,
329                                  "rendering process returned bad status (%d)",
330                                          status);
# Line 401 | Line 400 | tryagain:                              /* catch up with output? */
400   void
401   parental_loop()
402   {
403 < #define MAXIQ           (int)(PIPE_BUF/(sizeof(FVECT)*2))
405 <        static int      ignore_warning_given = 0;
406 <        int             qlimit = (accumulate == 1) ? 1 : MAXIQ-1;
403 >        const int       qlimit = (accumulate == 1) ? 1 : MAXIQ-1;
404          int             ninq = 0;
405          FVECT           orgdir[2*MAXIQ];
406          int             i, n;
# Line 415 | Line 412 | parental_loop()
412                  if (orgdir[2*ninq+1][0] == 0.0 &&       /* asking for flush? */
413                                  (orgdir[2*ninq+1][1] == 0.0) &
414                                  (orgdir[2*ninq+1][2] == 0.0)) {
415 <                        if (accumulate != 1) {
416 <                                if (!ignore_warning_given++)
417 <                                        error(WARNING,
418 <                                "dummy ray(s) ignored during accumulation\n");
419 <                                continue;
415 >                        if (ninq) {                     /* preempt our queue */
416 >                                i = next_child_nq(0);
417 >                                n = ninq;
418 >                                memset(orgdir[2*n++], 0, sizeof(FVECT)*2);
419 >                                n *= sizeof(FVECT)*2;
420 >                                if (writebuf(kida[i].pr.w, (char *)orgdir, n) != n)
421 >                                        error(SYSTEM, "pipe write error");
422 >                                kida[i].r1 = lastray+1;
423 >                                lastray += kida[i].nr = ninq;
424 >                                ninq = 0;
425                          }
426 <                        while (next_child_nq(1) >= 0)
427 <                                ;                       /* clear the queue */
428 <                        lastdone = lastray = 0;
429 <                        if ((yres <= 0) | (xres <= 0))
426 >                        if ((yres <= 0) | (xres <= 0) &&
427 >                                        (lastray+1) % accumulate == 0) {
428 >                                while (next_child_nq(1) >= 0)
429 >                                        ;               /* clear the queue */
430 >                                lastdone = lastray %= accumulate;
431                                  waitflush = 1;          /* flush next */
432 +                        }
433                          put_zero_record(++lastray);
434 <                } else if (++ninq >= qlimit || accumulate > 1 &&
434 >                } else if (++ninq >= qlimit ||
435                              lastray/accumulate != (lastray+ninq)/accumulate) {
436                          i = next_child_nq(0);           /* manages output */
437                          n = ninq;
# Line 438 | Line 442 | parental_loop()
442                                  error(SYSTEM, "pipe write error");
443                          kida[i].r1 = lastray+1;
444                          lastray += kida[i].nr = ninq;   /* mark as busy */
441                        ninq = 0;
445                          if (lastray < lastdone) {       /* RNUMBER wrapped? */
446                                  while (next_child_nq(1) >= 0)
447                                          ;
448 <                                lastdone = lastray = 0;
448 >                                lastray -= ninq;
449 >                                lastdone = lastray %= accumulate;
450                          }
451 +                        ninq = 0;
452                  }
453                  if (raysleft && !--raysleft)
454                          break;                          /* preemptive EOI */
455          }
456          while (next_child_nq(1) >= 0)           /* empty results queue */
457                  ;
458 <                                                /* output accumulated record */
459 <        if (accumulate <= 0 || account < accumulate) {
460 <                end_children();                 /* frees up file descriptors */
456 <                if (account < accumulate) {
457 <                        error(WARNING, "partial accumulation in final record");
458 <                        accumulate -= account;
459 <                }
460 <                for (i = 0; i < nmods; i++)
461 <                        mod_output(out_bq->mca[i]);
462 <                end_record();
463 <                free_binq(out_bq);
458 >        if (account < accumulate) {
459 >                error(WARNING, "partial accumulation in final record");
460 >                free_binq(out_bq);              /* XXX just ignore it */
461                  out_bq = NULL;
462          }
463 +        free_binq(NULL);                        /* clean up */
464 +        lu_done(&ofiletab);
465          if (raysleft)
466                  error(USER, "unexpected EOF on input");
467 <        free_binq(NULL);                        /* clean up */
467 > }
468 >
469 >
470 > /* Wait for the next available child by monitoring "to" pipes */
471 > static int
472 > next_child_ready()
473 > {
474 >        fd_set                  writeset, errset;
475 >        int                     i, n;
476 >
477 >        for (i = nchild; i--; )         /* see if there's one free first */
478 >                if (!kida[i].nr)
479 >                        return(i);
480 >                                        /* prepare select() call */
481 >        FD_ZERO(&writeset); FD_ZERO(&errset);
482 >        n = 0;
483 >        for (i = nchild; i--; ) {
484 >                FD_SET(kida[i].pr.w, &writeset);
485 >                FD_SET(kida[i].pr.r, &errset);
486 >                if (kida[i].pr.w >= n)
487 >                        n = kida[i].pr.w + 1;
488 >                if (kida[i].pr.r >= n)
489 >                        n = kida[i].pr.r + 1;
490 >        }
491 >        errno = 0;
492 >        n = select(n, NULL, &writeset, &errset, NULL);
493 >        if (n < 0)
494 >                error(SYSTEM, "select() error in next_child_ready()");
495 >        n = -1;                         /* identify waiting child */
496 >        for (i = nchild; i--; ) {
497 >                if (FD_ISSET(kida[i].pr.r, &errset))
498 >                        error(USER, "rendering process died");
499 >                if (FD_ISSET(kida[i].pr.w, &writeset))
500 >                        kida[n = i].nr = 0;
501 >        }
502 >        return(n);                      /* first available child */
503 > }
504 >
505 >
506 > /* Modified parental loop for full accumulation mode (-c 0) */
507 > void
508 > feeder_loop()
509 > {
510 >        static int      ignore_warning_given = 0;
511 >        int             ninq = 0;
512 >        FVECT           orgdir[2*MAXIQ];
513 >        int             i, n;
514 >                                        /* load rays from stdin & process */
515 > #ifdef getc_unlocked
516 >        flockfile(stdin);               /* avoid lock/unlock overhead */
517 > #endif
518 >        while (getvec(orgdir[2*ninq]) == 0 && getvec(orgdir[2*ninq+1]) == 0) {
519 >                if (orgdir[2*ninq+1][0] == 0.0 &&       /* asking for flush? */
520 >                                (orgdir[2*ninq+1][1] == 0.0) &
521 >                                (orgdir[2*ninq+1][2] == 0.0)) {
522 >                        if (!ignore_warning_given++)
523 >                                error(WARNING,
524 >                                "dummy ray(s) ignored during accumulation\n");
525 >                        continue;
526 >                }
527 >                if (++ninq >= MAXIQ) {
528 >                        i = next_child_ready();         /* get eager child */
529 >                        n = sizeof(FVECT)*2 * ninq;     /* give assignment */
530 >                        if (writebuf(kida[i].pr.w, (char *)orgdir, n) != n)
531 >                                error(SYSTEM, "pipe write error");
532 >                        kida[i].r1 = lastray+1;
533 >                        lastray += kida[i].nr = ninq;
534 >                        ninq = 0;
535 >                        if (lastray < lastdone)         /* RNUMBER wrapped? */
536 >                                lastdone = lastray = 0;
537 >                }
538 >                if (raysleft && !--raysleft)
539 >                        break;                          /* preemptive EOI */
540 >        }
541 >        if (ninq) {                             /* polish off input */
542 >                i = next_child_ready();
543 >                n = sizeof(FVECT)*2 * ninq;
544 >                if (writebuf(kida[i].pr.w, (char *)orgdir, n) != n)
545 >                        error(SYSTEM, "pipe write error");
546 >                kida[i].r1 = lastray+1;
547 >                lastray += kida[i].nr = ninq;
548 >                ninq = 0;
549 >        }
550 >        memset(orgdir, 0, sizeof(FVECT)*2);     /* get results */
551 >        for (i = nchild; i--; ) {
552 >                writebuf(kida[i].pr.w, (char *)orgdir, sizeof(FVECT)*2);
553 >                queue_results(i);
554 >        }
555 >        if (recover)                            /* and from before? */
556 >                queue_modifiers();
557 >        end_children(0);                        /* free up file descriptors */
558 >        for (i = 0; i < nmods; i++)
559 >                mod_output(out_bq->mca[i]);     /* output accumulated record */
560 >        end_record();
561 >        free_binq(out_bq);                      /* clean up */
562 >        out_bq = NULL;
563 >        free_binq(NULL);
564          lu_done(&ofiletab);
565 < #undef MAXIQ
565 >        if (raysleft)
566 >                error(USER, "unexpected EOF on input");
567   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines