The VisAO Camera
fifoutils.c
Go to the documentation of this file.
1 /************************************************************
2 * fifoutils.c
3 *
4 * Author: Jared R. Males (jrmales@as.arizona.edu)
5 *
6 * Linux fifo utilities, definitions
7 *
8 ************************************************************/
9 
10 /** \file fifoutils.c
11  * \author Jared R. Males
12  * \brief Definitions for linux fifo utilities.
13  *
14 */
15 
16 
17 
18 #include "fifoutils.h"
19 
20 #include "time.h"
21 #include "sys/time.h"
22 
23 double get_currt()
24 {
25  struct timespec tsp;
26  clock_gettime(CLOCK_REALTIME, &tsp);
27 
28  return ((double)tsp.tv_sec) + ((double)tsp.tv_nsec)/1e9;
29 }
30 
31 int init_fifo_channel(fifo_channel * fc)
32 {
33  fc->fd_out = 0;
34  fc->fd_in = 0;
35  fc->infname = 0;
36  fc->outfname = 0;
37  fc->input_handler = 0;
38  fc->server_response = 0;
39  fc->sr_sz = 0;
40  fc->auxdata = 0;
41  fc->timeout = 0;
42  fc->last_atime_out = 0;
43  fc->last_atime_in = 0;
44  return 0;
45 }
46 
47 int setup_fifo_channel(fifo_channel *fc,size_t buffsz)
48 {
49  if(fc->server_response) free(fc->server_response);
50 
51  fc->sr_sz = buffsz;
52 
53  fc->server_response = (char *)malloc(buffsz*sizeof(char));
54 
55  if(fc->server_response) return 0;
56  else
57  {
58  ERRMSG("server_response malloc failed in setup_fifo_channel.");
59  return -1;
60  }
61 }
62 
63 int set_fifo_channel(fifo_channel *fc, const char *fin, const char *fout, int (*inp_hand)(fifo_channel *), void * adata)
64 {
65  if(fc->infname) free(fc->infname);
66  fc->infname = (char *)malloc((strlen(fin)+1)*sizeof(char));
67  if(fc->infname == 0)
68  {
69  ERRMSG("infname malloc failed in set_fifo_channel.");
70  return -1;
71  }
72 
73  if(fc->outfname) free(fc->outfname);
74  fc->outfname = (char *)malloc((strlen(fout)+1)*sizeof(char));
75  if(fc->outfname == 0)
76  {
77  ERRMSG("outfname malloc failed in set_fifo_channel.");
78  return -1;
79  }
80 
81  strncpy(fc->infname, fin, (strlen(fin)+1));
82  strncpy(fc->outfname, fout, (strlen(fout)+1));
83 
84  fc->input_handler = inp_hand;
85 
86  fc->auxdata = adata;
87 
88  return create_fifos(fc);
89 
90 }
91 
92 int create_fifos(fifo_channel *fc)
93 {
94  //int i;
95  //umask(0);
96 
97  errno = 0;
98  if(mkfifo(fc->infname, S_IRUSR | S_IWUSR) !=0) // | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0)
99  {
100  if(errno != EEXIST)
101  {
102  ERRMSG("Error creating input fifo.");
103  return -1;
104  }
105  }
106  errno = 0;
107  if(mkfifo(fc->outfname, S_IRUSR | S_IWUSR) !=0 )//| S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0)
108  {
109  if(errno != EEXIST)
110  {
111  ERRMSG("Error creating output fifo.");
112  return -1;
113  }
114  }
115 
116  return 0;
117 }//int create_fifos(fifo_channel *fc)
118 
119 int open_fifo_channel_in(fifo_channel *fc)
120 {
121  int nbytes;
122  char rbuff[10];
123 
124  fc->fd_in = ropen_async(fc->infname, 0);
125 
126  if(fc->fd_in < 0)
127  {
128  ERRMSG("Error opening input fifo.");
129  return -1;
130  }
131 
132  //should lock.
133 
134  //Clear the fifo.
135  if(fc->fd_in > 0)
136  {
137  nbytes = read(fc->fd_in, rbuff, 10);
138  while(nbytes > 0) nbytes = read(fc->fd_in, rbuff, 10);
139  }
140 
141  return 0;
142 }
143 
144 int open_fifo_channel_in_nolock(fifo_channel *fc)
145 {
146  int nbytes;
147  char rbuff[10];
148 
149  fc->fd_in = ropen_async(fc->infname, 1);
150 
151  if(fc->fd_in < 0)
152  {
153  ERRMSG("Error opening input fifo.");
154  return -1;
155  }
156 
157  if(fc->fd_in > 0)
158  {
159  nbytes = read(fc->fd_in, rbuff, 10);
160  while(nbytes > 0) nbytes = read(fc->fd_in, rbuff, 10);
161  }
162 
163  return 0;
164 }
165 
166 int open_fifo_channel_out(fifo_channel *fc)
167 {
168 
169  fc->fd_out = wopen_nonblock(fc->outfname, 0);
170 
171  if(fc->fd_out < 0)
172  {
173  ERRMSG("Error opening output fifo.");
174  return -1;
175  }
176 
177  return 0;
178 }
179 
180 int open_fifo_channel_out_nolock(fifo_channel *fc)
181 {
182 
183  fc->fd_out = wopen_nonblock(fc->outfname, 1);
184 
185  if(fc->fd_out < 0)
186  {
187  ERRMSG("Error opening output fifo.");
188  return -1;
189  }
190 
191  return 0;
192 }
193 
194 int write_fifo_channel(fifo_channel *fc, const char * com, int comlen)
195 {
196  int nbytes;
197 
198  if(fc->fd_out == 0)
199  {
200  ERRMSG("Fifo channel output not connected.");
201  return -1;
202  }
203 
204  if(comlen + 1 > RWBUFF_SZ)
205  {
206  ERRMSG("Output buffer to large.");
207  return -1;
208  }
209 
210  fc->server_response[0] = '\0';
211  fc->seqmsg = fc->server_response;
212 
213  nbytes = write(fc->fd_out, com, comlen+1);
214 
215  return nbytes;
216 }
217 
218 int write_fifo_channel_seqmsg(fifo_channel *fc, const char * com, int comlen, char * seqmsg)
219 {
220  int nbytes;
221  char wbuff[RWBUFF_SZ];
222 
223  if(fc->fd_out == 0)
224  {
225  ERRMSG("Fifo channel output not connected.");
226  return -1;
227  }
228 
229  if(comlen + 7 > RWBUFF_SZ)
230  {
231  ERRMSG("Output buffer to large.");
232  return -1;
233  }
234 
235  fc->server_response[0] = '\0';
236  fc->seqmsg = fc->server_response;
237 
238  memcpy(wbuff, com, comlen+1);
239  memcpy(wbuff+comlen+1, seqmsg, 6);
240 
241  nbytes = write(fc->fd_out, wbuff, comlen+7); // +7
242 
243  return nbytes;
244 }
245 
246 int read_fifo_channel(fifo_channel * fc)
247 {
248  int nbytes, totbytes;
249  size_t slen;
250  char rbuffer[RWBUFF_SZ];
251  //testing vars:
252  //char app[3];
253  //uint32_t sn;
254 
255  if(fc->fd_in == 0)
256  {
257  ERRMSG("Fifo channel input not connected.");
258  return -1;
259  }
260 
261  totbytes = 0;
262 
263  errno = 0;
264  nbytes = read(fc->fd_in, rbuffer, RWBUFF_SZ);
265 
266  //totbytes += nbytes;
267  //rbuffer[nbytes+1] = '\0';
268 
269 
270  while(nbytes > 0 && nbytes+totbytes < fc->sr_sz-1)
271  {
272  memcpy(fc->server_response + totbytes, rbuffer, nbytes);
273  totbytes += nbytes;
274 
275  //snprintf(fc->server_response, fc->sr_sz, "%s%s", fc->server_response, rbuffer); //Probably a better way to do this?
276 
277  nbytes = read(fc->fd_in, rbuffer, RWBUFF_SZ);
278 
279  //rbuffer[nbytes+1] = '\0';
280  }
281 
282  if(nbytes < 0 && errno != EAGAIN)
283  {
284  ERRMSG("Read error.");
285  }
286 
287  if(totbytes + nbytes >= fc->sr_sz-1)
288  {
289  ERRMSG("input exceeded max server response size (fc->sr_sz). fifo read truncated.");
290  }
291 
292  if(totbytes > 0)
293  {
294  fc->server_response[totbytes] = '\0';
295 
296  slen = strlen(fc->server_response);
297  //if(totbytes > slen)
298  fc->seqmsg = &(fc->server_response[slen+1]);
299  //else fc->seqmsg = fc->server_response[slen];
300 
301 
302  /* if(fc->seqmsg[0] != '\0')
303  {
304  printf("Sequence message detected\n");
305  printf("%i\t%i\t|%s|\n", totbytes, (int) strlen(fc->server_response), fc->server_response);
306  parse_seqmsg(app, &sn, fc->seqmsg);
307  app[2] = '\0';
308  printf("%s\t%i\n", app, sn);
309  }*/
310  }
311  else fc->seqmsg = fc->server_response;
312 
313  return totbytes;
314 }
315 
316 int check_if_in_locked(fifo_channel *fc)
317 {
318  struct flock fl;
319  fl.l_type = F_WRLCK; //check for an exclusive lock
320  fl.l_whence = SEEK_SET;
321  fl.l_start = 0;
322  fl.l_len = 0;
323  fl.l_pid = getpid();
324 
325  if(fcntl(fc->fd_out, F_GETLK, &fl) < 0) return 1;
326 
327  if(fl.l_type == F_UNLCK) return 0;
328  else return 1;
329 
330  /*int pid;
331  pid = fcntl(fc->fd_out, F_GETOWN);
332  printf("%d\n", pid);
333 
334  return pid;*/
335 
336 }
337 
338 
339 /******* fifo_list functions ************/
340 
342 {
343  fl->nchan = 0;
344  fl->fifo_ch = 0;
345  FD_ZERO(&fl->fds);
346  fl->maxfile = 0;
347  fl->rq_sz = 1024;
348 
349  fl->RTSIGIO_overflow = 0;
350 
351  return 0;
352 }
353 
354 int setup_fifo_list(fifo_list * fl, int nch)
355 {
356  int i;
357 
358  fl->nchan = nch;
359 
360  fl->fifo_ch = (fifo_channel *)malloc(nch*sizeof(fifo_channel));
361 
362  if(fl->fifo_ch == 0)
363  {
364  ERRMSG("Error allocating fifo_list memory.");
365  return -1;
366  }
367 
368  for(i=0; i<nch; i++) init_fifo_channel(&fl->fifo_ch[i]);
369 
370  return 0;
371 }
372 
373 int set_fifo_list_channel(fifo_list *fl, int nch, int buffsz, const char *fin, const char *fout, int (*inp_hand)(fifo_channel *), void *adata)
374 {
375  if(setup_fifo_channel(&fl->fifo_ch[nch], buffsz) < 0) return -1;
376  return set_fifo_channel(&fl->fifo_ch[nch], fin, fout, inp_hand, adata);
377 }
378 
380 {
381  int i;
382  char errmsg[ERRMSG_SZ];
383 
384  for(i = 0; i < fl->nchan; i++)
385  {
386  if(open_fifo_channel_in(&fl->fifo_ch[i]) != 0)
387  {
388  snprintf(errmsg, ERRMSG_SZ, "Error opening input fifo channel %i (%s)", i, fl->fifo_ch[i].infname);
389  ERRMSG(errmsg);
390  return -1;
391  }
392  else
393  {
394  FD_SET(fl->fifo_ch[i].fd_in, &fl->fds);
395 
396  if(fl->fifo_ch[i].fd_in > fl->maxfile) fl->maxfile = fl->fifo_ch[i].fd_in;
397  }
398 
399  }
400 
401  for(i = 0; i < fl->nchan; i++)
402  {
403  if(open_fifo_channel_out_nolock(&fl->fifo_ch[i]) != 0)
404  {
405  snprintf(errmsg, ERRMSG_SZ, "Error opening output fifo channel %i (%s)", i, fl->fifo_ch[i].outfname);
406  ERRMSG(errmsg);
407  return -1;
408  }
409  }
410 
411  return init_fifo_list_pending_reads(fl);
412 
413 }
414 
416 {
417  int i;
418  char errmsg[ERRMSG_SZ];
419  //printf("4.4.1\n");
420  for(i = 0; i < fl->nchan; i++)
421  {
422  //printf("4.4.2 %i\n", i);
423 
424  if(open_fifo_channel_in_nolock(&fl->fifo_ch[i]) != 0)
425  {
426  snprintf(errmsg, ERRMSG_SZ, "Error opening input fifo channel %i (%s)", i, fl->fifo_ch[i].infname);
427  ERRMSG(errmsg);
428  return -1;
429  }
430  else
431  {
432  //printf("4.4.3 %i\n", i);
433  FD_SET(fl->fifo_ch[i].fd_in, &fl->fds);
434 
435  if(fl->fifo_ch[i].fd_in > fl->maxfile) fl->maxfile = fl->fifo_ch[i].fd_in;
436  }
437 
438  }
439  //printf("4.4.4\n");
440  for(i = 0; i < fl->nchan; i++)
441  {
442  if(open_fifo_channel_out_nolock(&fl->fifo_ch[i]) != 0)
443  {
444  snprintf(errmsg, ERRMSG_SZ, "Error opening output fifo channel %i (%s)", i, fl->fifo_ch[i].outfname);
445  ERRMSG(errmsg);
446  return -1;
447  }
448  }
449  //printf("4.4.5\n");
450  return init_fifo_list_pending_reads(fl);
451 
452 }
453 
455 {
456  int i;
457 
458  fl->fd_to_fifo_ch_index = (int *) malloc((fl->maxfile+1)*sizeof(int));
459 
460  for(i = 0; i < fl->maxfile+1; i++)
461  {
462  fl->fd_to_fifo_ch_index[i] = 0;
463  }
464 
465  for(i =0; i < fl->nchan; i++)
466  {
467  fl->fd_to_fifo_ch_index[fl->fifo_ch[i].fd_in] = i;
468  }
469 
470  fl->tot_pending_reads = 0;
471 
472  fl->pending_reads = (int *) malloc(fl->nchan*sizeof(int));
473 
474  for(i=0;i<fl->nchan;i++)
475  {
476  fl->pending_reads[i] = 0;
477  }
478 
479  fl->read_queue = (int *) malloc(fl->rq_sz*sizeof(int));
480 
481  for(i=0; i < fl->rq_sz; i++)
482  {
483  fl->read_queue[i] = 0;
484  }
485  fl->read_queue_pos = 0;
486  fl->read_queue_nextpos = 0;
487 
488  return 0;
489 }
490 
491 void catch_fifo_response_list(int signum __attribute__((unused)))
492 {
493  int i;
494  struct timeval tv;
495  tv.tv_sec = 0;
496  tv.tv_usec = 10;
497 
498  //printf("SIGIO Caught\n");
499 
500  select(global_fifo_list->maxfile+1, &global_fifo_list->fds, 0, 0, &tv);
501 
502  for(i=0;i<global_fifo_list->nchan;i++)
503  {
504  if(global_fifo_list->fifo_ch[i].fd_in > -1)
505  {
506  if(FD_ISSET(global_fifo_list->fifo_ch[i].fd_in, &global_fifo_list->fds))
507  {
508  global_fifo_list->fifo_ch[i].input_handler(&global_fifo_list->fifo_ch[i]);
509  }
510  else FD_SET(global_fifo_list->fifo_ch[i].fd_in, &global_fifo_list->fds); //reset for next time
511  }
512  }
513 
514  return;
515 }
516 
518 {
519  int i;
520 
521  for(i=0;i<fl->nchan; i++)
522  {
523  if(fl->fifo_ch[i].input_handler)
524  {
525  fcntl(fl->fifo_ch[i].fd_in, F_SETSIG, RTSIGIO);
526  }
527  else
528  {
529  fcntl(fl->fifo_ch[i].fd_in, F_SETSIG, RTSIGIGN);
530  }
531  }
532 
533  return 0;
534 }
535 
536 void catch_fifo_pending_reads(int signum __attribute__((unused)), siginfo_t *siginf, void *ucont __attribute__((unused)))
537 {
538  int fd;
539  int idx;
540 
541  //double t = get_curr_time();
542  //First check if this is an input available signal.
543  //This is necessary since we have to open fifos as RW, a
544  //POLL_OUT SIGIO signal will be generated every time we clear one.
545  if(siginf->si_code == POLL_IN)
546  {
548 
549  fd = siginf->si_fd;
551 
553 
554  if(global_fifo_list->read_queue[global_fifo_list->read_queue_nextpos])
555  {
556  ERRMSG("Condition met. RT Signal queue wraparound.");
558  }
559  global_fifo_list->read_queue[global_fifo_list->read_queue_nextpos] = idx;
560 
561  global_fifo_list->read_queue_nextpos++;
562 
563  if(global_fifo_list->read_queue_nextpos >= global_fifo_list->rq_sz) global_fifo_list->read_queue_nextpos = 0;
564  }
565 
566 }
567 
568 void catch_fifo_standard_sigio(int signum __attribute__((unused)))
569 {
570  ERRMSG("Standard SIGIO caught. RT Signal queue overflow.");
571 
573 }
574 
575 
577 {
578  int i, rv;
579 
580  i = fl->read_queue[fl->read_queue_pos];
581 
582  fl->read_queue[fl->read_queue_pos] = 0; //This means it is okay to use this position again
583 
584  fl->tot_pending_reads--;
585 
586  fl->pending_reads[i]--;
587 
588  fl->read_queue_pos++;
589 
590  if(fl->read_queue_pos >= fl->rq_sz) fl->read_queue_pos = 0;
591 
592  //if(i == 4)
593  // printf("fldpr: %.10f\n", get_currt());
594 
595  if(fl->fifo_ch[i].input_handler)
596  {
597  rv = fl->fifo_ch[i].input_handler(&fl->fifo_ch[i]);
598  }
599  else
600  {
601  rv = 0;
602  }
603 
604  return rv;
605 }
606 
607 int ropen_async(char * fname, int nolock)
608 {
609  int fd;
610  errno = 0;
611  char errmsg[ERRMSG_SZ];
612  struct flock fl;
613 
614  errno = 0;
615  fd = open(fname, O_RDWR| O_NONBLOCK);
616  if(fd < 0)
617  {
618  snprintf(errmsg, ERRMSG_SZ, "Error opening fifo %s. Error = %s", fname, strerror(errno));
619  ERRMSG(errmsg);
620  }
621  else
622  {
623  //Have to become owner to set O_ASYNC
624  fcntl(fd, F_SETOWN, getpid());
625  fcntl(fd, F_SETFL, 0);
626  fcntl(fd, F_SETFL, O_ASYNC | O_RDWR | O_NONBLOCK);
627 
628  if(!nolock)
629  {
630  fl.l_type = F_WRLCK; //get an exclusive lock
631  fl.l_whence = SEEK_SET;
632  fl.l_start = 0;
633  fl.l_len = 0;
634  fl.l_pid = getpid();
635  errno = 0;
636  if(fcntl(fd, F_SETLK, &fl) < 0)
637  {
638  snprintf(errmsg, ERRMSG_SZ, "Error getting exclusive lock on %s. Error = %s. Closing file.", fname, strerror(errno));
639  ERRMSG(errmsg);
640  close(fd);
641  fd = -1;
642  }
643  }
644  }
645 
646  return fd;
647 }
648 
649 int wopen_nonblock(char * fname, int nolock)
650 {
651  int fd;
652  char errmsg[ERRMSG_SZ];
653  struct flock fl;
654 
655  errno = 0;
656  fd = open(fname, O_RDWR | O_NONBLOCK);
657  if(fd < 0)
658  {
659  snprintf(errmsg, ERRMSG_SZ, "Error opening fifo %s. Error = %s", fname, strerror(errno));
660  ERRMSG(errmsg);
661  }
662 
663  if(fd >=0 && !nolock)
664  {
665  fl.l_type = F_WRLCK; //get an exclusive lock
666  fl.l_whence = SEEK_SET;
667  fl.l_start = 0;
668  fl.l_len = 0;
669  fl.l_pid = getpid();
670 
671  //fcntl(fd, F_SETOWN, getpid());
672 
673  errno = 0;
674  if(fcntl(fd, F_SETLK, &fl) < 0)
675  {
676  snprintf(errmsg, ERRMSG_SZ, "Error getting exclusive lock on %s. Error = %s. Closing file.", fname, strerror(errno));
677  ERRMSG(errmsg);
678 
679  close(fd);
680  fd = -1;
681  }
682  }
683  return fd;
684 }
685 
int fifo_list_do_pending_read(fifo_list *fl)
Runs through the pending reads, dispatching each handler in turn.
Definition: fifoutils.c:576
int open_fifo_channel_in(fifo_channel *fc)
Opens the input fifo channel for async reading with an exculsive lock.
Definition: fifoutils.c:119
#define ERRMSG_SZ
The size of the errmsg buffers.
Definition: fifoutils.h:48
int check_if_in_locked(fifo_channel *fc)
Checks if the output fifo of the channel is locked.
Definition: fifoutils.c:316
int connect_fifo_list_nolock(fifo_list *fl)
Open each fifo in the list, without exclusive locks.
Definition: fifoutils.c:415
int write_fifo_channel(fifo_channel *fc, const char *com, int comlen)
Write data to the output channel.
Definition: fifoutils.c:194
int setup_fifo_channel(fifo_channel *fc, size_t buffsz)
Allocate the server_response buffer.
Definition: fifoutils.c:47
int nchan
The number of channels.
Definition: fifoutils.h:206
int setup_fifo_list(fifo_list *fl, int nch)
Setup a fifo_list.
Definition: fifoutils.c:354
fifo_list * global_fifo_list
The global fifo_list, for signal handling.
Definition: dioserver.cpp:19
int init_fifo_channel(fifo_channel *fc)
Initializes the fifo_channel structure.
Definition: fifoutils.c:31
fd_set fds
the fd_set for the async SIGIO handler
Definition: fifoutils.h:209
int rq_sz
Size of the read_queue.
Definition: fifoutils.h:218
int read_fifo_channel(fifo_channel *fc)
Read data from the input fifo channel.
Definition: fifoutils.c:246
int * read_queue
Circular buffer which contains the fifo_ch index to read next.
Definition: fifoutils.h:217
int open_fifo_channel_in_nolock(fifo_channel *fc)
Opens the input fifo channel for async reading without an exculsive lock.
Definition: fifoutils.c:144
int set_fifo_channel(fifo_channel *fc, const char *fin, const char *fout, int(*inp_hand)(fifo_channel *), void *adata)
Set the details of the fifo_channel.
Definition: fifoutils.c:63
int write_fifo_channel_seqmsg(fifo_channel *fc, const char *com, int comlen, char *seqmsg)
Write data to the output channel, including a sequence message.
Definition: fifoutils.c:218
#define ERRMSG(msg)
Error reporting macro. If not using the function __error_message(msg) then use stderr.
Definition: fifoutils.h:53
A structure to hold a list of fifo_channels.
Definition: fifoutils.h:204
int wopen_nonblock(char *fname, int nolock)
Open a file for non-blocking writes.
Definition: fifoutils.c:649
int open_fifo_channel_out_nolock(fifo_channel *fc)
Opens the output fifo channel for non-blocking writing without an exclusive lock. ...
Definition: fifoutils.c:180
fifo_channel * fifo_ch
An array of fifo_channels.
Definition: fifoutils.h:207
int open_fifo_channel_out(fifo_channel *fc)
Opens the output fifo channel for non-blocking writing with an exclusive lock.
Definition: fifoutils.c:166
int * pending_reads
An array, with same index as fifo_ch, which tracks number of pending reads on each channel...
Definition: fifoutils.h:216
void catch_fifo_response_list(int signum)
A SIGIO handler, which uses global_fifo_list to call the appropriate handler.
int maxfile
the maximum file descriptor for the SIGIO handler to worry about.
Definition: fifoutils.h:210
int init_fifo_list_pending_reads(fifo_list *fl)
Populates the fd_to_fifo_ch_index array.
Definition: fifoutils.c:454
int ropen_async(char *fname, int nolock)
Open a file for non-blocking asynchronous reads.
Definition: fifoutils.c:607
void catch_fifo_pending_reads(int signum, siginfo_t *siginf, void *ucont)
A handler for a R/T SIGIO, which just updates the pending reads meta data but does no actual signal h...
int RTSIGIO_overflow
flag indicating that the signal queue has overflown.
Definition: fifoutils.h:223
int set_fifo_list_rtsig(fifo_list *fl)
Change from SIGIO to real time signals.
Definition: fifoutils.c:517
int connect_fifo_list(fifo_list *fl)
Open each fifo in the list, with exclusive lock on the input fifo.
Definition: fifoutils.c:379
int init_fifo_list(fifo_list *fl)
Initialize the fifo_list.
Definition: fifoutils.c:341
int create_fifos(fifo_channel *fc)
Creates the fifos if they don't already exist.
Definition: fifoutils.c:92
Declarations for linux fifo utilities.
int * fd_to_fifo_ch_index
Array mapping a file descriptor to an index in the fifo_ch array.
Definition: fifoutils.h:213
void catch_fifo_standard_sigio(int signum)
A handler for normal SIGIO when we should have gotten the R/T SIGIO, implying signal queue overflow...
double get_currt()
Returns time since the Unix epoch in double precision seconds.
Definition: fifoutils.c:23
int read_queue_pos
The current position in the read_queue.
Definition: fifoutils.h:220
int tot_pending_reads
The total number of pending reads.
Definition: fifoutils.h:215
#define RWBUFF_SZ
The size of the i/o buffer.
Definition: fifoutils.h:43
int set_fifo_list_channel(fifo_list *fl, int nch, int buffsz, const char *fin, const char *fout, int(*inp_hand)(fifo_channel *), void *adata)
Set the details of one channel in the list.
Definition: fifoutils.c:373