int ray_pqueue( /* queue a ray for computation */ RAY *r ) { if (r == NULL) return(0); /* check for full send queue */ if (sendq_full()) { RAY mySend = *r; /* wait for a result */ if (ray_presult(r, 0) <= 0) return(-1); /* put new ray in queue */ r_queue[r_send_next++] = mySend; return(1); } /* 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++]; return(1); }
int ray_fifo_in( /* add ray to FIFO */ RAY *r ) { static int incall = 0; /* prevent recursion */ int rv, rval = 0; if (incall++) error(INTERNAL, "recursive call to ray_fifo_in()"); if (r_fifo_start >= 1L<<30) { /* reset our counters */ if ((rv = ray_fifo_flush()) < 0) {--incall; return(-1);} rval += rv; } /* queue ray */ r->rno = r_fifo_next++; if ((rv = ray_pqueue(r)) < 0) {--incall; return(-1);} if (!rv) /* no result this time? */ {--incall; return(rval);} do { /* else send/queue result */ if ((rv = ray_fifo_push(r)) < 0) {--incall; return(-1);} rval += rv; } while (ray_presult(r, -1) > 0); /* empty in-core queue */ --incall; return(rval); }
void ray_pclose( /* close one or more child processes */ int nsub ) { static int inclose = 0; RAY res; int i, status = 0; /* check recursion */ if (inclose) return; inclose++; /* check no child / in child */ if (ray_pnprocs <= 0) return; /* check argument */ if ((nsub <= 0) | (nsub > ray_pnprocs)) nsub = ray_pnprocs; /* clear our ray queue */ while (ray_presult(&res,0) > 0) ; r_send_next = 0; /* hard reset in case of error */ r_recv_first = r_recv_next = RAYQLEN; /* close send pipes */ for (i = ray_pnprocs-nsub; i < ray_pnprocs; i++) close(r_proc[i].fd_send); if (nsub == 1) { /* awaiting single process? */ if (waitpid(r_proc[ray_pnprocs-1].pid, &status, 0) < 0) status = 127<<8; close(r_proc[ray_pnprocs-1].fd_recv); } else /* else unordered wait */ for (i = 0; i < nsub; ) { int j, mystatus; RT_PID pid = wait(&mystatus); for (j = ray_pnprocs-nsub; j < ray_pnprocs; j++) if (r_proc[j].pid == pid) { if (mystatus) status = mystatus; close(r_proc[j].fd_recv); ++i; } } ray_pnprocs -= nsub; ray_pnidle -= nsub; if (status) { sprintf(errmsg, "rendering process exited with code %d", status>>8); error(WARNING, errmsg); } inclose--; }
int waitrays(void) /* finish up pending rays */ { int nwaited = 0; int rval; RAY raydone; if (!ray_pnprocs) /* immediate mode? */ return(0); while ((rval = ray_presult(&raydone, 0)) > 0) { PNODE *p = (PNODE *)raydone.rno; copycolor(p->v, raydone.rcol); scalecolor(p->v, exposure); recolor(p); nwaited++; } if (rval < 0) return(-1); return(nwaited); }
void ray_pclose( /* close one or more child processes */ int nsub ) { static int inclose = 0; RAY res; /* check recursion */ if (inclose) return; inclose++; /* check no child / in child */ if (ray_pnprocs <= 0) return; /* check argument */ if ((nsub <= 0) | (nsub > ray_pnprocs)) nsub = ray_pnprocs; /* clear our ray queue */ while (ray_presult(&res,0) > 0) ; r_send_next = 0; /* hard reset in case of error */ r_recv_first = r_recv_next = RAYQLEN; /* clean up children */ while (nsub--) { int status; ray_pnprocs--; close(r_proc[ray_pnprocs].fd_send); if (waitpid(r_proc[ray_pnprocs].pid, &status, 0) < 0) status = 127<<8; close(r_proc[ray_pnprocs].fd_recv); if (status) { sprintf(errmsg, "rendering process %d exited with code %d", r_proc[ray_pnprocs].pid, status>>8); error(WARNING, errmsg); } ray_pnidle--; } inclose--; }
int ray_fifo_flush(void) /* flush everything and release buffer */ { RAY myRay; int rv, rval = 0; /* clear parallel queue */ while ((rv = ray_presult(&myRay, 0)) > 0 && (rv = ray_fifo_push(&myRay)) >= 0) rval += rv; if (rv < 0) /* check for exception */ return(-1); if (r_fifo_start != r_fifo_end) error(INTERNAL, "could not empty queue in ray_fifo_flush()"); if (r_fifo_buf != NULL) { free(r_fifo_buf); r_fifo_buf = NULL; r_fifo_len = 0; } r_fifo_next = r_fifo_end = r_fifo_start = 1; return(rval); }