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