1*71db0c75SAndroid Build Coastguard Worker //===-- Linux implementation of select ------------------------------------===// 2*71db0c75SAndroid Build Coastguard Worker // 3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information. 5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*71db0c75SAndroid Build Coastguard Worker // 7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 8*71db0c75SAndroid Build Coastguard Worker 9*71db0c75SAndroid Build Coastguard Worker #include "src/sys/select/select.h" 10*71db0c75SAndroid Build Coastguard Worker 11*71db0c75SAndroid Build Coastguard Worker #include "hdr/types/sigset_t.h" 12*71db0c75SAndroid Build Coastguard Worker #include "hdr/types/struct_timespec.h" 13*71db0c75SAndroid Build Coastguard Worker #include "src/__support/CPP/limits.h" 14*71db0c75SAndroid Build Coastguard Worker #include "src/__support/OSUtil/syscall.h" // For internal syscall function. 15*71db0c75SAndroid Build Coastguard Worker #include "src/__support/common.h" 16*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/config.h" 17*71db0c75SAndroid Build Coastguard Worker #include "src/errno/libc_errno.h" 18*71db0c75SAndroid Build Coastguard Worker 19*71db0c75SAndroid Build Coastguard Worker #include <stddef.h> // For size_t 20*71db0c75SAndroid Build Coastguard Worker #include <sys/syscall.h> // For syscall numbers. 21*71db0c75SAndroid Build Coastguard Worker 22*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL { 23*71db0c75SAndroid Build Coastguard Worker 24*71db0c75SAndroid Build Coastguard Worker struct pselect6_sigset_t { 25*71db0c75SAndroid Build Coastguard Worker sigset_t *ss; 26*71db0c75SAndroid Build Coastguard Worker size_t ss_len; 27*71db0c75SAndroid Build Coastguard Worker }; 28*71db0c75SAndroid Build Coastguard Worker 29*71db0c75SAndroid Build Coastguard Worker LLVM_LIBC_FUNCTION(int, select, 30*71db0c75SAndroid Build Coastguard Worker (int nfds, fd_set *__restrict read_set, 31*71db0c75SAndroid Build Coastguard Worker fd_set *__restrict write_set, fd_set *__restrict error_set, 32*71db0c75SAndroid Build Coastguard Worker struct timeval *__restrict timeout)) { 33*71db0c75SAndroid Build Coastguard Worker // Linux has a SYS_select syscall but it is not available on all 34*71db0c75SAndroid Build Coastguard Worker // architectures. So, we use the SYS_pselect6 syscall which is more 35*71db0c75SAndroid Build Coastguard Worker // widely available. However, SYS_pselect6 takes a struct timespec argument 36*71db0c75SAndroid Build Coastguard Worker // instead of a struct timeval argument. Also, it takes an additional 37*71db0c75SAndroid Build Coastguard Worker // argument which is a pointer to an object of a type defined above as 38*71db0c75SAndroid Build Coastguard Worker // "pselect6_sigset_t". 39*71db0c75SAndroid Build Coastguard Worker struct timespec ts { 40*71db0c75SAndroid Build Coastguard Worker 0, 0 41*71db0c75SAndroid Build Coastguard Worker }; 42*71db0c75SAndroid Build Coastguard Worker if (timeout != nullptr) { 43*71db0c75SAndroid Build Coastguard Worker // In general, if the tv_sec and tv_usec in |timeout| are correctly set, 44*71db0c75SAndroid Build Coastguard Worker // then converting tv_usec to nanoseconds will not be a problem. However, 45*71db0c75SAndroid Build Coastguard Worker // if tv_usec in |timeout| is more than a second, it can lead to overflows. 46*71db0c75SAndroid Build Coastguard Worker // So, we detect such cases and adjust. 47*71db0c75SAndroid Build Coastguard Worker constexpr time_t TIME_MAX = cpp::numeric_limits<time_t>::max(); 48*71db0c75SAndroid Build Coastguard Worker if ((TIME_MAX - timeout->tv_sec) < (timeout->tv_usec / 1000000)) { 49*71db0c75SAndroid Build Coastguard Worker ts.tv_sec = TIME_MAX; 50*71db0c75SAndroid Build Coastguard Worker ts.tv_nsec = 999999999; 51*71db0c75SAndroid Build Coastguard Worker } else { 52*71db0c75SAndroid Build Coastguard Worker ts.tv_sec = timeout->tv_sec + timeout->tv_usec / 1000000; 53*71db0c75SAndroid Build Coastguard Worker ts.tv_nsec = timeout->tv_usec * 1000; 54*71db0c75SAndroid Build Coastguard Worker } 55*71db0c75SAndroid Build Coastguard Worker } 56*71db0c75SAndroid Build Coastguard Worker pselect6_sigset_t pss{nullptr, sizeof(sigset_t)}; 57*71db0c75SAndroid Build Coastguard Worker #if SYS_pselect6 58*71db0c75SAndroid Build Coastguard Worker int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_pselect6, nfds, read_set, 59*71db0c75SAndroid Build Coastguard Worker write_set, error_set, &ts, &pss); 60*71db0c75SAndroid Build Coastguard Worker #elif defined(SYS_pselect6_time64) 61*71db0c75SAndroid Build Coastguard Worker int ret = LIBC_NAMESPACE::syscall_impl<int>( 62*71db0c75SAndroid Build Coastguard Worker SYS_pselect6_time64, nfds, read_set, write_set, error_set, &ts, &pss); 63*71db0c75SAndroid Build Coastguard Worker #else 64*71db0c75SAndroid Build Coastguard Worker #error "SYS_pselect6 and SYS_pselect6_time64 syscalls not available." 65*71db0c75SAndroid Build Coastguard Worker #endif 66*71db0c75SAndroid Build Coastguard Worker if (ret < 0) { 67*71db0c75SAndroid Build Coastguard Worker libc_errno = -ret; 68*71db0c75SAndroid Build Coastguard Worker return -1; 69*71db0c75SAndroid Build Coastguard Worker } 70*71db0c75SAndroid Build Coastguard Worker return ret; 71*71db0c75SAndroid Build Coastguard Worker } 72*71db0c75SAndroid Build Coastguard Worker 73*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL 74