1 /* Public domain. */
2 
3 #include "taia.h"
4 #include "select.h"
5 #include "iopause.h"
6 
iopause(iopause_fd * x,unsigned int len,struct taia * deadline,struct taia * stamp)7 void iopause(iopause_fd *x,unsigned int len,struct taia *deadline,struct taia *stamp)
8 {
9   struct taia t;
10   int millisecs;
11   double d;
12   int i;
13 
14   if (taia_less(deadline,stamp))
15     millisecs = 0;
16   else {
17     t = *stamp;
18     taia_sub(&t,deadline,&t);
19     d = taia_approx(&t);
20     if (d > 1000.0) d = 1000.0;
21     millisecs = d * 1000.0 + 20.0;
22   }
23 
24   for (i = 0;i < len;++i)
25     x[i].revents = 0;
26 
27 #ifdef IOPAUSE_POLL
28 
29   poll(x,len,millisecs);
30   /* XXX: some kernels apparently need x[0] even if len is 0 */
31   /* XXX: how to handle EAGAIN? are kernels really this dumb? */
32   /* XXX: how to handle EINVAL? when exactly can this happen? */
33 
34 #else
35 {
36 
37   struct timeval tv;
38   fd_set rfds;
39   fd_set wfds;
40   int nfds;
41   int fd;
42 
43   FD_ZERO(&rfds);
44   FD_ZERO(&wfds);
45 
46   nfds = 1;
47   for (i = 0;i < len;++i) {
48     fd = x[i].fd;
49     if (fd < 0) continue;
50     if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/
51 
52     if (fd >= nfds) nfds = fd + 1;
53     if (x[i].events & IOPAUSE_READ) FD_SET(fd,&rfds);
54     if (x[i].events & IOPAUSE_WRITE) FD_SET(fd,&wfds);
55   }
56 
57   tv.tv_sec = millisecs / 1000;
58   tv.tv_usec = 1000 * (millisecs % 1000);
59 
60   if (select(nfds,&rfds,&wfds,(fd_set *) 0,&tv) <= 0)
61     return;
62     /* XXX: for EBADF, could seek out and destroy the bad descriptor */
63 
64   for (i = 0;i < len;++i) {
65     fd = x[i].fd;
66     if (fd < 0) continue;
67     if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/
68 
69     if (x[i].events & IOPAUSE_READ)
70       if (FD_ISSET(fd,&rfds)) x[i].revents |= IOPAUSE_READ;
71     if (x[i].events & IOPAUSE_WRITE)
72       if (FD_ISSET(fd,&wfds)) x[i].revents |= IOPAUSE_WRITE;
73   }
74 
75 }
76 #endif
77 
78 }
79