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