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))
sys_select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * efds,struct timeval * timeout)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))
select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * efds,struct timeval * timeout)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