FreeRDP
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
13 static 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 
27 BOOL 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 
61 void 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 
72 void 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 
84 BOOL 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 
120 int 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 
205 BOOL 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 
232 BOOL 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 
253 BOOL 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