Rizin
unix-like reverse engineering framework and cli tools
posix-poll.c File Reference
#include "uv.h"
#include "internal.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>

Go to the source code of this file.

Functions

int uv__platform_loop_init (uv_loop_t *loop)
 
void uv__platform_loop_delete (uv_loop_t *loop)
 
int uv__io_fork (uv_loop_t *loop)
 
static void uv__pollfds_maybe_resize (uv_loop_t *loop)
 
static void uv__pollfds_swap (uv_loop_t *loop, size_t l, size_t r)
 
static void uv__pollfds_add (uv_loop_t *loop, uv__io_t *w)
 
static void uv__pollfds_del (uv_loop_t *loop, int fd)
 
void uv__io_poll (uv_loop_t *loop, int timeout)
 
void uv__platform_invalidate_fd (uv_loop_t *loop, int fd)
 
int uv__io_check_fd (uv_loop_t *loop, int fd)
 

Function Documentation

◆ uv__io_check_fd()

int uv__io_check_fd ( uv_loop_t loop,
int  fd 
)

Definition at line 356 of file posix-poll.c.

356  {
357  struct pollfd p[1];
358  int rv;
359 
360  p[0].fd = fd;
361  p[0].events = POLLIN;
362 
363  do
364  rv = poll(p, 1, 0);
365  while (rv == -1 && (errno == EINTR || errno == EAGAIN));
366 
367  if (rv == -1)
368  return UV__ERR(errno);
369 
370  if (p[0].revents & POLLNVAL)
371  return UV_EINVAL;
372 
373  return 0;
374 }
#define UV__ERR(x)
Definition: errno.h:29
void * p
Definition: libc.cpp:67
static const char struct stat static buf struct stat static buf static vhangup int struct rusage static rusage struct sysinfo static info unsigned static __unused struct utsname static buf const char static size const char static name static pid unsigned static persona static fsgid const void static flags const struct iovec static count static fd const void static len static munlockall struct sched_param static p static sched_yield static policy const struct timespec struct timespec static rem uid_t uid_t uid_t static suid poll
Definition: sflib.h:196
#define EINTR
Definition: sftypes.h:114
#define EAGAIN
Definition: sftypes.h:121
Definition: sftypes.h:75
static const z80_opcode fd[]
Definition: z80_tab.h:997

References EAGAIN, EINTR, fd, p, poll, and UV__ERR.

◆ uv__io_fork()

int uv__io_fork ( uv_loop_t loop)

Definition at line 49 of file posix-poll.c.

49  {
52 }
int uv__platform_loop_init(uv_loop_t *loop)
Definition: posix-poll.c:36
void uv__platform_loop_delete(uv_loop_t *loop)
Definition: posix-poll.c:44
uv_loop_t * loop
Definition: main.c:7

References loop, uv__platform_loop_delete(), and uv__platform_loop_init().

◆ uv__io_poll()

void uv__io_poll ( uv_loop_t loop,
int  timeout 
)

Definition at line 134 of file posix-poll.c.

