/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 = NULL; |
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 = 0; |
125 | 0 | UINT64 now = 0; |
126 | |
|
127 | 0 | now = GetTickCount64(); |
128 | 0 | if (dwMilliseconds == INFINITE) |
129 | 0 | dueTime = 0xFFFFFFFFFFFFFFFF; |
130 | 0 | else |
131 | 0 | dueTime = now + dwMilliseconds; |
132 | |
|
133 | 0 | #ifdef WINPR_HAVE_POLL_H |
134 | 0 | int timeout = 0; |
135 | |
|
136 | 0 | do |
137 | 0 | { |
138 | 0 | if (dwMilliseconds == INFINITE) |
139 | 0 | timeout = -1; |
140 | 0 | else |
141 | 0 | timeout = (int)(dueTime - now); |
142 | |
|
143 | 0 | ret = poll(set->pollset, set->fillIndex, timeout); |
144 | 0 | if (ret >= 0) |
145 | 0 | return ret; |
146 | | |
147 | 0 | if (errno != EINTR) |
148 | 0 | return -1; |
149 | | |
150 | 0 | now = GetTickCount64(); |
151 | 0 | } 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 | 0 | return 0; /* timeout */ |
203 | 0 | } |
204 | | |
205 | | BOOL pollset_isSignaled(WINPR_POLL_SET* set, size_t idx) |
206 | 0 | { |
207 | 0 | WINPR_ASSERT(set); |
208 | | |
209 | 0 | if (idx > set->fillIndex) |
210 | 0 | { |
211 | 0 | WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex); |
212 | 0 | return FALSE; |
213 | 0 | } |
214 | | |
215 | 0 | #ifdef WINPR_HAVE_POLL_H |
216 | 0 | 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 | 0 | } |
231 | | |
232 | | BOOL pollset_isReadSignaled(WINPR_POLL_SET* set, size_t idx) |
233 | 0 | { |
234 | 0 | WINPR_ASSERT(set); |
235 | | |
236 | 0 | if (idx > set->fillIndex) |
237 | 0 | { |
238 | 0 | WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex); |
239 | 0 | return FALSE; |
240 | 0 | } |
241 | | |
242 | 0 | #ifdef WINPR_HAVE_POLL_H |
243 | 0 | 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 | 0 | } |
252 | | |
253 | | BOOL pollset_isWriteSignaled(WINPR_POLL_SET* set, size_t idx) |
254 | 0 | { |
255 | 0 | WINPR_ASSERT(set); |
256 | | |
257 | 0 | if (idx > set->fillIndex) |
258 | 0 | { |
259 | 0 | WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex); |
260 | 0 | return FALSE; |
261 | 0 | } |
262 | | |
263 | 0 | #ifdef WINPR_HAVE_POLL_H |
264 | 0 | 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 | 0 | } |
273 | | |
274 | | #endif |