29 #include <sys/epoll.h> 35 #define SELECT_POLLIN_SET (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR) 36 #define SELECT_POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR) 37 #define SELECT_POLLEX_SET (POLLPRI) 39 static inline uint32_t events_epoll2poll(uint32_t epoll_event);
41 static int pollfd_cache_prepare(
struct sockets_context *ctx,
struct pollfd *fds,
42 nfds_t nfds, nfds_t num_linuxfds);
46 int tas_select(
int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
51 int fd, fd_r, fd_w, fd_e, ret, t;
54 ctx = flextcp_sockctx_getfull();
56 if (selectfd_cache_alloc(ctx, nfds) != 0) {
61 for (fd = 0; fd < nfds; fd++) {
62 p = &ctx->selectfds_cache[n];
64 fd_r = readfds != NULL && FD_ISSET(fd, readfds);
65 fd_w = writefds != NULL && FD_ISSET(fd, writefds);
66 fd_e = exceptfds != NULL && FD_ISSET(fd, exceptfds);
68 if (fd_r || fd_w || fd_e) {
76 p->events |= SELECT_POLLIN_SET;
78 p->events |= SELECT_POLLOUT_SET;
80 p->events |= SELECT_POLLEX_SET;
83 if (timeout == NULL) {
86 t = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
89 ret = tas_poll(ctx->selectfds_cache, n, t);
94 for (i = 0; i < n; i++) {
95 p = &ctx->selectfds_cache[i];
98 if (readfds != NULL && FD_ISSET(fd, readfds)) {
99 if ((p->revents & SELECT_POLLIN_SET) != 0)
105 if (writefds != NULL && FD_ISSET(fd, writefds)) {
106 if ((p->revents & SELECT_POLLOUT_SET) != 0)
107 FD_SET(fd, writefds);
109 FD_CLR(fd, writefds);
112 if (exceptfds != NULL && FD_ISSET(fd, exceptfds)) {
113 if ((p->revents & SELECT_POLLEX_SET) != 0)
114 FD_SET(fd, exceptfds);
116 FD_CLR(fd, exceptfds);
123 int tas_pselect(
int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
124 const struct timespec *timeout,
const sigset_t *sigmask)
131 int tas_poll(
struct pollfd *fds, nfds_t nfds,
int timeout)
136 nfds_t nfds_linux, nfds_tas, i;
138 int ret, active_fds, mixed_events = 0, j, block_ms;
139 uint64_t mtimeout = 0, cur_ts;
142 ctx = flextcp_sockctx_getfull();
144 if (timeout != 0 && timeout != -1)
145 mtimeout = get_msecs() + timeout;
149 flextcp_sockctx_poll_n(&ctx->ctx, nfds);
151 nfds_linux = nfds_tas = 0;
154 for (i = 0; i < nfds; i++) {
157 if (flextcp_fd_slookup(p->fd, &s) != 0) {
166 flextcp_fd_srelease(p->fd, s);
168 if ((p->events & ~(POLLIN | POLLPRI | POLLOUT | POLLRDHUP | POLLERR |
169 POLLHUP | POLLRDNORM | POLLWRNORM | POLLNVAL | POLLRDBAND |
170 POLLWRBAND | POLLERR)) != 0) {
172 fprintf(stderr,
"tas_pselect: unsupported fd flags (%x)\n", p->events);
176 p->revents = p->events & events_epoll2poll(s_events);
183 if (nfds_tas > 0 && active_fds == 0 && mixed_events == 0 && timeout != 0) {
187 cur_ts = get_msecs();
188 if (cur_ts < mtimeout) {
189 block_ms = mtimeout - cur_ts;
195 if (nfds_linux > 0 && nfds_tas == 0) {
197 return tas_libc_poll(fds, nfds, timeout);
198 }
else if (nfds_linux > 0 && mixed_events == 0) {
205 if (pollfd_cache_prepare(ctx, fds, nfds, nfds_linux) != 0) {
214 ret = tas_libc_poll(ctx->pollfds_cache, nfds_linux, 0);
216 perror(
"tas_poll: mixed poll, linux poll failed");
223 ret = tas_libc_poll(ctx->pollfds_cache, nfds_linux + 1, block_ms);
225 perror(
"tas_poll: mixed poll, linux poll failed");
230 if (ret > 0 && ctx->pollfds_cache[nfds_linux].revents != 0) {
233 mixed_events = ret - 1;
242 }
else if (nfds_tas > 0 && nfds_linux == 0 && block_ms != 0) {
246 }
while (active_fds == 0 && mixed_events == 0 && timeout != 0 &&
247 (timeout == -1 || get_msecs() < mtimeout));
250 if (mixed_events > 0) {
251 for (j = 0, i = 0; i < nfds; i++) {
254 if (flextcp_fd_slookup(p->fd, &s) == 0) {
256 flextcp_fd_srelease(p->fd, s);
260 if (p->fd != ctx->pollfds_cache[j].fd) {
261 fprintf(stderr,
"tas_poll: fds in poll cache changed? something is " 266 p->revents = ctx->pollfds_cache[j].revents;
271 return active_fds + mixed_events;
274 int tas_ppoll(
struct pollfd *fds, nfds_t nfds,
const struct timespec *tmo_p,
275 const sigset_t *sigmask)
282 static inline uint32_t events_epoll2poll(uint32_t epoll_event)
284 uint32_t poll_ev = 0;
286 if ((epoll_event & EPOLLIN) != 0)
287 poll_ev |= POLLIN | POLLRDNORM;
288 if ((epoll_event & EPOLLOUT) != 0)
289 poll_ev |= POLLOUT | POLLWRNORM;
290 if ((epoll_event & EPOLLRDHUP) != 0)
291 poll_ev |= POLLRDHUP;
292 if ((epoll_event & EPOLLPRI) != 0)
294 if ((epoll_event & EPOLLERR) != 0)
296 if ((epoll_event & EPOLLHUP) != 0)
306 size_t size, cnt = ctx->pollfds_cache_size;
321 size = cnt *
sizeof(
struct pollfd);
322 if ((ptr = realloc(ctx->pollfds_cache, size)) == NULL) {
323 perror(
"pollfd_cache_alloc: alloc failed");
327 ctx->pollfds_cache = ptr;
328 ctx->pollfds_cache_size = cnt;
334 static int pollfd_cache_prepare(
struct sockets_context *ctx,
struct pollfd *fds,
335 nfds_t nfds, nfds_t num_linuxfds_confirm)
339 nfds_t i, num_linux = 0;
341 if (pollfd_cache_alloc(ctx, num_linuxfds_confirm + 1) != 0)
345 for (i = 0; i < nfds; i++) {
348 if (flextcp_fd_slookup(p->fd, &s) == 0) {
350 flextcp_fd_srelease(p->fd, s);
354 if (num_linux >= num_linuxfds_confirm) {
355 fprintf(stderr,
"pollfd_cache_prepare: number of linux fds changed?\n");
359 ctx->pollfds_cache[num_linux] = *p;
364 ctx->pollfds_cache[num_linux].events = POLLIN;
365 ctx->pollfds_cache[num_linux].revents= 0;
374 size_t size, cnt = ctx->selectfds_cache_size;
388 size = cnt *
sizeof(
struct pollfd);
389 if ((ptr = realloc(ctx->selectfds_cache, size)) == NULL) {
390 perror(
"selectfd_cache_alloc: alloc failed");
394 ctx->selectfds_cache = ptr;
395 ctx->selectfds_cache_size = cnt;
int flextcp_context_wait(struct flextcp_context *ctx, int timeout_ms)
int flextcp_context_waitfd(struct flextcp_context *ctx)
int flextcp_context_canwait(struct flextcp_context *ctx)
void flextcp_context_waitclear(struct flextcp_context *ctx)