xref: /linux/tools/include/nolibc/sys/select.h (revision 10f407c66061524f0da0384de76827e30268f98a)
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