1 // Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <stddef.h>
16 #include <sys/poll.h>
17 #include <sys/select.h>
18 #include <sys/errno.h>
19 #include <sys/param.h>
20
poll(struct pollfd * fds,nfds_t nfds,int timeout)21 int poll(struct pollfd *fds, nfds_t nfds, int timeout)
22 {
23 struct timeval tv = {
24 // timeout is in milliseconds
25 .tv_sec = timeout / 1000,
26 .tv_usec = (timeout % 1000) * 1000,
27 };
28 int max_fd = -1;
29 fd_set readfds;
30 fd_set writefds;
31 fd_set errorfds;
32 struct _reent* r = __getreent();
33 int ret = 0;
34
35 if (fds == NULL) {
36 __errno_r(r) = ENOENT;
37 return -1;
38 }
39
40 FD_ZERO(&readfds);
41 FD_ZERO(&writefds);
42 FD_ZERO(&errorfds);
43
44 for (unsigned int i = 0; i < nfds; ++i) {
45 fds[i].revents = 0;
46
47 if (fds[i].fd < 0) {
48 // revents should remain 0 and events ignored (according to the documentation of poll()).
49 continue;
50 }
51
52 if (fds[i].fd >= FD_SETSIZE) {
53 fds[i].revents |= POLLNVAL;
54 ++ret;
55 continue;
56 }
57
58 if (fds[i].events & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
59 FD_SET(fds[i].fd, &readfds);
60 FD_SET(fds[i].fd, &errorfds);
61 max_fd = MAX(max_fd, fds[i].fd);
62 }
63
64 if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
65 FD_SET(fds[i].fd, &writefds);
66 FD_SET(fds[i].fd, &errorfds);
67 max_fd = MAX(max_fd, fds[i].fd);
68 }
69 }
70
71 const int select_ret = select(max_fd + 1, &readfds, &writefds, &errorfds, timeout < 0 ? NULL: &tv);
72
73 if (select_ret > 0) {
74 ret += select_ret;
75
76 for (unsigned int i = 0; i < nfds; ++i) {
77 if (FD_ISSET(fds[i].fd, &readfds)) {
78 fds[i].revents |= POLLIN;
79 }
80
81 if (FD_ISSET(fds[i].fd, &writefds)) {
82 fds[i].revents |= POLLOUT;
83 }
84
85 if (FD_ISSET(fds[i].fd, &errorfds)) {
86 fds[i].revents |= POLLERR;
87 }
88 }
89 } else {
90 ret = select_ret;
91 // keeping the errno from select()
92 }
93
94 return ret;
95 }
96