1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2016-12-28 Bernard first version
9 */
10 #include <dfs.h>
11 #include <dfs_fs.h>
12 #include <dfs_posix.h>
13
14 #include <dfs_poll.h>
15 #include <dfs_select.h>
16
fdszero(fd_set * set,int nfds)17 static void fdszero(fd_set *set, int nfds)
18 {
19 fd_mask *m;
20 int n;
21
22 /*
23 The 'sizeof(fd_set)' of the system space may differ from user space,
24 so the actual size of the 'fd_set' is determined here with the parameter 'nfds'
25 */
26 m = (fd_mask*)set;
27 for (n = 0; n < nfds; n += (sizeof(fd_mask) * 8))
28 {
29 rt_memset(m, 0, sizeof(fd_mask));
30 m ++;
31 }
32 }
33
select(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout)34 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
35 {
36 int fd;
37 int npfds;
38 int msec;
39 int ndx;
40 int ret;
41 struct pollfd *pollset = RT_NULL;
42
43 /* How many pollfd structures do we need to allocate? */
44 for (fd = 0, npfds = 0; fd < nfds; fd++)
45 {
46 /* Check if any monitor operation is requested on this fd */
47 if ((readfds && FD_ISSET(fd, readfds)) ||
48 (writefds && FD_ISSET(fd, writefds)) ||
49 (exceptfds && FD_ISSET(fd, exceptfds)))
50 {
51 npfds++;
52 }
53 }
54
55 /* Allocate the descriptor list for poll() */
56 if (npfds > 0)
57 {
58 pollset = (struct pollfd *)rt_calloc(npfds, sizeof(struct pollfd));
59 if (!pollset)
60 {
61 return -1;
62 }
63 }
64
65 /* Initialize the descriptor list for poll() */
66 for (fd = 0, ndx = 0; fd < nfds; fd++)
67 {
68 int incr = 0;
69
70 /* The readfs set holds the set of FDs that the caller can be assured
71 * of reading from without blocking. Note that POLLHUP is included as
72 * a read-able condition. POLLHUP will be reported at the end-of-file
73 * or when a connection is lost. In either case, the read() can then
74 * be performed without blocking.
75 */
76
77 if (readfds && FD_ISSET(fd, readfds))
78 {
79 pollset[ndx].fd = fd;
80 pollset[ndx].events |= POLLIN;
81 incr = 1;
82 }
83
84 if (writefds && FD_ISSET(fd, writefds))
85 {
86 pollset[ndx].fd = fd;
87 pollset[ndx].events |= POLLOUT;
88 incr = 1;
89 }
90
91 if (exceptfds && FD_ISSET(fd, exceptfds))
92 {
93 pollset[ndx].fd = fd;
94 incr = 1;
95 }
96
97 ndx += incr;
98 }
99
100 RT_ASSERT(ndx == npfds);
101
102 /* Convert the timeout to milliseconds */
103 if (timeout)
104 {
105 msec = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
106 }
107 else
108 {
109 msec = -1;
110 }
111
112 /* Then let poll do all of the real work. */
113
114 ret = poll(pollset, npfds, msec);
115
116 /* Now set up the return values */
117 if (readfds)
118 {
119 fdszero(readfds, nfds);
120 }
121
122 if (writefds)
123 {
124 fdszero(writefds, nfds);
125 }
126
127 if (exceptfds)
128 {
129 fdszero(exceptfds, nfds);
130 }
131
132 /* Convert the poll descriptor list back into selects 3 bitsets */
133
134 if (ret > 0)
135 {
136 ret = 0;
137 for (ndx = 0; ndx < npfds; ndx++)
138 {
139 /* Check for read conditions. Note that POLLHUP is included as a
140 * read condition. POLLHUP will be reported when no more data will
141 * be available (such as when a connection is lost). In either
142 * case, the read() can then be performed without blocking.
143 */
144
145 if (readfds)
146 {
147 if (pollset[ndx].revents & (POLLIN | POLLHUP))
148 {
149 FD_SET(pollset[ndx].fd, readfds);
150 ret++;
151 }
152 }
153
154 /* Check for write conditions */
155 if (writefds)
156 {
157 if (pollset[ndx].revents & POLLOUT)
158 {
159 FD_SET(pollset[ndx].fd, writefds);
160 ret++;
161 }
162 }
163
164 /* Check for exceptions */
165 if (exceptfds)
166 {
167 if (pollset[ndx].revents & POLLERR)
168 {
169 FD_SET(pollset[ndx].fd, exceptfds);
170 ret++;
171 }
172 }
173 }
174 }
175
176 if (pollset) rt_free(pollset);
177
178 return ret;
179 }
180
181