Files
vlibc/include/sys/select.h
T

121 lines
4.7 KiB
C

#ifndef VLIBC_SYS_SELECT_H
#define VLIBC_SYS_SELECT_H
/*
* vlibc — <sys/select.h>.
*
* Synchronous I/O multiplexing: wait for readiness on file-descriptor sets
* with select() or pselect(). Both are thin wrappers over the SYS_pselect6
* kernel ABI, (nfds, readfds, writefds, exceptfds, struct timespec *,
* { sigset_t *, size_t } *): pselect passes its timespec and optional signal
* mask straight through, select converts its struct timeval timeout to a
* timespec and passes a NULL sigset pair.
*
* Level 1 (onlyposix): select, pselect, FD_* macros, fd_set, struct
* timeval.
*
* fd_set is the kernel's bitmap layout on x86_64: an array of unsigned long
* words, with descriptor d held in bit d % 64 of word d / 64. FD_SETSIZE
* caps the tracked descriptors at 1024 (16 words), so select()/pselect()
* must be called with nfds <= FD_SETSIZE and FD_SET() only ever receives
* descriptors below FD_SETSIZE. select() and pselect() report the number of
* ready descriptors, 0 on timeout, or -1 with errno set on error.
*
* The signal mask type is declared here under the shared guard; <signal.h>
* is its canonical POSIX home and will own the full sig* API.
*/
#include <vlibc/features.h>
#include <sys/types.h>
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Maximum descriptors select()/pselect() track (fd_set's bit capacity). */
#define FD_SETSIZE 1024
/*
* A set of file descriptors, one bit per descriptor, stored in the kernel
* bitmap layout: an array of unsigned long words, bit d in word
* d / (8 * sizeof(unsigned long)). Descriptors 0..FD_SETSIZE-1 fit; no
* operation may touch a descriptor at or above FD_SETSIZE.
*/
typedef struct
{
unsigned long fds_bits[FD_SETSIZE / (8 * sizeof(unsigned long))];
} fd_set;
/* The word holding bit d of an fd_set, and that bit's mask within the word. */
#define VLIBC_FDS_WORD(d) ((d) / (8 * sizeof(unsigned long)))
#define VLIBC_FDS_MASK(d) (1UL << ((d) % (8 * sizeof(unsigned long))))
/* Clear every descriptor bit of set. */
#define FD_ZERO(set) \
do \
{ \
size_t fd_zero_i; \
for (fd_zero_i = 0; fd_zero_i < sizeof(fd_set) / sizeof(unsigned long); fd_zero_i++) \
{ \
(set)->fds_bits[fd_zero_i] = 0UL; \
} \
} while (0)
/* Add descriptor d to set. */
#define FD_SET(d, set) ((set)->fds_bits[VLIBC_FDS_WORD(d)] |= VLIBC_FDS_MASK(d))
/* Remove descriptor d from set. */
#define FD_CLR(d, set) ((set)->fds_bits[VLIBC_FDS_WORD(d)] &= ~VLIBC_FDS_MASK(d))
/* Nonzero when descriptor d is a member of set. */
#define FD_ISSET(d, set) ((set)->fds_bits[VLIBC_FDS_WORD(d)] & VLIBC_FDS_MASK(d))
#ifndef VLIBC_SIGSET_T_DEFINED
#define VLIBC_SIGSET_T_DEFINED
/*
* Signal mask type: a single 64-bit word — the x86_64 Linux sigset_t (see
* setjmp.h). pselect() and ppoll() only ever forward a pointer to the
* kernel, which reads the word directly. <signal.h> is the canonical POSIX
* home for sigset_t and builds the sig* API on this same layout; the
* typedef is repeated in <poll.h> under this guard so the two headers stay
* consistent.
*/
typedef unsigned long sigset_t;
#endif
/* Elapsed time in seconds and microseconds (see select()'s timeout). */
struct timeval
{
time_t tv_sec;
suseconds_t tv_usec;
};
/*
* Wait for readiness on the descriptors marked in readfds, writefds and
* exceptfds (each may be NULL), up to nfds descriptors (the highest
* descriptor in any set plus one). timeout is an upper bound on the wait; a
* NULL timeout blocks indefinitely, { 0, 0 } never blocks. On return each
* non-NULL set holds only its ready descriptors. Return the number of ready
* descriptors across the sets, 0 on timeout, or -1 with errno set.
*/
int
select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
/*
* Like select(), but the timeout is a struct timespec and, when sigmask is
* not NULL, the given signal mask is atomically installed for the duration
* of the wait (the previous mask is restored before returning).
*/
int
pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
const struct timespec *timeout, const sigset_t *sigmask);
#ifdef __cplusplus
}
#endif
#endif /* VLIBC_SYS_SELECT_H */