--- ray/src/rt/raypcalls.c 2005/12/17 22:17:51 2.12 +++ ray/src/rt/raypcalls.c 2007/09/18 19:10:02 2.17 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: raypcalls.c,v 2.12 2005/12/17 22:17:51 greg Exp $"; +static const char RCSid[] = "$Id: raypcalls.c,v 2.17 2007/09/18 19:10:02 greg Exp $"; #endif /* * raypcalls.c - interface for parallel rendering using Radiance @@ -23,14 +23,17 @@ static const char RCSid[] = "$Id: raypcalls.c,v 2.12 2 * The first step is opening one or more rendering processes * with a call to ray_pinit(oct, nproc). Before calling fork(), * ray_pinit() loads the octree and data structures into the - * caller's memory. This permits all sorts of queries that - * wouldn't be possible otherwise, without causing any real + * caller's memory, and ray_popen() synchronizes the ambient + * file, if any. Shared memory permits all sorts of queries + * that wouldn't be possible otherwise, without causing any real * memory overhead, since all the static data are shared * between processes. Rays are then traced using a simple * queuing mechanism, explained below. * - * The ray queue holds as many rays as there are rendering - * processes. Rays are queued and returned by a single + * 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 * and the queue is not yet full. A return value of 1 @@ -105,7 +108,7 @@ static const char RCSid[] = "$Id: raypcalls.c,v 2.12 2 * Note: These routines are written to coordinate with the * definitions in raycalls.c, and in fact depend on them. * If you want to trace a ray and get a result synchronously, - * use the ray_trace() call to compute it in the parent process + * use the ray_trace() call to compute it in the parent process. * This will not interfere with any subprocess calculations, * but beware that a fatal error may end with a call to quit(). * @@ -138,7 +141,7 @@ static const char RCSid[] = "$Id: raypcalls.c,v 2.12 2 #include "selcall.h" #ifndef RAYQLEN -#define RAYQLEN 16 /* # rays to send at once */ +#define RAYQLEN 12 /* # rays to send at once */ #endif #ifndef MAX_RPROCS @@ -170,7 +173,7 @@ static int r_recv_next; /* next receive ray placement #define sendq_full() (r_send_next >= RAYQLEN) static int ray_pflush(void); -static void ray_pchild(int fd_in, int fd_out); +static void ray_pchild(int fd_in, int fd_out); extern void @@ -243,8 +246,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; } @@ -263,19 +265,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 */ } - /* add ray to send queue */ - r_queue[r_send_next] = *r; - r_send_next++; + /* else add ray to send queue */ + 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); } @@ -295,8 +294,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? */ @@ -310,6 +311,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) || @@ -370,8 +374,7 @@ getready: /* any children waiting for us? */ rp->slights = NULL; } /* return first ray received */ - *r = r_queue[r_recv_first]; - r_recv_first++; + *r = r_queue[r_recv_first++]; return(1); } @@ -399,6 +402,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; @@ -447,8 +452,8 @@ ray_popen( /* open the specified # processes */ nadd = MAX_NPROCS - ray_pnprocs; if (nadd <= 0) return; - fflush(stderr); /* clear pending output */ - fflush(stdout); + ambsync(); /* load any new ambient values */ + fflush(NULL); /* clear pending output */ while (nadd--) { /* fork each new process */ int p0[2], p1[2]; if (pipe(p0) < 0 || pipe(p1) < 0) @@ -522,5 +527,7 @@ void quit(ec) /* make sure exit is called */ int ec; { + if (ray_pnprocs > 0) /* close children if any */ + ray_pclose(0); exit(ec); }