1 /*
2 * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stddef.h>
8 #include <sys/poll.h>
9 #include <sys/select.h>
10 #include <sys/errno.h>
11 #include <sys/param.h>
12
poll(struct pollfd * fds,nfds_t nfds,int timeout)13 int poll(struct pollfd *fds, nfds_t nfds, int timeout)
14 {
15 struct timeval tv = {
16 // timeout is in milliseconds
17 .tv_sec = timeout / 1000,
18 .tv_usec = (timeout % 1000) * 1000,
19 };
20 int max_fd = -1;
21 fd_set readfds;
22 fd_set writefds;
23 fd_set errorfds;
24 struct _reent* r = __getreent();
25 int ret = 0;
26
27 if (fds == NULL) {
28 __errno_r(r) = ENOENT;
29 return -1;
30 }
31
32 FD_ZERO(&readfds);
33 FD_ZERO(&writefds);
34 FD_ZERO(&errorfds);
35
36 for (unsigned int i = 0; i < nfds; ++i) {
37 fds[i].revents = 0;
38
39 if (fds[i].fd < 0) {
40 // revents should remain 0 and events ignored (according to the documentation of poll()).
41 continue;
42 }
43
44 if (fds[i].fd >= FD_SETSIZE) {
45 fds[i].revents |= POLLNVAL;
46 ++ret;
47 continue;
48 }
49
50 if (fds[i].events & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
51 FD_SET(fds[i].fd, &readfds);
52 FD_SET(fds[i].fd, &errorfds);
53 max_fd = MAX(max_fd, fds[i].fd);
54 }
55
56 if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
57 FD_SET(fds[i].fd, &writefds);
58 FD_SET(fds[i].fd, &errorfds);
59 max_fd = MAX(max_fd, fds[i].fd);
60 }
61 }
62
63 const int select_ret = select(max_fd + 1, &readfds, &writefds, &errorfds, timeout < 0 ? NULL: &tv);
64
65 if (select_ret > 0) {
66 ret += select_ret;
67
68 for (unsigned int i = 0; i < nfds; ++i) {
69 if (FD_ISSET(fds[i].fd, &readfds)) {
70 fds[i].revents |= POLLIN;
71 }
72
73 if (FD_ISSET(fds[i].fd, &writefds)) {
74 fds[i].revents |= POLLOUT;
75 }
76
77 if (FD_ISSET(fds[i].fd, &errorfds)) {
78 fds[i].revents |= POLLERR;
79 }
80 }
81 } else {
82 ret = select_ret;
83 // keeping the errno from select()
84 }
85
86 return ret;
87 }
88