select.c 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. #include <sys/select.h>
  2. #include <signal.h>
  3. #include <stdint.h>
  4. #include <errno.h>
  5. #include "syscall.h"
  6. #define IS32BIT(x) !((x)+0x80000000ULL>>32)
  7. #define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63))
  8. int select(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, struct timeval *restrict tv)
  9. {
  10. time_t s = tv ? tv->tv_sec : 0;
  11. suseconds_t us = tv ? tv->tv_usec : 0;
  12. long ns;
  13. const time_t max_time = (1ULL<<8*sizeof(time_t)-1)-1;
  14. if (s<0 || us<0) return __syscall_ret(-EINVAL);
  15. if (us/1000000 > max_time - s) {
  16. s = max_time;
  17. us = 999999;
  18. ns = 999999999;
  19. } else {
  20. s += us/1000000;
  21. us %= 1000000;
  22. ns = us*1000;
  23. }
  24. #ifdef SYS_pselect6_time64
  25. int r = -ENOSYS;
  26. if (SYS_pselect6 == SYS_pselect6_time64 || !IS32BIT(s))
  27. r = __syscall_cp(SYS_pselect6_time64, n, rfds, wfds, efds,
  28. tv ? ((long long[]){s, ns}) : 0,
  29. ((syscall_arg_t[]){ 0, _NSIG/8 }));
  30. if (SYS_pselect6 == SYS_pselect6_time64 || r!=-ENOSYS)
  31. return __syscall_ret(r);
  32. #endif
  33. #ifdef SYS_select
  34. return syscall_cp(SYS_select, n, rfds, wfds, efds, ((long[]){s, us}));
  35. #else
  36. return syscall_cp(SYS_pselect6, n, rfds, wfds, efds,
  37. tv ? ((long[]){s, ns}) : 0, ((syscall_arg_t[]){ 0, _NSIG/8 }));
  38. #endif
  39. }