134  {
135  sigset_t* pset;
136  sigset_t set;
137  uint64_t time_base;
138  uint64_t time_diff;
139  QUEUE* q;
140  uv__io_t* w;
141  size_t i;
142  unsigned int nevents;
143  int nfds;
144  int have_signals;
145  struct pollfd* pe;
146  int fd;
147  int user_timeout;
148  int reset_timeout;
149 
150  if (loop->nfds == 0) {
151  assert(QUEUE_EMPTY(&loop->watcher_queue));
152  return;
153  }
154 
155  /* Take queued watchers and add their fds to our poll fds array. */
156  while (!QUEUE_EMPTY(&loop->watcher_queue)) {
157  q = QUEUE_HEAD(&loop->watcher_queue);
158  QUEUE_REMOVE(q);
159  QUEUE_INIT(q);
160 
161  w = QUEUE_DATA(q, uv__io_t, watcher_queue);
162  assert(w->pevents != 0);
163  assert(w->fd >= 0);
164  assert(w->fd < (int) loop->nwatchers);
165 
167 
168  w->events = w->pevents;
169  }
170 
171  /* Prepare a set of signals to block around poll(), if any. */
172  pset = NULL;
173  if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
174  pset = &set;
175  sigemptyset(pset);
176  sigaddset(pset, SIGPROF);
177  }
178 
179  assert(timeout >= -1);
180  time_base = loop->time;
181 
183  reset_timeout = 1;
184  user_timeout = timeout;
185  timeout = 0;
186  } else {
187  reset_timeout = 0;
188  }
189 
190  /* Loop calls to poll() and processing of results. If we get some
191  * results from poll() but they turn out not to be interesting to
192  * our caller then we need to loop around and poll() again.
193  */
194  for (;;) {
195  /* Only need to set the provider_entry_time if timeout != 0. The function
196  * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME.
197  */
198  if (timeout != 0)
200 
201  if (pset != NULL)
202  if (pthread_sigmask(SIG_BLOCK, pset, NULL))
203  abort();
204  nfds = poll(loop->poll_fds, (nfds_t)loop->poll_fds_used, timeout);
205  if (pset != NULL)
206  if (pthread_sigmask(SIG_UNBLOCK, pset, NULL))
207  abort();
208 
209  /* Update loop->time unconditionally. It's tempting to skip the update when
210  * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
211  * operating system didn't reschedule our process while in the syscall.
212  */
213  SAVE_ERRNO(uv__update_time(loop));
214 
215  if (nfds == 0) {
216  if (reset_timeout != 0) {
217  timeout = user_timeout;
218  reset_timeout = 0;
219  if (timeout == -1)
220  continue;
221  if (timeout > 0)
222  goto update_timeout;
223  }
224 
225  assert(timeout != -1);
226  return;
227  }
228 
229  if (nfds == -1) {
230  if (errno != EINTR)
231  abort();
232 
233  if (reset_timeout != 0) {
234  timeout = user_timeout;
235  reset_timeout = 0;
236  }
237 
238  if (timeout == -1)
239  continue;
240 
241  if (timeout == 0)
242  return;
243 
244  /* Interrupted by a signal. Update timeout and poll again. */
245  goto update_timeout;
246  }
247 
248  /* Tell uv__platform_invalidate_fd not to manipulate our array
249  * while we are iterating over it.
250  */
251  loop->poll_fds_iterating = 1;
252 
253  /* Initialize a count of events that we care about. */
254  nevents = 0;
255  have_signals = 0;
256 
257  /* Loop over the entire poll fds array looking for returned events. */
258  for (i = 0; i < loop->poll_fds_used; i++) {
259  pe = loop->poll_fds + i;
260  fd = pe->fd;
261 
262  /* Skip invalidated events, see uv__platform_invalidate_fd. */
263  if (fd == -1)
264  continue;
265 
266  assert(fd >= 0);
267  assert((unsigned) fd < loop->nwatchers);
268 
269  w = loop->watchers[fd];
270 
271  if (w == NULL) {
272  /* File descriptor that we've stopped watching, ignore. */
274  continue;
275  }
276 
277  /* Filter out events that user has not requested us to watch
278  * (e.g. POLLNVAL).
279  */
280  pe->revents &= w->pevents | POLLERR | POLLHUP;
281 
282  if (pe->revents != 0) {
283  /* Run signal watchers last. */
284  if (w == &loop->signal_io_watcher) {
285  have_signals = 1;
286  } else {
288  w->cb(loop, w, pe->revents);
289  }
290 
291  nevents++;
292  }
293  }
294 
295  if (reset_timeout != 0) {
296  timeout = user_timeout;
297  reset_timeout = 0;
298  }
299 
300  if (have_signals != 0) {
302  loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
303  }
304 
305  loop->poll_fds_iterating = 0;
306 
307  /* Purge invalidated fds from our poll fds array. */
308  uv__pollfds_del(loop, -1);
309 
310  if (have_signals != 0)
311  return; /* Event loop should cycle now so don't poll again. */
312 
313  if (nevents != 0)
314  return;
315 
316  if (timeout == 0)
317  return;
318 
319  if (timeout == -1)
320  continue;
321 
322 update_timeout:
323  assert(timeout > 0);
324 
325  time_diff = loop->time - time_base;
326  if (time_diff >= (uint64_t) timeout)
327  return;
328 
329  timeout -= time_diff;
330  }
331 }
lzma_index ** i
Definition: index.h:629
#define NULL
Definition: cris-opc.c:27
#define w
Definition: crypto_rc6.c:13
static const char struct stat static buf struct stat static buf static vhangup int struct rusage static rusage struct sysinfo static info unsigned static __unused struct utsname static buf const char static size const char static name static pid unsigned static persona static fsgid const void static flags const struct iovec static count static fd const void static len static munlockall struct sched_param static p static sched_yield static policy const struct timespec struct timespec static rem uid_t uid_t uid_t static suid struct pollfd unsigned nfds
Definition: sflib.h:196
assert(limit<=UINT32_MAX/2)
static void uv__pollfds_add(uv_loop_t *loop, uv__io_t *w)
Definition: posix-poll.c:86
void uv__platform_invalidate_fd(uv_loop_t *loop, int fd)
Definition: posix-poll.c:336
static void uv__pollfds_del(uv_loop_t *loop, int fd)
Definition: posix-poll.c:107
#define QUEUE_DATA(ptr, type, field)
Definition: queue.h:30
#define QUEUE_EMPTY(q)
Definition: queue.h:39
#define QUEUE_HEAD(q)
Definition: queue.h:42
#define QUEUE_INIT(q)
Definition: queue.h:45
void * QUEUE[2]
Definition: queue.h:21
#define QUEUE_REMOVE(q)
Definition: queue.h:101
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
unsigned long uint64_t
Definition: sftypes.h:28
int sigset_t
Definition: sftypes.h:63
Definition: unix.h:96
uv_timer_t timeout
Definition: main.c:9
@ UV_LOOP_BLOCK_SIGPROF
Definition: internal.h:137
#define SAVE_ERRNO(block)
Definition: internal.h:92
void uv__metrics_update_idle_time(uv_loop_t *loop)
Definition: uv-common.c:872
void uv__metrics_set_provider_entry_time(uv_loop_t *loop)
Definition: uv-common.c:899
#define uv__get_internal_fields(loop)
Definition: uv-common.h:336
@ UV_METRICS_IDLE_TIME
Definition: uv.h:251

