| /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ | |
| #include "../nolibc.h" | |
| #ifndef _NOLIBC_SYS_SELECT_H | |
| #define _NOLIBC_SYS_SELECT_H | |
| #include <linux/time.h> | |
| #include <linux/unistd.h> | |
| /* commonly an fd_set represents 256 FDs */ | |
| #ifndef FD_SETSIZE | |
| #define FD_SETSIZE 256 | |
| #endif | |
| #define FD_SETIDXMASK (8 * sizeof(unsigned long)) | |
| #define FD_SETBITMASK (8 * sizeof(unsigned long)-1) | |
| /* for select() */ | |
| typedef struct { | |
| unsigned long fds[(FD_SETSIZE + FD_SETBITMASK) / FD_SETIDXMASK]; | |
| } fd_set; | |
| #define FD_CLR(fd, set) do { \ | |
| fd_set *__set = (set); \ | |
| int __fd = (fd); \ | |
| if (__fd >= 0) \ | |
| __set->fds[__fd / FD_SETIDXMASK] &= \ | |
| ~(1U << (__fd & FD_SETBITMASK)); \ | |
| } while (0) | |
| #define FD_SET(fd, set) do { \ | |
| fd_set *__set = (set); \ | |
| int __fd = (fd); \ | |
| if (__fd >= 0) \ | |
| __set->fds[__fd / FD_SETIDXMASK] |= \ | |
| 1 << (__fd & FD_SETBITMASK); \ | |
| } while (0) | |
| #define FD_ISSET(fd, set) ({ \ | |
| fd_set *__set = (set); \ | |
| int __fd = (fd); \ | |
| int __r = 0; \ | |
| if (__fd >= 0) \ | |
| __r = !!(__set->fds[__fd / FD_SETIDXMASK] & \ | |
| 1U << (__fd & FD_SETBITMASK)); \ | |
| __r; \ | |
| }) | |
| #define FD_ZERO(set) do { \ | |
| fd_set *__set = (set); \ | |
| int __idx; \ | |
| int __size = (FD_SETSIZE+FD_SETBITMASK) / FD_SETIDXMASK;\ | |
| for (__idx = 0; __idx < __size; __idx++) \ | |
| __set->fds[__idx] = 0; \ | |
| } while (0) | |
| /* | |
| * int select(int nfds, fd_set *read_fds, fd_set *write_fds, | |
| * fd_set *except_fds, struct timeval *timeout); | |
| */ | |
| static __attribute__((unused)) | |
| int _sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) | |
| { | |
| #if defined(__NR_pselect6_time64) | |
| struct __kernel_timespec t; | |
| if (timeout) { | |
| t.tv_sec = timeout->tv_sec; | |
| t.tv_nsec = (uint32_t)timeout->tv_usec * 1000; | |
| } | |
| return __nolibc_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, | |
| timeout ? &t : NULL, NULL); | |
| #else | |
| struct __kernel_old_timespec t; | |
| if (timeout) { | |
| t.tv_sec = timeout->tv_sec; | |
| t.tv_nsec = (uint32_t)timeout->tv_usec * 1000; | |
| } | |
| return __nolibc_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, | |
| timeout ? &t : NULL, NULL); | |
| #endif | |
| } | |
| static __attribute__((unused)) | |
| int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) | |
| { | |
| return __sysret(_sys_select(nfds, rfds, wfds, efds, timeout)); | |
| } | |
| #endif /* _NOLIBC_SYS_SELECT_H */ |