1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 3 #include "../nolibc.h" 4 5 #ifndef _NOLIBC_SYS_SELECT_H 6 #define _NOLIBC_SYS_SELECT_H 7 8 #include <linux/time.h> 9 #include <linux/unistd.h> 10 11 /* commonly an fd_set represents 256 FDs */ 12 #ifndef FD_SETSIZE 13 #define FD_SETSIZE 256 14 #endif 15 16 #define FD_SETIDXMASK (8 * sizeof(unsigned long)) 17 #define FD_SETBITMASK (8 * sizeof(unsigned long)-1) 18 19 /* for select() */ 20 typedef struct { 21 unsigned long fds[(FD_SETSIZE + FD_SETBITMASK) / FD_SETIDXMASK]; 22 } fd_set; 23 24 #define FD_CLR(fd, set) do { \ 25 fd_set *__set = (set); \ 26 int __fd = (fd); \ 27 if (__fd >= 0) \ 28 __set->fds[__fd / FD_SETIDXMASK] &= \ 29 ~(1U << (__fd & FD_SETBITMASK)); \ 30 } while (0) 31 32 #define FD_SET(fd, set) do { \ 33 fd_set *__set = (set); \ 34 int __fd = (fd); \ 35 if (__fd >= 0) \ 36 __set->fds[__fd / FD_SETIDXMASK] |= \ 37 1 << (__fd & FD_SETBITMASK); \ 38 } while (0) 39 40 #define FD_ISSET(fd, set) ({ \ 41 fd_set *__set = (set); \ 42 int __fd = (fd); \ 43 int __r = 0; \ 44 if (__fd >= 0) \ 45 __r = !!(__set->fds[__fd / FD_SETIDXMASK] & \ 46 1U << (__fd & FD_SETBITMASK)); \ 47 __r; \ 48 }) 49 50 #define FD_ZERO(set) do { \ 51 fd_set *__set = (set); \ 52 int __idx; \ 53 int __size = (FD_SETSIZE+FD_SETBITMASK) / FD_SETIDXMASK;\ 54 for (__idx = 0; __idx < __size; __idx++) \ 55 __set->fds[__idx] = 0; \ 56 } while (0) 57 58 /* 59 * int select(int nfds, fd_set *read_fds, fd_set *write_fds, 60 * fd_set *except_fds, struct timeval *timeout); 61 */ 62 63 static __attribute__((unused)) 64 int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 65 { 66 #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect) 67 struct sel_arg_struct { 68 unsigned long n; 69 fd_set *r, *w, *e; 70 struct timeval *t; 71 } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout }; 72 return my_syscall1(__NR_select, &arg); 73 #elif defined(__NR__newselect) 74 return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); 75 #elif defined(__NR_select) 76 return my_syscall5(__NR_select, nfds, rfds, wfds, efds, timeout); 77 #elif defined(__NR_pselect6) 78 struct timespec t; 79 80 if (timeout) { 81 t.tv_sec = timeout->tv_sec; 82 t.tv_nsec = timeout->tv_usec * 1000; 83 } 84 return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 85 #else 86 struct __kernel_timespec t; 87 88 if (timeout) { 89 t.tv_sec = timeout->tv_sec; 90 t.tv_nsec = timeout->tv_usec * 1000; 91 } 92 return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 93 #endif 94 } 95 96 static __attribute__((unused)) 97 int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 98 { 99 return __sysret(sys_select(nfds, rfds, wfds, efds, timeout)); 100 } 101 102 103 #endif /* _NOLIBC_SYS_SELECT_H */ 104