ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo2l.c
Revision: 3.20
Committed: Sat Dec 16 18:33:55 2023 UTC (4 months, 2 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 3.19: +2 -1 lines
Log Message:
fix(rholo): Added -co- switch to overriding rtrace options

File Contents

# User Rev Content
1 gregl 3.1 #ifndef lint
2 greg 3.20 static const char RCSid[] = "$Id: rholo2l.c,v 3.19 2022/04/21 03:11:55 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 schorsch 3.13 static SUBPROC rtpd[MAXPROC]; /* process descriptors */
27 gregl 3.1 static float *rtbuf = NULL; /* allocated i/o buffer */
28     static int maxqlen = 0; /* maximum packets per queue */
29    
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.20 rtargv[rtargc++] = "-co-";
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     n = psiz/(RPACKSIZ*6*sizeof(float));
83     if (maxqlen == 0) {
84     if (!(maxqlen = n))
85     error(INTERNAL,
86     "bad pipe buffer size assumption");
87 gregl 3.11 sleep(2);
88 gregl 3.1 } else if (n != maxqlen)
89     error(INTERNAL, "varying pipe buffer size!");
90     rmaxpack += n;
91     }
92     rtbuf = (float *)malloc(RPACKSIZ*6*sizeof(float)*maxqlen);
93     if (rtbuf == NULL)
94     error(SYSTEM, "malloc failure in start_rtrace");
95     return(rmaxpack);
96     }
97    
98    
99     static int
100 schorsch 3.16 bestout(void) /* get best process to process packet */
101 gregl 3.1 {
102     int cnt;
103 greg 3.18 int pn, i;
104 gregl 3.1
105     pn = 0; /* find shortest queue */
106     for (i = 1; i < nprocs; i++)
107     if (pqlen[i] < pqlen[pn])
108     pn = i;
109     /* sanity check */
110     if (pqlen[pn] == maxqlen)
111     return(-1);
112     cnt = 0; /* count number of ties */
113     for (i = pn; i < nprocs; i++)
114     if (pqlen[i] == pqlen[pn])
115     cnt++;
116     /* break ties fairly */
117 greg 3.19 if ((cnt = irandom(cnt)))
118 gregl 3.1 for (i = pn; i < nprocs; i++)
119     if (pqlen[i] == pqlen[pn] && !cnt--)
120     return(i);
121     return(pn);
122     }
123    
124    
125 schorsch 3.16 static int
126     slots_avail(void) /* count packet slots available */
127 gregl 3.1 {
128 greg 3.18 int nslots = 0;
129     int i;
130 gregl 3.1
131     for (i = nprocs; i--; )
132     nslots += maxqlen - pqlen[i];
133     return(nslots);
134     }
135    
136    
137 schorsch 3.16 static void
138     queue_packet( /* queue up a beam packet */
139 greg 3.18 PACKET *p
140 schorsch 3.16 )
141 gregl 3.1 {
142     int pn, n;
143     /* determine process to write to */
144     if ((pn = bestout()) < 0)
145     error(INTERNAL, "rtrace input queues are full!");
146     /* write out the packet */
147     packrays(rtbuf, p);
148     if ((n = p->nr) < RPACKSIZ) /* add flush block? */
149 schorsch 3.14 memset((char *)(rtbuf+6*n++), '\0', 6*sizeof(float));
150 schorsch 3.13 if (writebuf(rtpd[pn].w, (char *)rtbuf, 6*sizeof(float)*n) < 0)
151 gregl 3.1 error(SYSTEM, "write error in queue_packet");
152     p->next = NULL;
153     if (!pqlen[pn]++) /* add it to the end of the queue */
154     pqueue[pn] = p;
155     else {
156 greg 3.18 PACKET *rpl = pqueue[pn];
157 gregl 3.1 while (rpl->next != NULL)
158     rpl = rpl->next;
159     rpl->next = p;
160     }
161     }
162    
163    
164 schorsch 3.16 static PACKET *
165     get_packets( /* read packets from rtrace processes */
166     int poll
167     )
168 gregl 3.1 {
169     static struct timeval tpoll; /* zero timeval struct */
170     fd_set readset, errset;
171     PACKET *pldone = NULL, *plend;
172 greg 3.18 PACKET *p;
173 gregl 3.1 int n, nr;
174 greg 3.18 int pn;
175 gregl 3.1 float *bp;
176     /* prepare select call */
177     FD_ZERO(&readset); FD_ZERO(&errset); n = 0;
178     for (pn = nprocs; pn--; ) {
179     if (pqlen[pn])
180 schorsch 3.13 FD_SET(rtpd[pn].r, &readset);
181     FD_SET(rtpd[pn].r, &errset);
182     if (rtpd[pn].r >= n)
183     n = rtpd[pn].r + 1;
184 gregl 3.1 }
185     /* make the call */
186     n = select(n, &readset, (fd_set *)NULL, &errset,
187     poll ? &tpoll : (struct timeval *)NULL);
188     if (n < 0) {
189     if (errno == EINTR) /* interrupted select call */
190     return(NULL);
191     error(SYSTEM, "select call failure in get_packets");
192     }
193     if (n == 0) /* is nothing ready? */
194     return(NULL);
195     /* make read call(s) */
196     for (pn = 0; pn < nprocs; pn++) {
197 schorsch 3.13 if (!FD_ISSET(rtpd[pn].r, &readset) &&
198     !FD_ISSET(rtpd[pn].r, &errset))
199 gregl 3.1 continue;
200     reread:
201 schorsch 3.13 n = read(rtpd[pn].r, (char *)rtbuf,
202 gregl 3.1 4*sizeof(float)*RPACKSIZ*pqlen[pn]);
203     if (n < 0) {
204 schorsch 3.15 if ((errno == EINTR) | (errno == EAGAIN))
205 gregl 3.1 goto reread;
206     error(SYSTEM, "read error in get_packets");
207     }
208     if (n == 0)
209     goto eoferr;
210     bp = rtbuf; /* finish processing */
211     for (p = pqueue[pn]; n && p != NULL; p = p->next) {
212     if ((nr = p->nr) < RPACKSIZ)
213     nr++; /* add flush block */
214     n -= 4*sizeof(float)*nr;
215     if (n < 0) { /* get remainder */
216 schorsch 3.13 n += readbuf(rtpd[pn].r,
217 gregl 3.1 (char *)(bp+4*nr)+n, -n);
218     if (n)
219     goto eoferr;
220     }
221     donerays(p, bp);
222     bp += 4*nr;
223     pqlen[pn]--;
224     }
225     if (n) /* read past end? */
226     error(INTERNAL, "packet sync error in get_packets");
227     /* take from queue */
228 gregl 3.2 if (pldone == NULL)
229 gregl 3.1 pldone = plend = pqueue[pn];
230     else
231     plend->next = pqueue[pn];
232     while (plend->next != p)
233     plend = plend->next;
234     plend->next = NULL;
235     pqueue[pn] = p;
236     }
237     return(pldone); /* return finished packets */
238     eoferr:
239 gregl 3.3 error(USER, "rtrace process died");
240 schorsch 3.16 return NULL; /* pro forma return */
241 gregl 3.1 }
242    
243    
244 greg 3.18 PACKET *
245 schorsch 3.16 do_packets( /* queue a packet list, return finished */
246 greg 3.18 PACKET *pl
247 schorsch 3.16 )
248 gregl 3.1 {
249 greg 3.18 PACKET *p;
250 gregl 3.1 /* consistency check */
251     if (nprocs < 1)
252     error(CONSISTENCY, "do_packets called with no active process");
253     /* queue each new packet */
254     while (pl != NULL) {
255     p = pl; pl = p->next; p->next = NULL;
256     queue_packet(p);
257     }
258     return(get_packets(slots_avail())); /* return processed packets */
259     }
260    
261    
262 greg 3.18 PACKET *
263 schorsch 3.16 flush_queue(void) /* empty all rtrace queues */
264 gregl 3.1 {
265     PACKET *rpdone = NULL;
266 greg 3.18 PACKET *rpl = NULL;
267 gregl 3.1 float *bp;
268 greg 3.18 PACKET *p;
269 gregl 3.1 int i, n, nr;
270    
271     for (i = 0; i < nprocs; i++)
272     if (pqlen[i]) {
273     if (rpdone == NULL) { /* tack on queue */
274     rpdone = rpl = pqueue[i];
275 gregl 3.4 if ((nr = rpl->nr) < RPACKSIZ) nr++;
276 gregl 3.1 } else {
277     rpl->next = pqueue[i];
278 gregl 3.2 nr = 0;
279 gregl 3.1 }
280 gregl 3.2 while (rpl->next != NULL) {
281     nr += (rpl = rpl->next)->nr;
282     if (rpl->nr < RPACKSIZ)
283     nr++; /* add flush block */
284     }
285 schorsch 3.13 n = readbuf(rtpd[i].r, (char *)rtbuf,
286 gregl 3.2 4*sizeof(float)*nr);
287 gregl 3.1 if (n < 0)
288     error(SYSTEM, "read failure in flush_queue");
289     bp = rtbuf; /* process packets */
290     for (p = pqueue[i]; p != NULL; p = p->next) {
291     if ((nr = p->nr) < RPACKSIZ)
292     nr++; /* add flush block */
293     n -= 4*sizeof(float)*nr;
294     if (n >= 0)
295     donerays(p, bp);
296     else
297     p->nr = 0; /* short data error */
298     bp += 4*nr;
299     }
300     pqueue[i] = NULL; /* zero this queue */
301     pqlen[i] = 0;
302     }
303     return(rpdone); /* return all packets completed */
304     }
305    
306    
307 schorsch 3.16 static void
308     killpersist(void) /* kill persistent process */
309 gregl 3.1 {
310     FILE *fp;
311     int pid;
312    
313 gregl 3.6 if ((fp = fopen(pfile, "r")) == NULL)
314 gregl 3.1 return;
315     if (fscanf(fp, "%*s %d", &pid) != 1 || kill(pid, SIGALRM) < 0)
316 gregl 3.6 unlink(pfile);
317 gregl 3.1 fclose(fp);
318     }
319    
320    
321 greg 3.18 int
322 schorsch 3.16 end_rtrace(void) /* close rtrace process(es) */
323 gregl 3.1 {
324     int status = 0, rv;
325    
326     if (nprocs > 1)
327     killpersist();
328 greg 3.17 status = close_processes(rtpd, nprocs);
329     nprocs = 0;
330 greg 3.12 free((void *)rtbuf);
331 gregl 3.1 rtbuf = NULL;
332     maxqlen = 0;
333     return(status);
334     }