ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo2l.c
Revision: 3.24
Committed: Thu Feb 6 03:54:32 2025 UTC (2 months, 3 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 3.23: +2 -2 lines
Log Message:
fix(rholo): Safer option setting for rtrace to avoid non-RGB results

File Contents

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