/src/FreeRDP/winpr/libwinpr/synch/pollset.c
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef _WIN32 |
2 | | #include <errno.h> |
3 | | |
4 | | #include "pollset.h" |
5 | | #include <winpr/handle.h> |
6 | | #include <winpr/sysinfo.h> |
7 | | #include <winpr/assert.h> |
8 | | #include "../log.h" |
9 | | |
10 | | #define TAG WINPR_TAG("sync.pollset") |
11 | | |
12 | | #ifdef WINPR_HAVE_POLL_H |
13 | | static INT16 handle_mode_to_pollevent(ULONG mode) |
14 | 0 | { |
15 | 0 | INT16 event = 0; |
16 | |
|
17 | 0 | if (mode & WINPR_FD_READ) |
18 | 0 | event |= POLLIN; |
19 | |
|
20 | 0 | if (mode & WINPR_FD_WRITE) |
21 | 0 | event |= POLLOUT; |
22 | |
|
23 | 0 | return event; |
24 | 0 | } |
25 | | #endif |
26 | | |
27 | | BOOL pollset_init(WINPR_POLL_SET* set, size_t nhandles) |
28 | 0 | { |
29 | 0 | WINPR_ASSERT(set); |
30 | 0 | #ifdef WINPR_HAVE_POLL_H |
31 | 0 | if (nhandles > MAXIMUM_WAIT_OBJECTS) |
32 | 0 | { |
33 | 0 | set->isStatic = FALSE; |
34 | 0 | set->pollset = calloc(nhandles, sizeof(*set->pollset)); |
35 | 0 | if (!set->pollset) |
36 | 0 | return FALSE; |
37 | 0 | } |
38 | 0 | else |
39 | 0 | { |
40 | 0 | set->pollset = set->staticSet; |
41 | 0 | set->isStatic = TRUE; |
42 | 0 | } |
43 | | #else |
44 | | set->fdIndex = calloc(nhandles, sizeof(*set->fdIndex)); |
45 | | if (!set->fdIndex) |
46 | | return FALSE; |
47 | | |
48 | | FD_ZERO(&set->rset_base); |
49 | | FD_ZERO(&set->rset); |
50 | | FD_ZERO(&set->wset_base); |
51 | | FD_ZERO(&set->wset); |
52 | | set->maxFd = 0; |
53 | | set->nread = set->nwrite = 0; |
54 | | #endif |
55 | | |
56 | 0 | set->size = nhandles; |
57 | 0 | set->fillIndex = 0; |
58 | 0 | return TRUE; |
59 | 0 | } |
60 | | |
61 | | void pollset_uninit(WINPR_POLL_SET* set) |
62 | 0 | { |
63 | 0 | WINPR_ASSERT(set); |
64 | 0 | #ifdef WINPR_HAVE_POLL_H |
65 | 0 | if (!set->isStatic) |
66 | 0 | free(set->pollset); |
67 | | #else |
68 | | free(set->fdIndex); |
69 | | #endif |
70 | 0 | } |
71 | | |
72 | | void pollset_reset(WINPR_POLL_SET* set) |
73 | 0 | { |
74 | 0 | WINPR_ASSERT(set); |
75 | | #ifndef WINPR_HAVE_POLL_H |
76 | | FD_ZERO(&set->rset_base); |
77 | | FD_ZERO(&set->wset_base); |
78 | | set->maxFd = 0; |
79 | | set->nread = set->nwrite = 0; |
80 | | #endif |
81 | 0 | set->fillIndex = 0; |
82 | 0 | } |
83 | | |
84 | | BOOL pollset_add(WINPR_POLL_SET* set, int fd, ULONG mode) |
85 | 0 | { |
86 | 0 | WINPR_ASSERT(set); |
87 | 0 | #ifdef WINPR_HAVE_POLL_H |
88 | 0 | struct pollfd* item; |
89 | 0 | if (set->fillIndex == set->size) |
90 | 0 | return FALSE; |
91 | | |
92 | 0 | item = &set->pollset[set->fillIndex]; |
93 | 0 | item->fd = fd; |
94 | 0 | item->revents = 0; |
95 | 0 | item->events = handle_mode_to_pollevent(mode); |
96 | | #else |
97 | | FdIndex* fdIndex = &set->fdIndex[set->fillIndex]; |
98 | | if (mode & WINPR_FD_READ) |
99 | | { |
100 | | FD_SET(fd, &set->rset_base); |
101 | | set->nread++; |
102 | | } |
103 | | |
104 | | if (mode & WINPR_FD_WRITE) |
105 | | { |
106 | | FD_SET(fd, &set->wset_base); |
107 | | set->nwrite++; |
108 | | } |
109 | | |
110 | | if (fd > set->maxFd) |
111 | | set->maxFd = fd; |
112 | | |
113 | | fdIndex->fd = fd; |
114 | | fdIndex->mode = mode; |
115 | | #endif |
116 | 0 | set->fillIndex++; |
117 | 0 | return TRUE; |
118 | 0 | } |
119 | | |
120 | | int pollset_poll(WINPR_POLL_SET* set, DWORD dwMilliseconds) |
121 | 0 | { |
122 | 0 | WINPR_ASSERT(set); |
123 | 0 | int ret = 0; |
124 | 0 | UINT64 dueTime, now; |
125 | |
|
126 | 0 | now = GetTickCount64(); |
127 | 0 | if (dwMilliseconds == INFINITE) |
128 | 0 | dueTime = 0xFFFFFFFFFFFFFFFF; |
129 | 0 | else |
130 | 0 | dueTime = now + dwMilliseconds; |
131 | |
|
132 | 0 | #ifdef WINPR_HAVE_POLL_H |
133 | 0 | int timeout; |
134 | |
|
135 | 0 | do |
136 | 0 | { |
137 | 0 | if (dwMilliseconds == INFINITE) |
138 | 0 | timeout = -1; |
139 | 0 | else |
140 | 0 | timeout = (int)(dueTime - now); |
141 | |
|
142 | 0 | ret = poll(set->pollset, set->fillIndex, timeout); |
143 | 0 | if (ret >= 0) |
144 | 0 | return ret; |
145 | | |
146 | 0 | if (errno != EINTR) |
147 | 0 | return -1; |
148 | | |
149 | 0 | now = GetTickCount64(); |
150 | 0 | } while (now < dueTime); |
151 | | |
152 | | #else |
153 | | do |
154 | | { |
155 | | struct timeval staticTimeout; |
156 | | struct timeval* timeout; |
157 | | |
158 | | fd_set* rset = NULL; |
159 | | fd_set* wset = NULL; |
160 | | |
161 | | if (dwMilliseconds == INFINITE) |
162 | | { |
163 | | timeout = NULL; |
164 | | } |
165 | | else |
166 | | { |
167 | | long waitTime = (long)(dueTime - now); |
168 | | |
169 | | timeout = &staticTimeout; |
170 | | timeout->tv_sec = waitTime / 1000; |
171 | | timeout->tv_usec = (waitTime % 1000) * 1000; |
172 | | } |
173 | | |
174 | | if (set->nread) |
175 | | { |
176 | | rset = &set->rset; |
177 | | memcpy(rset, &set->rset_base, sizeof(*rset)); |
178 | | } |
179 | | |
180 | | if (set->nwrite) |
181 | | { |
182 | | wset = &set->wset; |
183 | | memcpy(wset, &set->wset_base, sizeof(*wset)); |
184 | | } |
185 | | |
186 | | ret = select(set->maxFd + 1, rset, wset, NULL, timeout); |
187 | | if (ret >= 0) |
188 | | return ret; |
189 | | |
190 | | if (errno != EINTR) |
191 | | return -1; |
192 | | |
193 | | now = GetTickCount64(); |
194 | | |
195 | | } while (now < dueTime); |
196 | | |
197 | | FD_ZERO(&set->rset); |
198 | | FD_ZERO(&set->wset); |
199 | | #endif |
200 | | |
201 | 0 | return 0; /* timeout */ |
202 | 0 | } |
203 | | |
204 | | BOOL pollset_isSignaled(WINPR_POLL_SET* set, size_t idx) |
205 | 0 | { |
206 | 0 | WINPR_ASSERT(set); |
207 | | |
208 | 0 | if (idx > set->fillIndex) |
209 | 0 | { |
210 | 0 | WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex); |
211 | 0 | return FALSE; |
212 | 0 | } |
213 | | |
214 | 0 | #ifdef WINPR_HAVE_POLL_H |
215 | 0 | return !!(set->pollset[idx].revents & set->pollset[idx].events); |
216 | | #else |
217 | | FdIndex* fdIndex = &set->fdIndex[idx]; |
218 | | if (fdIndex->fd < 0) |
219 | | return FALSE; |
220 | | |
221 | | if ((fdIndex->mode & WINPR_FD_READ) && FD_ISSET(fdIndex->fd, &set->rset)) |
222 | | return TRUE; |
223 | | |
224 | | if ((fdIndex->mode & WINPR_FD_WRITE) && FD_ISSET(fdIndex->fd, &set->wset)) |
225 | | return TRUE; |
226 | | |
227 | | return FALSE; |
228 | | #endif |
229 | 0 | } |
230 | | |
231 | | BOOL pollset_isReadSignaled(WINPR_POLL_SET* set, size_t idx) |
232 | 0 | { |
233 | 0 | WINPR_ASSERT(set); |
234 | | |
235 | 0 | if (idx > set->fillIndex) |
236 | 0 | { |
237 | 0 | WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex); |
238 | 0 | return FALSE; |
239 | 0 | } |
240 | | |
241 | 0 | #ifdef WINPR_HAVE_POLL_H |
242 | 0 | return !!(set->pollset[idx].revents & POLLIN); |
243 | | #else |
244 | | FdIndex* fdIndex = &set->fdIndex[idx]; |
245 | | if (fdIndex->fd < 0) |
246 | | return FALSE; |
247 | | |
248 | | return FD_ISSET(fdIndex->fd, &set->rset); |
249 | | #endif |
250 | 0 | } |
251 | | |
252 | | BOOL pollset_isWriteSignaled(WINPR_POLL_SET* set, size_t idx) |
253 | 0 | { |
254 | 0 | WINPR_ASSERT(set); |
255 | | |
256 | 0 | if (idx > set->fillIndex) |
257 | 0 | { |
258 | 0 | WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex); |
259 | 0 | return FALSE; |
260 | 0 | } |
261 | | |
262 | 0 | #ifdef WINPR_HAVE_POLL_H |
263 | 0 | return !!(set->pollset[idx].revents & POLLOUT); |
264 | | #else |
265 | | FdIndex* fdIndex = &set->fdIndex[idx]; |
266 | | if (fdIndex->fd < 0) |
267 | | return FALSE; |
268 | | |
269 | | return FD_ISSET(fdIndex->fd, &set->wset); |
270 | | #endif |
271 | 0 | } |
272 | | |
273 | | #endif |