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);
}
Exemple #2
0
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--;
}
Exemple #4
0
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);
}
Exemple #5
0
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--;
}
Exemple #6
0
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);
}