--- ray/src/rt/raypcalls.c 2003/07/03 15:00:19 2.3 +++ ray/src/rt/raypcalls.c 2004/09/17 21:43:50 2.8 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: raypcalls.c,v 2.3 2003/07/03 15:00:19 greg Exp $"; +static const char RCSid[] = "$Id: raypcalls.c,v 2.8 2004/09/17 21:43:50 greg Exp $"; #endif /* * raypcalls.c - interface for parallel rendering using Radiance @@ -51,8 +51,8 @@ static const char RCSid[] = "$Id: raypcalls.c,v 2.3 20 * Note the differences between this and the simpler ray_trace() * call. In particular, the call may or may not return a value * in the passed ray structure. Also, you need to call rayorigin() - * yourself, which is normally for you by ray_trace(). The - * great thing is that ray_pqueue() will trace rays faster in + * yourself, which is normally called for you by ray_trace(). The + * benefit is that ray_pqueue() will trace rays faster in * proportion to the number of CPUs you have available on your * system. If the ray queue is full before the call, ray_pqueue() * will block until a result is ready so it can queue this one. @@ -81,8 +81,9 @@ static const char RCSid[] = "$Id: raypcalls.c,v 2.3 20 * ray_psend(&myRay); * } * - * The ray_presult() and/or ray_pqueue() functions may then be - * called to read back the results. + * Note that it is a fatal error to call ra_psend() when + * ray_pnidle is zero. The ray_presult() and/or ray_pqueue() + * functions may be called subsequently to read back the results. * * When you are done, you may call ray_pdone(1) to close * all child processes and clean up memory used by Radiance. @@ -99,19 +100,21 @@ static const char RCSid[] = "$Id: raypcalls.c,v 2.3 20 * If you just want to reap children so that you can alter the * rendering parameters without reloading the scene, use the * ray_pclose(0) and ray_popen(nproc) calls to close - * then restart the child processes. + * then restart the child processes after the changes are made. * * 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(). * * Note: One of the advantages of using separate processes * is that it gives the calling program some immunity from * fatal rendering errors. As discussed in raycalls.c, * Radiance tends to throw up its hands and exit at the * first sign of trouble, calling quit() to return control - * to the system. Although you can avoid exit() with + * to the top level. Although you can avoid exit() with * your own longjmp() in quit(), the cleanup afterwards * is always suspect. Through the use of subprocesses, * we avoid this pitfall by closing the processes and @@ -120,12 +123,18 @@ static const char RCSid[] = "$Id: raypcalls.c,v 2.3 20 * of these calls, you can assume that the processes have * been cleaned up with a call to ray_close(), though you * will have to call ray_pdone() yourself if you want to - * free memory. Obviously, you cannot continue rendering, - * but otherwise your process should not be compromised. + * free memory. Obviously, you cannot continue rendering + * without risking further errors, but otherwise your + * process should not be compromised. */ -#include "ray.h" +#include +#include +#include /* XXX platform */ +#include "rtprocess.h" +#include "ray.h" +#include "ambient.h" #include "selcall.h" #ifndef RAYQLEN @@ -160,11 +169,15 @@ 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); -void -ray_pinit(otnm, nproc) /* initialize ray-tracing processes */ -char *otnm; -int nproc; + +extern void +ray_pinit( /* initialize ray-tracing processes */ + char *otnm, + int nproc +) { if (nobjects > 0) /* close old calculation */ ray_pdone(0); @@ -185,11 +198,11 @@ int nproc; static int -ray_pflush() /* send queued rays to idle children */ +ray_pflush(void) /* send queued rays to idle children */ { int nc, n, nw, i, sfirst; - if ((ray_pnidle <= 0 | r_send_next <= 0)) + if ((ray_pnidle <= 0) | (r_send_next <= 0)) return(0); /* nothing we can send */ sfirst = 0; /* divvy up labor */ @@ -219,9 +232,10 @@ ray_pflush() /* send queued rays to idle children */ } -void -ray_psend(r) /* add a ray to our send queue */ -RAY *r; +extern void +ray_psend( /* add a ray to our send queue */ + RAY *r +) { if (r == NULL) return; @@ -229,14 +243,15 @@ RAY *r; if (sendq_full() && ray_pflush() <= 0) error(INTERNAL, "ray_pflush failed in ray_psend"); - copystruct(&r_queue[r_send_next], r); + r_queue[r_send_next] = *r; r_send_next++; } -int -ray_pqueue(r) /* queue a ray for computation */ -RAY *r; +extern int +ray_pqueue( /* queue a ray for computation */ + RAY *r +) { if (r == NULL) return(0); @@ -244,31 +259,32 @@ RAY *r; if (sendq_full()) { RAY mySend; int rval; - copystruct(&mySend, r); + mySend = *r; /* wait for a result */ rval = ray_presult(r, 0); /* put new ray in queue */ - copystruct(&r_queue[r_send_next], &mySend); + r_queue[r_send_next] = mySend; r_send_next++; return(rval); /* done */ } /* add ray to send queue */ - copystruct(&r_queue[r_send_next], r); + r_queue[r_send_next] = *r; r_send_next++; /* check for returned ray... */ if (r_recv_first >= r_recv_next) return(0); /* ...one is sitting in queue */ - copystruct(r, &r_queue[r_recv_first]); + *r = r_queue[r_recv_first]; r_recv_first++; return(1); } -int -ray_presult(r, poll) /* check for a completed ray */ -RAY *r; -int poll; +extern int +ray_presult( /* check for a completed ray */ + RAY *r, + int poll +) { static struct timeval tpoll; /* zero timeval struct */ static fd_set readset, errset; @@ -279,7 +295,7 @@ int poll; return(0); /* check queued results first */ if (r_recv_first < r_recv_next) { - copystruct(r, &r_queue[r_recv_first]); + *r = r_queue[r_recv_first]; r_recv_first++; return(1); } @@ -354,15 +370,16 @@ getready: /* any children waiting for us? */ rp->slights = NULL; } /* return first ray received */ - copystruct(r, &r_queue[r_recv_first]); + *r = r_queue[r_recv_first]; r_recv_first++; return(1); } -void -ray_pdone(freall) /* reap children and free data */ -int freall; +extern void +ray_pdone( /* reap children and free data */ + int freall +) { ray_pclose(0); /* close child processes */ @@ -375,9 +392,10 @@ int freall; static void -ray_pchild(fd_in, fd_out) /* process rays (never returns) */ -int fd_in; -int fd_out; +ray_pchild( /* process rays (never returns) */ + int fd_in, + int fd_out +) { int n; register int i; @@ -421,9 +439,10 @@ int fd_out; } -void -ray_popen(nadd) /* open the specified # processes */ -int nadd; +extern void +ray_popen( /* open the specified # processes */ + int nadd +) { /* check if our table has room */ if (ray_pnprocs + nadd > MAX_NPROCS) @@ -458,9 +477,10 @@ int nadd; } -void -ray_pclose(nsub) /* close one or more child processes */ -int nsub; +extern void +ray_pclose( /* close one or more child processes */ + int nsub +) { static int inclose = 0; RAY res; @@ -469,7 +489,7 @@ int nsub; return; inclose++; /* check argument */ - if ((nsub <= 0 | nsub > ray_pnprocs)) + if ((nsub <= 0) | (nsub > ray_pnprocs)) nsub = ray_pnprocs; /* clear our ray queue */ while (ray_presult(&res,0) > 0) @@ -480,8 +500,8 @@ int nsub; ray_pnprocs--; close(r_proc[ray_pnprocs].fd_recv); close(r_proc[ray_pnprocs].fd_send); - while (wait(&status) != r_proc[ray_pnprocs].pid) - ; + if (waitpid(r_proc[ray_pnprocs].pid, &status, 0) < 0) + status = 127<<8; if (status) { sprintf(errmsg, "rendering process %d exited with code %d",