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