References assert(), EINTR, fd, flags, i, loop, nfds, NULL, poll, QUEUE_DATA, QUEUE_EMPTY, QUEUE_HEAD, QUEUE_INIT, QUEUE_REMOVE, SAVE_ERRNO, timeout, uv__get_internal_fields, uv__metrics_set_provider_entry_time(), uv__metrics_update_idle_time(), uv__platform_invalidate_fd(), uv__pollfds_add(), uv__pollfds_del(), UV_LOOP_BLOCK_SIGPROF, UV_METRICS_IDLE_TIME, and w.

◆ uv__platform_invalidate_fd()

void uv__platform_invalidate_fd ( uv_loop_t loop,
int  fd 
)

Definition at line 336 of file posix-poll.c.

336  {
337  size_t i;
338 
339  assert(fd >= 0);
340 
341  if (loop->poll_fds_iterating) {
342  /* uv__io_poll is currently iterating. Just invalidate fd. */
343  for (i = 0; i < loop->poll_fds_used; i++)
344  if (loop->poll_fds[i].fd == fd) {
345  loop->poll_fds[i].fd = -1;
346  loop->poll_fds[i].events = 0;
347  loop->poll_fds[i].revents = 0;
348  }
349  } else {
350  /* uv__io_poll is not iterating. Delete fd from the set. */
352  }
353 }

References assert(), fd, i, loop, and uv__pollfds_del().

Referenced by uv__io_poll().

◆ uv__platform_loop_delete()

void uv__platform_loop_delete ( uv_loop_t loop)

Definition at line 44 of file posix-poll.c.

44  {
45  uv__free(loop->poll_fds);
46  loop->poll_fds = NULL;
47 }
void uv__free(void *ptr)
Definition: uv-common.c:81

References loop, NULL, and uv__free().

Referenced by uv__io_fork().

◆ uv__platform_loop_init()

int uv__platform_loop_init ( uv_loop_t loop)

Definition at line 36 of file posix-poll.c.

36  {
37  loop->poll_fds = NULL;
38  loop->poll_fds_used = 0;
39  loop->poll_fds_size = 0;
40  loop->poll_fds_iterating = 0;
41  return 0;
42 }

