ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo2l.c
Revision: 3.13
Committed: Thu Jun 26 00:58:10 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.12: +18 -16 lines
Log Message:
Abstracted process and path handling for Windows.
Renamed FLOAT to RREAL because of conflict on Windows.
Added conditional compiles for some signal handlers.

File Contents

# User Rev Content
1 gregl 3.1 #ifndef lint
2 schorsch 3.13 static const char RCSid[] = "$Id: rholo2l.c,v 3.12 2003/02/22 02:07:25 greg Exp $";
3 gregl 3.1 #endif
4     /*
5     * Routines for local rtrace execution
6     */
7    
8 schorsch 3.13 #include <signal.h>
9     #include <sys/time.h>
10    
11 gregl 3.1 #include "rholo.h"
12     #include "random.h"
13 gregl 3.6 #include "paths.h"
14 gregl 3.3 #include "selcall.h"
15 schorsch 3.13 #include "rtprocess.h"
16 gregl 3.1
17     #ifndef MAXPROC
18 gregl 3.8 #define MAXPROC 64
19 gregl 3.1 #endif
20    
21 gregl 3.8 int nprocs = 0; /* running process count */
22    
23 gregl 3.6 static char pfile[] = TEMPLATE; /* persist file name */
24 gregl 3.1
25 schorsch 3.13 static SUBPROC rtpd[MAXPROC]; /* process descriptors */
26 gregl 3.1 static float *rtbuf = NULL; /* allocated i/o buffer */
27     static int maxqlen = 0; /* maximum packets per queue */
28    
29     static PACKET *pqueue[MAXPROC]; /* packet queues */
30     static int pqlen[MAXPROC]; /* packet queue lengths */
31    
32    
33     int
34     start_rtrace() /* start rtrace process */
35     {
36     static char buf1[8];
37     int rmaxpack = 0;
38 gregl 3.9 int psiz, n;
39 gregl 3.1 /* get number of processes */
40 gregl 3.10 if (ncprocs <= 0 || nprocs > 0)
41 gregl 3.1 return(0);
42 gregl 3.9 if (ncprocs > MAXPROC) {
43 gregl 3.1 sprintf(errmsg,
44     "number of rtrace processes reduced from %d to %d",
45 gregl 3.9 ncprocs, MAXPROC);
46 gregl 3.1 error(WARNING, errmsg);
47 gregl 3.9 ncprocs = MAXPROC;
48 gregl 3.1 }
49 gregl 3.9 if (rtargv[rtargc-1] != vval(OCTREE)) {
50     /* add compulsory options */
51     rtargv[rtargc++] = "-i-";
52     rtargv[rtargc++] = "-I-";
53     rtargv[rtargc++] = "-h-";
54     rtargv[rtargc++] = "-ld-";
55     sprintf(buf1, "%d", RPACKSIZ);
56     rtargv[rtargc++] = "-x"; rtargv[rtargc++] = buf1;
57     rtargv[rtargc++] = "-y"; rtargv[rtargc++] = "0";
58     rtargv[rtargc++] = "-fff";
59     rtargv[rtargc++] = vbool(VDIST) ? "-ovl" : "-ovL";
60     if (nowarn)
61     rtargv[rtargc++] = "-w-";
62     if (ncprocs > 1) {
63     mktemp(pfile);
64     rtargv[rtargc++] = "-PP"; rtargv[rtargc++] = pfile;
65     }
66     rtargv[rtargc++] = vval(OCTREE);
67     rtargv[rtargc] = NULL;
68 gregl 3.1 }
69     maxqlen = 0;
70 gregl 3.9 for (nprocs = 0; nprocs < ncprocs; nprocs++) { /* spawn children */
71 schorsch 3.13 psiz = open_process(&rtpd[nprocs], rtargv);
72 gregl 3.1 if (psiz <= 0)
73     error(SYSTEM, "cannot start rtrace process");
74     n = psiz/(RPACKSIZ*6*sizeof(float));
75     if (maxqlen == 0) {
76     if (!(maxqlen = n))
77     error(INTERNAL,
78     "bad pipe buffer size assumption");
79 gregl 3.11 sleep(2);
80 gregl 3.1 } else if (n != maxqlen)
81     error(INTERNAL, "varying pipe buffer size!");
82     rmaxpack += n;
83     }
84     rtbuf = (float *)malloc(RPACKSIZ*6*sizeof(float)*maxqlen);
85     if (rtbuf == NULL)
86     error(SYSTEM, "malloc failure in start_rtrace");
87     return(rmaxpack);
88     }
89    
90    
91     static int
92     bestout() /* get best process to process packet */
93     {
94     int cnt;
95     register int pn, i;
96    
97     pn = 0; /* find shortest queue */
98     for (i = 1; i < nprocs; i++)
99     if (pqlen[i] < pqlen[pn])
100     pn = i;
101     /* sanity check */
102     if (pqlen[pn] == maxqlen)
103     return(-1);
104     cnt = 0; /* count number of ties */
105     for (i = pn; i < nprocs; i++)
106     if (pqlen[i] == pqlen[pn])
107     cnt++;
108     /* break ties fairly */
109     if ((cnt = random() % cnt))
110     for (i = pn; i < nprocs; i++)
111     if (pqlen[i] == pqlen[pn] && !cnt--)
112     return(i);
113     return(pn);
114     }
115    
116    
117     int
118     slots_avail() /* count packet slots available */
119     {
120     register int nslots = 0;
121     register int i;
122    
123     for (i = nprocs; i--; )
124     nslots += maxqlen - pqlen[i];
125     return(nslots);
126     }
127    
128    
129     queue_packet(p) /* queue up a beam packet */
130     register PACKET *p;
131     {
132     int pn, n;
133     /* determine process to write to */
134     if ((pn = bestout()) < 0)
135     error(INTERNAL, "rtrace input queues are full!");
136     /* write out the packet */
137     packrays(rtbuf, p);
138     if ((n = p->nr) < RPACKSIZ) /* add flush block? */
139     bzero((char *)(rtbuf+6*n++), 6*sizeof(float));
140 schorsch 3.13 if (writebuf(rtpd[pn].w, (char *)rtbuf, 6*sizeof(float)*n) < 0)
141 gregl 3.1 error(SYSTEM, "write error in queue_packet");
142     p->next = NULL;
143     if (!pqlen[pn]++) /* add it to the end of the queue */
144     pqueue[pn] = p;
145     else {
146     register PACKET *rpl = pqueue[pn];
147     while (rpl->next != NULL)
148     rpl = rpl->next;
149     rpl->next = p;
150     }
151     }
152    
153    
154     PACKET *
155     get_packets(poll) /* read packets from rtrace processes */
156     int poll;
157     {
158     static struct timeval tpoll; /* zero timeval struct */
159     fd_set readset, errset;
160     PACKET *pldone = NULL, *plend;
161     register PACKET *p;
162     int n, nr;
163     register int pn;
164     float *bp;
165     /* prepare select call */
166     FD_ZERO(&readset); FD_ZERO(&errset); n = 0;
167     for (pn = nprocs; pn--; ) {
168     if (pqlen[pn])
169 schorsch 3.13 FD_SET(rtpd[pn].r, &readset);
170     FD_SET(rtpd[pn].r, &errset);
171     if (rtpd[pn].r >= n)
172     n = rtpd[pn].r + 1;
173 gregl 3.1 }
174     /* make the call */
175     n = select(n, &readset, (fd_set *)NULL, &errset,
176     poll ? &tpoll : (struct timeval *)NULL);
177     if (n < 0) {
178     if (errno == EINTR) /* interrupted select call */
179     return(NULL);
180     error(SYSTEM, "select call failure in get_packets");
181     }
182     if (n == 0) /* is nothing ready? */
183     return(NULL);
184     /* make read call(s) */
185     for (pn = 0; pn < nprocs; pn++) {
186 schorsch 3.13 if (!FD_ISSET(rtpd[pn].r, &readset) &&
187     !FD_ISSET(rtpd[pn].r, &errset))
188 gregl 3.1 continue;
189     reread:
190 schorsch 3.13 n = read(rtpd[pn].r, (char *)rtbuf,
191 gregl 3.1 4*sizeof(float)*RPACKSIZ*pqlen[pn]);
192     if (n < 0) {
193     if (errno == EINTR | errno == EAGAIN)
194     goto reread;
195     error(SYSTEM, "read error in get_packets");
196     }
197     if (n == 0)
198     goto eoferr;
199     bp = rtbuf; /* finish processing */
200     for (p = pqueue[pn]; n && p != NULL; p = p->next) {
201     if ((nr = p->nr) < RPACKSIZ)
202     nr++; /* add flush block */
203     n -= 4*sizeof(float)*nr;
204     if (n < 0) { /* get remainder */
205 schorsch 3.13 n += readbuf(rtpd[pn].r,
206 gregl 3.1 (char *)(bp+4*nr)+n, -n);
207     if (n)
208     goto eoferr;
209     }
210     donerays(p, bp);
211     bp += 4*nr;
212     pqlen[pn]--;
213     }
214     if (n) /* read past end? */
215     error(INTERNAL, "packet sync error in get_packets");
216     /* take from queue */
217 gregl 3.2 if (pldone == NULL)
218 gregl 3.1 pldone = plend = pqueue[pn];
219     else
220     plend->next = pqueue[pn];
221     while (plend->next != p)
222     plend = plend->next;
223     plend->next = NULL;
224     pqueue[pn] = p;
225     }
226     return(pldone); /* return finished packets */
227     eoferr:
228 gregl 3.3 error(USER, "rtrace process died");
229 gregl 3.1 }
230    
231    
232     PACKET *
233     do_packets(pl) /* queue a packet list, return finished */
234     register PACKET *pl;
235     {
236     register PACKET *p;
237     /* consistency check */
238     if (nprocs < 1)
239     error(CONSISTENCY, "do_packets called with no active process");
240     /* queue each new packet */
241     while (pl != NULL) {
242     p = pl; pl = p->next; p->next = NULL;
243     queue_packet(p);
244     }
245     return(get_packets(slots_avail())); /* return processed packets */
246     }
247    
248    
249     PACKET *
250     flush_queue() /* empty all rtrace queues */
251     {
252     PACKET *rpdone = NULL;
253     register PACKET *rpl;
254     float *bp;
255     register PACKET *p;
256     int i, n, nr;
257    
258     for (i = 0; i < nprocs; i++)
259     if (pqlen[i]) {
260     if (rpdone == NULL) { /* tack on queue */
261     rpdone = rpl = pqueue[i];
262 gregl 3.4 if ((nr = rpl->nr) < RPACKSIZ) nr++;
263 gregl 3.1 } else {
264     rpl->next = pqueue[i];
265 gregl 3.2 nr = 0;
266 gregl 3.1 }
267 gregl 3.2 while (rpl->next != NULL) {
268     nr += (rpl = rpl->next)->nr;
269     if (rpl->nr < RPACKSIZ)
270     nr++; /* add flush block */
271     }
272 schorsch 3.13 n = readbuf(rtpd[i].r, (char *)rtbuf,
273 gregl 3.2 4*sizeof(float)*nr);
274 gregl 3.1 if (n < 0)
275     error(SYSTEM, "read failure in flush_queue");
276     bp = rtbuf; /* process packets */
277     for (p = pqueue[i]; p != NULL; p = p->next) {
278     if ((nr = p->nr) < RPACKSIZ)
279     nr++; /* add flush block */
280     n -= 4*sizeof(float)*nr;
281     if (n >= 0)
282     donerays(p, bp);
283     else
284     p->nr = 0; /* short data error */
285     bp += 4*nr;
286     }
287     pqueue[i] = NULL; /* zero this queue */
288     pqlen[i] = 0;
289     }
290     return(rpdone); /* return all packets completed */
291     }
292    
293    
294     static
295     killpersist() /* kill persistent process */
296     {
297     FILE *fp;
298     int pid;
299    
300 gregl 3.6 if ((fp = fopen(pfile, "r")) == NULL)
301 gregl 3.1 return;
302     if (fscanf(fp, "%*s %d", &pid) != 1 || kill(pid, SIGALRM) < 0)
303 gregl 3.6 unlink(pfile);
304 gregl 3.1 fclose(fp);
305     }
306    
307    
308     int
309     end_rtrace() /* close rtrace process(es) */
310     {
311     int status = 0, rv;
312    
313     if (nprocs > 1)
314     killpersist();
315     while (nprocs > 0) {
316 schorsch 3.13 rv = close_process(&rtpd[--nprocs]);
317 gregl 3.1 if (rv > 0)
318     status = rv;
319     }
320 greg 3.12 free((void *)rtbuf);
321 gregl 3.1 rtbuf = NULL;
322     maxqlen = 0;
323     return(status);
324     }