/src/FreeRDP/winpr/libwinpr/synch/pollset.c
Line | Count | Source |
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 |
17 | | static INT16 handle_mode_to_pollevent(ULONG mode) |
18 | 70.7k | { |
19 | 70.7k | INT16 event = 0; |
20 | | |
21 | 70.7k | if (mode & WINPR_FD_READ) |
22 | 70.7k | event |= POLLIN; |
23 | | |
24 | 70.7k | if (mode & WINPR_FD_WRITE) |
25 | 0 | event |= POLLOUT; |
26 | | |
27 | 70.7k | return event; |
28 | 70.7k | } |
29 | | #endif |
30 | | |
31 | | BOOL pollset_init(WINPR_POLL_SET* set, size_t nhandles) |
32 | 53.0k | { |
33 | 53.0k | WINPR_ASSERT(set); |
34 | 53.0k | #ifdef WINPR_HAVE_POLL_H |
35 | 53.0k | if (nhandles > MAXIMUM_WAIT_OBJECTS) |
36 | 0 | { |
37 | 0 | set->isStatic = FALSE; |
38 | 0 | set->pollset = calloc(nhandles, sizeof(*set->pollset)); |
39 | 0 | if (!set->pollset) |
40 | 0 | return FALSE; |
41 | 0 | } |
42 | 53.0k | else |
43 | 53.0k | { |
44 | 53.0k | set->pollset = set->staticSet; |
45 | 53.0k | set->isStatic = TRUE; |
46 | 53.0k | } |
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 | 53.0k | set->size = nhandles; |
61 | 53.0k | set->fillIndex = 0; |
62 | 53.0k | return TRUE; |
63 | 53.0k | } |
64 | | |
65 | | void pollset_uninit(WINPR_POLL_SET* set) |
66 | 53.0k | { |
67 | 53.0k | WINPR_ASSERT(set); |
68 | 53.0k | #ifdef WINPR_HAVE_POLL_H |
69 | 53.0k | if (!set->isStatic) |
70 | 0 | free(set->pollset); |
71 | | #else |
72 | | free(set->fdIndex); |
73 | | #endif |
74 | 53.0k | } |
75 | | |
76 | | void pollset_reset(WINPR_POLL_SET* set) |
77 | 0 | { |
78 | 0 | 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 | 0 | set->fillIndex = 0; |
86 | 0 | } |
87 | | |
88 | | BOOL pollset_add(WINPR_POLL_SET* set, int fd, ULONG mode) |
89 | 70.7k | { |
90 | 70.7k | WINPR_ASSERT(set); |
91 | 70.7k | #ifdef WINPR_HAVE_POLL_H |
92 | 70.7k | struct pollfd* item = NULL; |
93 | 70.7k | if (set->fillIndex == set->size) |
94 | 0 | return FALSE; |
95 | | |
96 | 70.7k | item = &set->pollset[set->fillIndex]; |
97 | 70.7k | item->fd = fd; |
98 | 70.7k | item->revents = 0; |
99 | 70.7k | 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 | 70.7k | set->fillIndex++; |
121 | 70.7k | return TRUE; |
122 | 70.7k | } |
123 | | |
124 | | int pollset_poll(WINPR_POLL_SET* set, DWORD dwMilliseconds) |
125 | 53.0k | { |
126 | 53.0k | WINPR_ASSERT(set); |
127 | 53.0k | int ret = 0; |
128 | 53.0k | UINT64 dueTime = 0; |
129 | 53.0k | UINT64 now = 0; |
130 | | |
131 | 53.0k | now = GetTickCount64(); |
132 | 53.0k | if (dwMilliseconds == INFINITE) |
133 | 35.3k | dueTime = 0xFFFFFFFFFFFFFFFF; |
134 | 17.7k | else |
135 | 17.7k | dueTime = now + dwMilliseconds; |
136 | | |
137 | 53.0k | #ifdef WINPR_HAVE_POLL_H |
138 | 53.0k | int timeout = 0; |
139 | | |
140 | 53.0k | do |
141 | 53.0k | { |
142 | 53.0k | if (dwMilliseconds == INFINITE) |
143 | 35.3k | timeout = -1; |
144 | 17.7k | else |
145 | 17.7k | timeout = (int)(dueTime - now); |
146 | | |
147 | 53.0k | ret = poll(set->pollset, set->fillIndex, timeout); |
148 | 53.0k | if (ret >= 0) |
149 | 53.0k | { |
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 | 53.0k | return ret; |
165 | 53.0k | } |
166 | | |
167 | 0 | if (errno != EINTR) |
168 | 0 | return -1; |
169 | | |
170 | 0 | now = GetTickCount64(); |
171 | 0 | } 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 | 0 | return 0; /* timeout */ |
223 | 53.0k | } |
224 | | |
225 | | BOOL pollset_isSignaled(WINPR_POLL_SET* set, size_t idx) |
226 | 69.6k | { |
227 | 69.6k | WINPR_ASSERT(set); |
228 | | |
229 | 69.6k | if (idx > set->fillIndex) |
230 | 0 | { |
231 | 0 | WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex); |
232 | 0 | return FALSE; |
233 | 0 | } |
234 | | |
235 | 69.6k | #ifdef WINPR_HAVE_POLL_H |
236 | 69.6k | 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 | 69.6k | } |
251 | | |
252 | | BOOL pollset_isReadSignaled(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 & 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 | 0 | } |
272 | | |
273 | | BOOL pollset_isWriteSignaled(WINPR_POLL_SET* set, size_t idx) |
274 | 0 | { |
275 | 0 | WINPR_ASSERT(set); |
276 | | |
277 | 0 | if (idx > set->fillIndex) |
278 | 0 | { |
279 | 0 | WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex); |
280 | 0 | return FALSE; |
281 | 0 | } |
282 | | |
283 | 0 | #ifdef WINPR_HAVE_POLL_H |
284 | 0 | 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 | 0 | } |
293 | | |
294 | | #endif |