--- ray/src/rt/raypcalls.c 2005/12/20 20:36:44 2.13 +++ ray/src/rt/raypcalls.c 2008/02/08 18:27:31 2.18 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: raypcalls.c,v 2.13 2005/12/20 20:36:44 greg Exp $"; +static const char RCSid[] = "$Id: raypcalls.c,v 2.18 2008/02/08 18:27:31 greg Exp $"; #endif /* * raypcalls.c - interface for parallel rendering using Radiance @@ -30,8 +30,9 @@ static const char RCSid[] = "$Id: raypcalls.c,v 2.13 2 * between processes. Rays are then traced using a simple * queuing mechanism, explained below. * - * The ray queue holds at least RAYQLEN rays, up to - * as many rays as there are rendering processes. + * The ray queue buffers RAYQLEN rays before sending to + * children, each of which may internally buffer RAYQLEN rays. + * * Rays are queued and returned by a single * ray_pqueue() call. A ray_pqueue() return * value of 0 indicates that no rays are ready @@ -130,13 +131,11 @@ static const char RCSid[] = "$Id: raypcalls.c,v 2.13 2 * process should not be compromised. */ -#include -#include -#include /* XXX platform */ - #include "rtprocess.h" #include "ray.h" #include "ambient.h" +#include +#include #include "selcall.h" #ifndef RAYQLEN @@ -245,8 +244,7 @@ ray_psend( /* add a ray to our send queue */ if (sendq_full() && ray_pflush() <= 0) error(INTERNAL, "ray_pflush failed in ray_psend"); - r_queue[r_send_next] = *r; - r_send_next++; + r_queue[r_send_next++] = *r; } @@ -265,19 +263,16 @@ ray_pqueue( /* queue a ray for computation */ /* wait for a result */ rval = ray_presult(r, 0); /* put new ray in queue */ - r_queue[r_send_next] = mySend; - r_send_next++; + r_queue[r_send_next++] = mySend; return(rval); /* done */ } /* else add ray to send queue */ - r_queue[r_send_next] = *r; - r_send_next++; + r_queue[r_send_next++] = *r; /* check for returned ray... */ if (r_recv_first >= r_recv_next) return(0); /* ...one is sitting in queue */ - *r = r_queue[r_recv_first]; - r_recv_first++; + *r = r_queue[r_recv_first++]; return(1); } @@ -297,8 +292,10 @@ ray_presult( /* check for a completed ray */ return(0); /* check queued results first */ if (r_recv_first < r_recv_next) { - *r = r_queue[r_recv_first]; - r_recv_first++; + *r = r_queue[r_recv_first++]; + /* make sure send queue has room */ + if (sendq_full() && ray_pflush() <= 0) + return(-1); return(1); } n = ray_pnprocs - ray_pnidle; /* pending before flush? */ @@ -312,6 +309,9 @@ ray_presult( /* check for a completed ray */ n = ray_pnprocs - ray_pnidle; if (n <= 0) /* return if nothing to await */ return(0); + if (!poll && ray_pnprocs == 1) /* one process -> skip select() */ + FD_SET(r_proc[0].fd_recv, &readset); + getready: /* any children waiting for us? */ for (pn = ray_pnprocs; pn--; ) if (FD_ISSET(r_proc[pn].fd_recv, &readset) || @@ -400,6 +400,8 @@ ray_pchild( /* process rays (never returns) */ { int n; register int i; + /* flag child process for quit() */ + ray_pnprocs = -1; /* read each ray request set */ while ((n = read(fd_in, (char *)r_queue, sizeof(r_queue))) > 0) { int n2; @@ -523,5 +525,7 @@ void quit(ec) /* make sure exit is called */ int ec; { + if (ray_pnprocs > 0) /* close children if any */ + ray_pclose(0); exit(ec); }