FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
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#define TAG WINPR_TAG("sync.pollset")
11
12#ifdef WINPR_HAVE_POLL_H
13static INT16 handle_mode_to_pollevent(ULONG mode)
14{
15 INT16 event = 0;
16
17 if (mode & WINPR_FD_READ)
18 event |= POLLIN;
19
20 if (mode & WINPR_FD_WRITE)
21 event |= POLLOUT;
22
23 return event;
24}
25#endif
26
27BOOL pollset_init(WINPR_POLL_SET* set, size_t nhandles)
28{
29 WINPR_ASSERT(set);
30#ifdef WINPR_HAVE_POLL_H
31 if (nhandles > MAXIMUM_WAIT_OBJECTS)
32 {
33 set->isStatic = FALSE;
34 set->pollset = calloc(nhandles, sizeof(*set->pollset));
35 if (!set->pollset)
36 return FALSE;
37 }
38 else
39 {
40 set->pollset = set->staticSet;
41 set->isStatic = TRUE;
42 }
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 set->size = nhandles;
57 set->fillIndex = 0;
58 return TRUE;
59}
60
61void pollset_uninit(WINPR_POLL_SET* set)
62{
63 WINPR_ASSERT(set);
64#ifdef WINPR_HAVE_POLL_H
65 if (!set->isStatic)
66 free(set->pollset);
67#else
68 free(set->fdIndex);
69#endif
70}
71
72void pollset_reset(WINPR_POLL_SET* set)
73{
74 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 set->fillIndex = 0;
82}
83
84BOOL pollset_add(WINPR_POLL_SET* set, int fd, ULONG mode)
85{
86 WINPR_ASSERT(set);
87#ifdef WINPR_HAVE_POLL_H
88 struct pollfd* item = NULL;
89 if (set->fillIndex == set->size)
90 return FALSE;
91
92 item = &set->pollset[set->fillIndex];
93 item->fd = fd;
94 item->revents = 0;
95 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 set->fillIndex++;
117 return TRUE;
118}
119
120int pollset_poll(WINPR_POLL_SET* set, DWORD dwMilliseconds)
121{
122 WINPR_ASSERT(set);
123 int ret = 0;
124 UINT64 dueTime = 0;
125 UINT64 now = 0;
126
127 now = GetTickCount64();
128 if (dwMilliseconds == INFINITE)
129 dueTime = 0xFFFFFFFFFFFFFFFF;
130 else
131 dueTime = now + dwMilliseconds;
132
133#ifdef WINPR_HAVE_POLL_H
134 int timeout = 0;
135
136 do
137 {
138 if (dwMilliseconds == INFINITE)
139 timeout = -1;
140 else
141 timeout = (int)(dueTime - now);
142
143 ret = poll(set->pollset, set->fillIndex, timeout);
144 if (ret >= 0)
145 return ret;
146
147 if (errno != EINTR)
148 return -1;
149
150 now = GetTickCount64();
151 } while (now < dueTime);
152
153#else
154 do
155 {
156 struct timeval staticTimeout;
157 struct timeval* timeout;
158
159 fd_set* rset = NULL;
160 fd_set* wset = NULL;
161
162 if (dwMilliseconds == INFINITE)
163 {
164 timeout = NULL;
165 }
166 else
167 {
168 long waitTime = (long)(dueTime - now);
169
170 timeout = &staticTimeout;
171 timeout->tv_sec = waitTime / 1000;
172 timeout->tv_usec = (waitTime % 1000) * 1000;
173 }
174
175 if (set->nread)
176 {
177 rset = &set->rset;
178 memcpy(rset, &set->rset_base, sizeof(*rset));
179 }
180
181 if (set->nwrite)
182 {
183 wset = &set->wset;
184 memcpy(wset, &set->wset_base, sizeof(*wset));
185 }
186
187 ret = select(set->maxFd + 1, rset, wset, NULL, timeout);
188 if (ret >= 0)
189 return ret;
190
191 if (errno != EINTR)
192 return -1;
193
194 now = GetTickCount64();
195
196 } while (now < dueTime);
197
198 FD_ZERO(&set->rset);
199 FD_ZERO(&set->wset);
200#endif
201
202 return 0; /* timeout */
203}
204
205BOOL pollset_isSignaled(WINPR_POLL_SET* set, size_t idx)
206{
207 WINPR_ASSERT(set);
208
209 if (idx > set->fillIndex)
210 {
211 WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex);
212 return FALSE;
213 }
214
215#ifdef WINPR_HAVE_POLL_H
216 return !!(set->pollset[idx].revents & set->pollset[idx].events);
217#else
218 FdIndex* fdIndex = &set->fdIndex[idx];
219 if (fdIndex->fd < 0)
220 return FALSE;
221
222 if ((fdIndex->mode & WINPR_FD_READ) && FD_ISSET(fdIndex->fd, &set->rset))
223 return TRUE;
224
225 if ((fdIndex->mode & WINPR_FD_WRITE) && FD_ISSET(fdIndex->fd, &set->wset))
226 return TRUE;
227
228 return FALSE;
229#endif
230}
231
232BOOL pollset_isReadSignaled(WINPR_POLL_SET* set, size_t idx)
233{
234 WINPR_ASSERT(set);
235
236 if (idx > set->fillIndex)
237 {
238 WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex);
239 return FALSE;
240 }
241
242#ifdef WINPR_HAVE_POLL_H
243 return !!(set->pollset[idx].revents & POLLIN);
244#else
245 FdIndex* fdIndex = &set->fdIndex[idx];
246 if (fdIndex->fd < 0)
247 return FALSE;
248
249 return FD_ISSET(fdIndex->fd, &set->rset);
250#endif
251}
252
253BOOL pollset_isWriteSignaled(WINPR_POLL_SET* set, size_t idx)
254{
255 WINPR_ASSERT(set);
256
257 if (idx > set->fillIndex)
258 {
259 WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex);
260 return FALSE;
261 }
262
263#ifdef WINPR_HAVE_POLL_H
264 return !!(set->pollset[idx].revents & POLLOUT);
265#else
266 FdIndex* fdIndex = &set->fdIndex[idx];
267 if (fdIndex->fd < 0)
268 return FALSE;
269
270 return FD_ISSET(fdIndex->fd, &set->wset);
271#endif
272}
273
274#endif