blob: 74a5a3a167f62b4535199c6f41feed6e3b061abf [file] [log] [blame]
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001#include "iolooper.h"
2#include "qemu-common.h"
3
4/* An implementation of iolooper.h based on Unix select() */
5#ifdef _WIN32
6# include <winsock2.h>
7#else
8# include <sys/types.h>
9# include <sys/select.h>
10#endif
11
12struct IoLooper {
13 fd_set reads[1];
14 fd_set writes[1];
15 fd_set reads_result[1];
16 fd_set writes_result[1];
17 int max_fd;
18 int max_fd_valid;
19};
20
21IoLooper*
22iolooper_new(void)
23{
24 IoLooper* iol = qemu_malloc(sizeof(*iol));
25 iolooper_reset(iol);
26 return iol;
27}
28
29void
30iolooper_free( IoLooper* iol )
31{
32 qemu_free(iol);
33}
34
35void
36iolooper_reset( IoLooper* iol )
37{
38 FD_ZERO(iol->reads);
39 FD_ZERO(iol->writes);
40 iol->max_fd = -1;
41 iol->max_fd_valid = 1;
42}
43
44static void
45iolooper_add_fd( IoLooper* iol, int fd )
46{
47 if (iol->max_fd_valid && fd > iol->max_fd) {
48 iol->max_fd = fd;
49 }
50}
51
52static void
53iolooper_del_fd( IoLooper* iol, int fd )
54{
55 if (iol->max_fd_valid && fd == iol->max_fd)
56 iol->max_fd_valid = 0;
57}
58
59static int
60iolooper_fd_count( IoLooper* iol )
61{
62 int max_fd = iol->max_fd;
63 int fd;
64
65 if (iol->max_fd_valid)
66 return max_fd + 1;
67
68 /* recompute max fd */
69 for (fd = 0; fd < FD_SETSIZE; fd++) {
70 if (!FD_ISSET(fd, iol->reads) && !FD_ISSET(fd, iol->writes))
71 continue;
72
73 max_fd = fd;
74 }
75 iol->max_fd = max_fd;
76 iol->max_fd_valid = 1;
77
78 return max_fd + 1;
79}
80
81void
82iolooper_add_read( IoLooper* iol, int fd )
83{
84 if (fd >= 0) {
85 iolooper_add_fd(iol, fd);
86 FD_SET(fd, iol->reads);
87 }
88}
89
90void
91iolooper_add_write( IoLooper* iol, int fd )
92{
93 if (fd >= 0) {
94 iolooper_add_fd(iol, fd);
95 FD_SET(fd, iol->writes);
96 }
97}
98
99void
100iolooper_del_read( IoLooper* iol, int fd )
101{
102 if (fd >= 0) {
103 iolooper_del_fd(iol, fd);
104 FD_CLR(fd, iol->reads);
105 }
106}
107
108void
109iolooper_del_write( IoLooper* iol, int fd )
110{
111 if (fd >= 0) {
112 iolooper_del_fd(iol, fd);
113 FD_CLR(fd, iol->reads);
114 }
115}
116
117int
118iolooper_poll( IoLooper* iol )
119{
120 int count = iolooper_fd_count(iol);
121 int ret;
122 fd_set errs;
123
124 if (count == 0)
125 return 0;
126
127 FD_ZERO(&errs);
128
129 do {
130 struct timeval tv;
131
132 tv.tv_sec = tv.tv_usec = 0;
133
134 iol->reads_result[0] = iol->reads[0];
135 iol->writes_result[0] = iol->writes[0];
136
137 ret = select( count, iol->reads_result, iol->writes_result, &errs, &tv);
138 } while (ret < 0 && errno == EINTR);
139
140 return ret;
141}
142
143int
144iolooper_wait( IoLooper* iol, int64_t duration )
145{
146 int count = iolooper_fd_count(iol);
147 int ret;
148 fd_set errs;
149
150 if (count == 0)
151 return 0;
152
153 FD_ZERO(&errs);
154
155 do {
156 iol->reads_result[0] = iol->reads[0];
157 iol->writes_result[0] = iol->writes[0];
158
159 ret = select( count, iol->reads_result, iol->writes_result, &errs, NULL);
160 } while (ret < 0 && errno == EINTR);
161
162 return ret;
163}
164
165
166int
167iolooper_is_read( IoLooper* iol, int fd )
168{
169 return FD_ISSET(fd, iol->reads_result);
170}
171
172int
173iolooper_is_write( IoLooper* iol, int fd )
174{
175 return FD_ISSET(fd, iol->writes_result);
176}