References loop, and NULL.

Referenced by uv__io_fork().

◆ uv__pollfds_add()

static void uv__pollfds_add ( uv_loop_t loop,
uv__io_t w 
)
static

Definition at line 86 of file posix-poll.c.

86  {
87  size_t i;
88  struct pollfd* pe;
89 
90  /* If the fd is already in the set just update its events. */
91  assert(!loop->poll_fds_iterating);
92  for (i = 0; i < loop->poll_fds_used; ++i) {
93  if (loop->poll_fds[i].fd == w->fd) {
94  loop->poll_fds[i].events = w->pevents;
95  return;
96  }
97  }
98 
99  /* Otherwise, allocate a new slot in the set for the fd. */
101  pe = &loop->poll_fds[loop->poll_fds_used++];
102  pe->fd = w->fd;
103  pe->events = w->pevents;
104 }
static void uv__pollfds_maybe_resize(uv_loop_t *loop)
Definition: posix-poll.c:55

References assert(), i, loop, uv__pollfds_maybe_resize(), and w.

Referenced by uv__io_poll().

◆ uv__pollfds_del()

static void uv__pollfds_del ( uv_loop_t loop,
int  fd 
)
static

Definition at line 107 of file posix-poll.c.

107  {
108  size_t i;
109  assert(!loop->poll_fds_iterating);
110  for (i = 0; i < loop->poll_fds_used;) {
111  if (loop->poll_fds[i].fd == fd) {
112  /* swap to last position and remove */
113  --loop->poll_fds_used;
114  uv__pollfds_swap(loop, i, loop->poll_fds_used);
115  loop->poll_fds[loop->poll_fds_used].fd = -1;
116  loop->poll_fds[loop->poll_fds_used].events = 0;
117  loop->poll_fds[loop->poll_fds_used].revents = 0;
118  /* This method is called with an fd of -1 to purge the invalidated fds,
119  * so we may possibly have multiples to remove.
120  */
121  if (-1 != fd)
122  return;
123  } else {
124  /* We must only increment the loop counter when the fds do not match.
125  * Otherwise, when we are purging an invalidated fd, the value just
126  * swapped here from the previous end of the array will be skipped.
127  */
128  ++i;
129  }
130  }
131 }
static void uv__pollfds_swap(uv_loop_t *loop, size_t l, size_t r)
Definition: posix-poll.c:78

References assert(), fd, i, loop, and uv__pollfds_swap().

Referenced by uv__io_poll(), and uv__platform_invalidate_fd().

◆ uv__pollfds_maybe_resize()

static void uv__pollfds_maybe_resize ( uv_loop_t loop)
static

Definition at line 55 of file posix-poll.c.

55  {
56  size_t i;
57  size_t n;
58  struct pollfd* p;
59 
60  if (loop->poll_fds_used < loop->poll_fds_size)
61  return;
62 
63  n = loop->poll_fds_size ? loop->poll_fds_size * 2 : 64;
64  p = uv__reallocf(loop->poll_fds, n * sizeof(*loop->poll_fds));
65  if (p == NULL)
66  abort();
67 
68  loop->poll_fds = p;
69  for (i = loop->poll_fds_size; i < n; i++) {
70  loop->poll_fds[i].fd = -1;
71  loop->poll_fds[i].events = 0;
72  loop->poll_fds[i].revents = 0;
73  }
74  loop->poll_fds_size = n;
75 }
int n
Definition: mipsasm.c:19
void * uv__reallocf(void *ptr, size_t size)
Definition: uv-common.c:103

References i, loop, n, NULL, p, and uv__reallocf().

Referenced by uv__pollfds_add().

◆ uv__pollfds_swap()

static void uv__pollfds_swap ( uv_loop_t loop,
size_t  l,
size_t  r 
)
static

Definition at line 78 of file posix-poll.c.

78  {
79  struct pollfd pfd;
80  pfd = loop->poll_fds[l];
81  loop->poll_fds[l] = loop->poll_fds[r];
82  loop->poll_fds[r] = pfd;
83 }
#define r
Definition: crypto_rc6.c:12

References loop, and r.

Referenced by uv__pollfds_del().