Coverage Report

Created: 2023-09-25 06:56

/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;
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, now;
125
126
0
  now = GetTickCount64();
127
0
  if (dwMilliseconds == INFINITE)
128
0
    dueTime = 0xFFFFFFFFFFFFFFFF;
129
0
  else
130
0
    dueTime = now + dwMilliseconds;
131
132
0
#ifdef WINPR_HAVE_POLL_H
133
0
  int timeout;
134
135
0
  do
136
0
  {
137
0
    if (dwMilliseconds == INFINITE)
138
0
      timeout = -1;
139
0
    else
140
0
      timeout = (int)(dueTime - now);
141
142
0
    ret = poll(set->pollset, set->fillIndex, timeout);
143
0
    if (ret >= 0)
144
0
      return ret;
145
146
0
    if (errno != EINTR)
147
0
      return -1;
148
149
0
    now = GetTickCount64();
150
0
  } while (now < dueTime);
151
152
#else
153
  do
154
  {
155
    struct timeval staticTimeout;
156
    struct timeval* timeout;
157
158
    fd_set* rset = NULL;
159
    fd_set* wset = NULL;
160
161
    if (dwMilliseconds == INFINITE)
162
    {
163
      timeout = NULL;
164
    }
165
    else
166
    {
167
      long waitTime = (long)(dueTime - now);
168
169
      timeout = &staticTimeout;
170
      timeout->tv_sec = waitTime / 1000;
171
      timeout->tv_usec = (waitTime % 1000) * 1000;
172
    }
173
174
    if (set->nread)
175
    {
176
      rset = &set->rset;
177
      memcpy(rset, &set->rset_base, sizeof(*rset));
178
    }
179
180
    if (set->nwrite)
181
    {
182
      wset = &set->wset;
183
      memcpy(wset, &set->wset_base, sizeof(*wset));
184
    }
185
186
    ret = select(set->maxFd + 1, rset, wset, NULL, timeout);
187
    if (ret >= 0)
188
      return ret;
189
190
    if (errno != EINTR)
191
      return -1;
192
193
    now = GetTickCount64();
194
195
  } while (now < dueTime);
196
197
  FD_ZERO(&set->rset);
198
  FD_ZERO(&set->wset);
199
#endif
200
201
0
  return 0; /* timeout */
202
0
}
203
204
BOOL pollset_isSignaled(WINPR_POLL_SET* set, size_t idx)
205
0
{
206
0
  WINPR_ASSERT(set);
207
208
0
  if (idx > set->fillIndex)
209
0
  {
210
0
    WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex);
211
0
    return FALSE;
212
0
  }
213
214
0
#ifdef WINPR_HAVE_POLL_H
215
0
  return !!(set->pollset[idx].revents & set->pollset[idx].events);
216
#else
217
  FdIndex* fdIndex = &set->fdIndex[idx];
218
  if (fdIndex->fd < 0)
219
    return FALSE;
220
221
  if ((fdIndex->mode & WINPR_FD_READ) && FD_ISSET(fdIndex->fd, &set->rset))
222
    return TRUE;
223
224
  if ((fdIndex->mode & WINPR_FD_WRITE) && FD_ISSET(fdIndex->fd, &set->wset))
225
    return TRUE;
226
227
  return FALSE;
228
#endif
229
0
}
230
231
BOOL pollset_isReadSignaled(WINPR_POLL_SET* set, size_t idx)
232
0
{
233
0
  WINPR_ASSERT(set);
234
235
0
  if (idx > set->fillIndex)
236
0
  {
237
0
    WLog_ERR(TAG, "index=%d out of pollset(fillIndex=%" PRIuz ")", idx, set->fillIndex);
238
0
    return FALSE;
239
0
  }
240
241
0
#ifdef WINPR_HAVE_POLL_H
242
0
  return !!(set->pollset[idx].revents & POLLIN);
243
#else
244
  FdIndex* fdIndex = &set->fdIndex[idx];
245
  if (fdIndex->fd < 0)
246
    return FALSE;
247
248
  return FD_ISSET(fdIndex->fd, &set->rset);
249
#endif
250
0
}
251
252
BOOL pollset_isWriteSignaled(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 & POLLOUT);
264
#else
265
  FdIndex* fdIndex = &set->fdIndex[idx];
266
  if (fdIndex->fd < 0)
267
    return FALSE;
268
269
  return FD_ISSET(fdIndex->fd, &set->wset);
270
#endif
271
0
}
272
273
#endif