Coverage Report

Created: 2025-07-01 06:46

/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