[libc-commits] [libc] [libc] Remove 32-bit time_t support (PR #200426)

via libc-commits libc-commits at lists.llvm.org
Fri May 29 08:50:41 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Jeff Bailey (kaladron)

<details>
<summary>Changes</summary>

Removed time_t_32.h and forced time_t to 64-bit (__INT64_TYPE__) on all platforms.

Forced tv_nsec in struct timespec and tv_usec in struct timeval to 64-bit. This ensures struct timespec matches the kernel layout of struct __kernel_timespec, allowing direct casting in syscall wrappers. Note that under C23, tv_nsec is allowed to be any signed integer type capable of representing [0, 999999999], making this 64-bit definition fully compliant.

Updated syscall wrappers to prefer 64-bit time syscalls:
* clock_gettime64
* clock_settime64
* clock_nanosleep_time64
* pselect6_time64
* utimensat_time64
* futex_time64

Added static_asserts to legacy fallback paths to prevent compiling on 32-bit platforms that lack 64-bit time support.

Removed obsolete Y2038 overflow tests from mktime and other time tests.

Assisted-by: Automated tooling, human reviewed.

---

Patch is 31.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/200426.diff


26 Files Affected:

- (modified) libc/cmake/modules/LLVMLibCCompileOptionRules.cmake (-4) 
- (modified) libc/cmake/modules/LLVMLibCFlagRules.cmake (-13) 
- (modified) libc/config/config.json (-6) 
- (modified) libc/include/llvm-libc-types/CMakeLists.txt (+1-5) 
- (modified) libc/include/llvm-libc-types/struct_timespec.h (+3-2) 
- (modified) libc/include/llvm-libc-types/suseconds_t.h (+1-1) 
- (modified) libc/include/llvm-libc-types/time_t.h (-4) 
- (removed) libc/include/llvm-libc-types/time_t_32.h (-20) 
- (modified) libc/src/__support/OSUtil/linux/syscall_wrappers/utimensat.h (+7-3) 
- (modified) libc/src/__support/threads/linux/futex_utils.h (+9) 
- (modified) libc/src/__support/threads/linux/futex_word.h (+3-3) 
- (modified) libc/src/__support/time/linux/clock_gettime.cpp (+15-18) 
- (modified) libc/src/__support/time/linux/clock_settime.cpp (+9-14) 
- (modified) libc/src/poll/linux/poll.cpp (+10-5) 
- (modified) libc/src/sched/linux/sched_rr_get_interval.cpp (+9-22) 
- (modified) libc/src/sys/select/linux/select.cpp (+10-5) 
- (modified) libc/src/sys/time/linux/getitimer.cpp (+12-8) 
- (modified) libc/src/sys/time/linux/setitimer.cpp (+24-6) 
- (modified) libc/src/sys/time/linux/utimes.cpp (+3-13) 
- (modified) libc/src/time/linux/nanosleep.cpp (+8-6) 
- (modified) libc/src/time/time_constants.h (-6) 
- (modified) libc/src/time/time_utils.cpp (+4-31) 
- (modified) libc/test/src/time/asctime_test.cpp (-2) 
- (modified) libc/test/src/time/gmtime_r_test.cpp (-2) 
- (modified) libc/test/src/time/gmtime_test.cpp (-4) 
- (modified) libc/test/src/time/mktime_test.cpp (-90) 


``````````diff
diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
index c65fc4db605c9..02921973e4940 100644
--- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
+++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
@@ -134,10 +134,6 @@ function(_get_compile_options_from_config output_var)
     libc_add_definition(config_options "LIBC_COPT_USE_MEM_BUILTINS")
   endif()
 
-  if(LIBC_TYPES_TIME_T_IS_32_BIT AND LLVM_LIBC_FULL_BUILD)
-    libc_add_definition(config_options "LIBC_TYPES_TIME_T_IS_32_BIT")
-  endif()
-
   if(LIBC_ADD_NULL_CHECKS)
     libc_add_definition(config_options "LIBC_ADD_NULL_CHECKS")
   endif()
diff --git a/libc/cmake/modules/LLVMLibCFlagRules.cmake b/libc/cmake/modules/LLVMLibCFlagRules.cmake
index d721756f9b4c5..70a3f9b64483e 100644
--- a/libc/cmake/modules/LLVMLibCFlagRules.cmake
+++ b/libc/cmake/modules/LLVMLibCFlagRules.cmake
@@ -308,16 +308,3 @@ if(NOT DEFINED SKIP_FLAG_EXPANSION_ROUND_OPT)
     set(SKIP_FLAG_EXPANSION_ROUND_OPT TRUE)
   endif()
 endif()
-
-# Choose whether time_t is 32- or 64-bit, based on target architecture
-# and config options. This will be used to set a #define during the
-# library build, and also to select the right version of time_t.h for
-# the output headers.
-if(LIBC_TARGET_ARCHITECTURE_IS_ARM AND NOT (LIBC_CONF_TIME_64BIT))
-  # Set time_t to 32 bit for compatibility with glibc, unless
-  # configuration says otherwise
-  set(LIBC_TYPES_TIME_T_IS_32_BIT TRUE)
-else()
-  # Other platforms default to 64-bit time_t
-  set(LIBC_TYPES_TIME_T_IS_32_BIT FALSE)
-endif()
diff --git a/libc/config/config.json b/libc/config/config.json
index 27d9f08ed31e0..510a6c1b1990c 100644
--- a/libc/config/config.json
+++ b/libc/config/config.json
@@ -167,12 +167,6 @@
       "doc": "Make setjmp save the value of x18, and longjmp restore it. The AArch64 ABI delegates this register to platform ABIs, which can choose whether to make it caller-saved."
     }
   },
-  "time": {
-    "LIBC_CONF_TIME_64BIT": {
-      "value": false,
-      "doc": "Force the size of time_t to 64 bits, even on platforms where compatibility considerations would otherwise make it 32-bit."
-    }
-  },
   "general": {
     "LIBC_ADD_NULL_CHECKS": {
       "value": true,
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 7c88e6e538879..6f3eca7e8e606 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -87,11 +87,7 @@ add_header(pthread_spinlock_t HDR pthread_spinlock_t.h DEPENDS .pid_t)
 add_header(pthread_t HDR pthread_t.h DEPENDS .__thread_type)
 add_header(pthread_id_np_t HDR pthread_id_np_t.h DEPENDS libc.include.llvm-libc-macros.stdint_macros)
 add_header(rlim_t HDR rlim_t.h)
-if(LIBC_TYPES_TIME_T_IS_32_BIT)
-  add_header(time_t HDR time_t_32.h DEST_HDR time_t.h)
-else()
-  add_header(time_t HDR time_t_64.h DEST_HDR time_t.h)
-endif()
+add_header(time_t HDR time_t_64.h DEST_HDR time_t.h)
 add_header(sighandler_t HDR sighandler_t.h)
 add_header(stack_t HDR stack_t.h DEPENDS .size_t)
 add_header(suseconds_t HDR suseconds_t.h)
diff --git a/libc/include/llvm-libc-types/struct_timespec.h b/libc/include/llvm-libc-types/struct_timespec.h
index 8993ecc7db8f0..7546795665dec 100644
--- a/libc/include/llvm-libc-types/struct_timespec.h
+++ b/libc/include/llvm-libc-types/struct_timespec.h
@@ -18,8 +18,9 @@
 
 struct timespec {
   time_t tv_sec; /* Seconds.  */
-  /* TODO: BIG_ENDIAN may require padding. */
-  long tv_nsec; /* Nanoseconds.  */
+  /* Nanoseconds. Forced to 64-bit to match __kernel_timespec layout (C23
+   * compliant). */
+  __INT64_TYPE__ tv_nsec;
 };
 #endif // __APPLE__
 
diff --git a/libc/include/llvm-libc-types/suseconds_t.h b/libc/include/llvm-libc-types/suseconds_t.h
index acc1822cb59e1..cd18b4f7cb889 100644
--- a/libc/include/llvm-libc-types/suseconds_t.h
+++ b/libc/include/llvm-libc-types/suseconds_t.h
@@ -19,7 +19,7 @@
 // to ensure type compatibility and avoid redefinition errors.
 #include <sys/_types/_suseconds_t.h>
 #else
-typedef long suseconds_t;
+typedef __INT64_TYPE__ suseconds_t;
 #endif // __APPLE__
 
 #endif // LLVM_LIBC_TYPES_SUSECONDS_T_H
diff --git a/libc/include/llvm-libc-types/time_t.h b/libc/include/llvm-libc-types/time_t.h
index 76920dc07ec69..7609a7a5c33f7 100644
--- a/libc/include/llvm-libc-types/time_t.h
+++ b/libc/include/llvm-libc-types/time_t.h
@@ -9,10 +9,6 @@
 #ifndef LLVM_LIBC_TYPES_TIME_T_H
 #define LLVM_LIBC_TYPES_TIME_T_H
 
-#ifdef LIBC_TYPES_TIME_T_IS_32_BIT
-#include "time_t_32.h"
-#else
 #include "time_t_64.h"
-#endif
 
 #endif // LLVM_LIBC_TYPES_TIME_T_H
diff --git a/libc/include/llvm-libc-types/time_t_32.h b/libc/include/llvm-libc-types/time_t_32.h
deleted file mode 100644
index 8d7a81e5ce7f7..0000000000000
--- a/libc/include/llvm-libc-types/time_t_32.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//===-- Definition of the type time_t -------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIBC_TYPES_TIME_T_32_H
-#define LLVM_LIBC_TYPES_TIME_T_32_H
-
-#if defined(__APPLE__)
-// Darwin provides its own definition for time_t. Include it directly
-// to ensure type compatibility and avoid redefinition errors.
-#include <sys/_types/_time_t.h>
-#else
-typedef __INT32_TYPE__ time_t;
-#endif // __APPLE__
-
-#endif // LLVM_LIBC_TYPES_TIME_T_32_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/utimensat.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/utimensat.h
index d71afb9f5251d..cbf79f5de2cbf 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/utimensat.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/utimensat.h
@@ -23,14 +23,18 @@ namespace linux_syscalls {
 LIBC_INLINE ErrorOr<int> utimensat(int dirfd, const char *path,
                                    const struct timespec times[2], int flags) {
 #if defined(SYS_utimensat_time64)
-  constexpr auto UTIMENSAT_SYSCALL_ID = SYS_utimensat_time64;
+  int ret = syscall_impl<int>(SYS_utimensat_time64, dirfd, path, times, flags);
 #elif defined(SYS_utimensat)
-  constexpr auto UTIMENSAT_SYSCALL_ID = SYS_utimensat;
+  static_assert(
+      sizeof(timespec::tv_nsec) == sizeof(long),
+      "This legacy syscall fallback is only safe on platforms where tv_nsec "
+      "matches the register size (long). It is unsafe on 32-bit platforms "
+      "with 64-bit tv_nsec.");
+  int ret = syscall_impl<int>(SYS_utimensat, dirfd, path, times, flags);
 #else
 #error "utimensat or utimensat_time64 syscalls not available."
 #endif
 
-  int ret = syscall_impl<int>(UTIMENSAT_SYSCALL_ID, dirfd, path, times, flags);
   if (ret < 0)
     return Error(-static_cast<int>(ret));
   return ret;
diff --git a/libc/src/__support/threads/linux/futex_utils.h b/libc/src/__support/threads/linux/futex_utils.h
index 4a39c66c6eb9a..ff6b5d526a3c1 100644
--- a/libc/src/__support/threads/linux/futex_utils.h
+++ b/libc/src/__support/threads/linux/futex_utils.h
@@ -22,6 +22,15 @@
 #include <linux/futex.h>
 
 namespace LIBC_NAMESPACE_DECL {
+
+#if !defined(SYS_futex_time64) && defined(SYS_futex)
+static_assert(
+    sizeof(timespec::tv_nsec) == sizeof(long),
+    "This legacy syscall fallback is only safe on platforms where tv_nsec "
+    "matches the register size (long). It is unsafe on 32-bit platforms "
+    "with 64-bit tv_nsec.");
+#endif
+
 class Futex : public cpp::Atomic<FutexWordType> {
 public:
   using Timeout = internal::AbsTimeout;
diff --git a/libc/src/__support/threads/linux/futex_word.h b/libc/src/__support/threads/linux/futex_word.h
index 1cf7befea5c88..9ef55ceaeb790 100644
--- a/libc/src/__support/threads/linux/futex_word.h
+++ b/libc/src/__support/threads/linux/futex_word.h
@@ -17,10 +17,10 @@ namespace LIBC_NAMESPACE_DECL {
 // Futexes are 32 bits in size on all platforms, including 64-bit platforms.
 using FutexWordType = uint32_t;
 
-#if SYS_futex
-constexpr auto FUTEX_SYSCALL_ID = SYS_futex;
-#elif defined(SYS_futex_time64)
+#if defined(SYS_futex_time64)
 constexpr auto FUTEX_SYSCALL_ID = SYS_futex_time64;
+#elif defined(SYS_futex)
+constexpr auto FUTEX_SYSCALL_ID = SYS_futex;
 #else
 #error "futex and futex_time64 syscalls not available."
 #endif
diff --git a/libc/src/__support/time/linux/clock_gettime.cpp b/libc/src/__support/time/linux/clock_gettime.cpp
index 944fc0a2b80fe..c893bcf9b772e 100644
--- a/libc/src/__support/time/linux/clock_gettime.cpp
+++ b/libc/src/__support/time/linux/clock_gettime.cpp
@@ -25,7 +25,21 @@ namespace internal {
 ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
   using namespace vdso;
   int ret;
-#if defined(SYS_clock_gettime)
+#if defined(SYS_clock_gettime64)
+  TypedSymbol<VDSOSym::ClockGetTime64> clock_gettime64;
+  if (LIBC_LIKELY(clock_gettime64 != nullptr)) {
+    ret = clock_gettime64(clockid, reinterpret_cast<__kernel_timespec *>(ts));
+  } else {
+    ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime64,
+                                            static_cast<long>(clockid),
+                                            reinterpret_cast<long>(ts));
+  }
+#elif defined(SYS_clock_gettime)
+  static_assert(
+      sizeof(timespec::tv_nsec) == sizeof(long),
+      "This legacy syscall fallback is only safe on platforms where tv_nsec "
+      "matches the register size (long). It is unsafe on 32-bit platforms "
+      "with 64-bit tv_nsec.");
   TypedSymbol<VDSOSym::ClockGetTime> clock_gettime;
   if (LIBC_LIKELY(clock_gettime != nullptr))
     ret = clock_gettime(clockid, ts);
@@ -33,23 +47,6 @@ ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
     ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime,
                                             static_cast<long>(clockid),
                                             reinterpret_cast<long>(ts));
-#elif defined(SYS_clock_gettime64)
-  static_assert(
-      sizeof(time_t) == sizeof(int64_t),
-      "SYS_clock_gettime64 requires struct timespec with 64-bit members.");
-
-  TypedSymbol<VDSOSym::ClockGetTime64> clock_gettime64;
-  __kernel_timespec ts64{};
-  if (LIBC_LIKELY(clock_gettime64 != nullptr))
-    ret = clock_gettime64(clockid, &ts64);
-  else
-    ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime64,
-                                            static_cast<long>(clockid),
-                                            reinterpret_cast<long>(&ts64));
-  if (ret == 0) {
-    ts->tv_sec = static_cast<decltype(ts->tv_sec)>(ts64.tv_sec);
-    ts->tv_nsec = static_cast<decltype(ts->tv_nsec)>(ts64.tv_nsec);
-  }
 #else
 #error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available."
 #endif
diff --git a/libc/src/__support/time/linux/clock_settime.cpp b/libc/src/__support/time/linux/clock_settime.cpp
index dd42610adb031..ec96828b42352 100644
--- a/libc/src/__support/time/linux/clock_settime.cpp
+++ b/libc/src/__support/time/linux/clock_settime.cpp
@@ -23,24 +23,19 @@ namespace LIBC_NAMESPACE_DECL {
 namespace internal {
 ErrorOr<int> clock_settime(clockid_t clockid, const timespec *ts) {
   int ret;
-#if defined(SYS_clock_settime)
-  ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_settime,
+#if defined(SYS_clock_settime64)
+  ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_settime64,
                                           static_cast<long>(clockid),
                                           reinterpret_cast<long>(ts));
-#elif defined(SYS_clock_settime64)
+#elif defined(SYS_clock_settime)
   static_assert(
-      sizeof(time_t) == sizeof(int64_t),
-      "SYS_clock_settime64 requires struct timespec with 64-bit members.");
-
-  __kernel_timespec ts64{};
-
-  // Populate the 64-bit kernel structure from the user-provided timespec
-  ts64.tv_sec = static_cast<decltype(ts64.tv_sec)>(ts->tv_sec);
-  ts64.tv_nsec = static_cast<decltype(ts64.tv_nsec)>(ts->tv_nsec);
-
-  ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_settime64,
+      sizeof(timespec::tv_nsec) == sizeof(long),
+      "This legacy syscall fallback is only safe on platforms where tv_nsec "
+      "matches the register size (long). It is unsafe on 32-bit platforms "
+      "with 64-bit tv_nsec.");
+  ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_settime,
                                           static_cast<long>(clockid),
-                                          reinterpret_cast<long>(&ts64));
+                                          reinterpret_cast<long>(ts));
 #else
 #error "SYS_clock_settime and SYS_clock_settime64 syscalls not available."
 #endif
diff --git a/libc/src/poll/linux/poll.cpp b/libc/src/poll/linux/poll.cpp
index 4cac75b9687c8..7db5b16b1f5b9 100644
--- a/libc/src/poll/linux/poll.cpp
+++ b/libc/src/poll/linux/poll.cpp
@@ -16,7 +16,7 @@
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
 
-#include <sys/syscall.h> // SYS_poll, SYS_ppoll
+#include <sys/syscall.h> // SYS_poll, SYS_ppoll, SYS_ppoll_time64
 
 namespace LIBC_NAMESPACE_DECL {
 
@@ -34,12 +34,17 @@ LLVM_LIBC_FUNCTION(int, poll, (pollfd * fds, nfds_t nfds, int timeout)) {
   } else {
     tsp = nullptr;
   }
-#if defined(SYS_ppoll)
-  ret =
-      LIBC_NAMESPACE::syscall_impl<int>(SYS_ppoll, fds, nfds, tsp, nullptr, 0);
-#elif defined(SYS_ppoll_time64)
+#if defined(SYS_ppoll_time64)
   ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_ppoll_time64, fds, nfds, tsp,
                                           nullptr, 0);
+#elif defined(SYS_ppoll)
+  static_assert(
+      sizeof(timespec::tv_nsec) == sizeof(long),
+      "This legacy syscall fallback is only safe on platforms where tv_nsec "
+      "matches the register size (long). It is unsafe on 32-bit platforms "
+      "with 64-bit tv_nsec.");
+  ret =
+      LIBC_NAMESPACE::syscall_impl<int>(SYS_ppoll, fds, nfds, tsp, nullptr, 0);
 #else
 #error "poll, ppoll, ppoll_time64 syscalls not available."
 #endif // defined(SYS_ppoll) || defined(SYS_ppoll_time64)
diff --git a/libc/src/sched/linux/sched_rr_get_interval.cpp b/libc/src/sched/linux/sched_rr_get_interval.cpp
index eecbaa4dc03ce..c87d1808bc902 100644
--- a/libc/src/sched/linux/sched_rr_get_interval.cpp
+++ b/libc/src/sched/linux/sched_rr_get_interval.cpp
@@ -17,34 +17,21 @@
 #include "hdr/types/struct_timespec.h"
 #include <sys/syscall.h> // For syscall numbers.
 
-#ifdef SYS_sched_rr_get_interval_time64
-#include <linux/time_types.h> // For __kernel_timespec.
-#endif
-
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, sched_rr_get_interval,
                    (pid_t tid, struct timespec *tp)) {
-#ifdef SYS_sched_rr_get_interval
+#if defined(SYS_sched_rr_get_interval_time64)
+  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_sched_rr_get_interval_time64,
+                                              tid, tp);
+#elif defined(SYS_sched_rr_get_interval)
+  static_assert(
+      sizeof(timespec::tv_nsec) == sizeof(long),
+      "This legacy syscall fallback is only safe on platforms where tv_nsec "
+      "matches the register size (long). It is unsafe on 32-bit platforms "
+      "with 64-bit tv_nsec.");
   int ret =
       LIBC_NAMESPACE::syscall_impl<int>(SYS_sched_rr_get_interval, tid, tp);
-#elif defined(SYS_sched_rr_get_interval_time64)
-  // The difference between the  and SYS_sched_rr_get_interval
-  // SYS_sched_rr_get_interval_time64 syscalls is the data type used for the
-  // time interval parameter: the latter takes a struct __kernel_timespec
-  int ret;
-  if (tp) {
-    struct __kernel_timespec ts32;
-    ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_sched_rr_get_interval_time64,
-                                            tid, &ts32);
-    if (ret == 0) {
-      tp->tv_sec = ts32.tv_sec;
-      tp->tv_nsec = static_cast<long int>(ts32.tv_nsec);
-    }
-  } else
-    // When tp is a nullptr, we still do the syscall to set ret and errno
-    ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_sched_rr_get_interval_time64,
-                                            tid, nullptr);
 #else
 #error                                                                         \
     "sched_rr_get_interval and sched_rr_get_interval_time64 syscalls not available."
diff --git a/libc/src/sys/select/linux/select.cpp b/libc/src/sys/select/linux/select.cpp
index 6c434eb584596..939cad4cd2bdd 100644
--- a/libc/src/sys/select/linux/select.cpp
+++ b/libc/src/sys/select/linux/select.cpp
@@ -16,7 +16,7 @@
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
 
-#include <stddef.h>      // For size_t
+#include "hdr/types/size_t.h"
 #include <sys/syscall.h> // For syscall numbers.
 
 namespace LIBC_NAMESPACE_DECL {
@@ -54,12 +54,17 @@ LLVM_LIBC_FUNCTION(int, select,
     }
   }
   pselect6_sigset_t pss{nullptr, sizeof(sigset_t)};
-#if SYS_pselect6
-  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_pselect6, nfds, read_set,
-                                              write_set, error_set, &ts, &pss);
-#elif defined(SYS_pselect6_time64)
+#if defined(SYS_pselect6_time64)
   int ret = LIBC_NAMESPACE::syscall_impl<int>(
       SYS_pselect6_time64, nfds, read_set, write_set, error_set, &ts, &pss);
+#elif defined(SYS_pselect6)
+  static_assert(
+      sizeof(timespec::tv_nsec) == sizeof(long),
+      "This legacy syscall fallback is only safe on platforms where tv_nsec "
+      "matches the register size (long). It is unsafe on 32-bit platforms "
+      "with 64-bit tv_nsec.");
+  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_pselect6, nfds, read_set,
+                                              write_set, error_set, &ts, &pss);
 #else
 #error "SYS_pselect6 and SYS_pselect6_time64 syscalls not available."
 #endif
diff --git a/libc/src/sys/time/linux/getitimer.cpp b/libc/src/sys/time/linux/getitimer.cpp
index b874066796940..2a40491bc95fb 100644
--- a/libc/src/sys/time/linux/getitimer.cpp
+++ b/libc/src/sys/time/linux/getitimer.cpp
@@ -19,14 +19,18 @@ LLVM_LIBC_FUNCTION(int, getitimer, (int which, struct itimerval *curr_value)) {
   long ret = 0;
   if constexpr (sizeof(time_t) > sizeof(long)) {
     // There is no SYS_getitimer_time64 call, so we can't use time_t directly.
-    long curr_value32[4];
-    ret =
-        LIBC_NAMESPACE::syscall_impl<long>(SYS_getitimer, which, curr_value32);
-    if (!ret) {
-      curr_value->it_interval.tv_sec = curr_value32[0];
-      curr_value->it_interval.tv_usec = curr_value32[1];
-      curr_value->it_value.tv_sec = curr_value32[2];
-      curr_value->it_value.tv_usec = curr_value32[3];
+    if (curr_value) {
+      long curr_value32[4];
+      ret = LIBC_NAMESPACE::syscall_impl<long>(SYS_getitimer, which,
+                                               curr_value32);
+      if (!ret) {
+        curr_value->it_interval.tv_sec = curr_value32[0];
+        curr_value->it_interval.tv_usec = curr_value32[1];
+        curr_value->it_value.tv_sec = curr_value32[2];
+        curr_value->it_value.tv_usec = curr_value32[3];
+      }
+    } else {
+      ret = LIBC_NAMESPACE::syscall_impl<long>(SYS_getitimer, which, nullptr);
     }
   } else {
     ret = LIBC_NAMESPACE::syscall_impl<long>(SYS_getitimer, which, curr_value);
diff --git a/libc/src/sys/time/linux/setitimer.cpp b/libc/src/sys/time/linux/setitimer.cpp
index fb163586e30d9..2c2f0d7198204 100644
--- a/libc/src/sys/time/linux/setitimer.cpp
+++ b/libc/src/sys/time/linux/setitimer.cpp
@@ -6,7 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 #include "src/sys/time/setitimer.h"
+#include "hdr/errno_macros.h"
 #include "hdr/types/struct_itimerval.h"
+#include "src/__support/CPP/limits.h"
 #include "src/__support/OSUtil/syscall.h"
 #include "src/__support/common.h"
 #include "src/__support/libc_errno.h"
@@ -21,14 +23,30 @@ LLVM_LIBC_FUNCTION(int, setitimer,
   if constexpr (sizeof(time_t) > sizeof(long)) {
     // There is no SYS_setitimer_time64 call, so we can't use time_t directly,
     // and need to convert it to long first.
-    long new_value32[4] = {static_cast<long>(new_value->it_interval.tv_sec),
-                           static_cast<long>(new_value->it_interval.tv_usec),
-                           static_cast<long>(new_value->it_value.tv_sec),
-                           static_cast<long>(new_value->it_value.tv_usec)};
     long old_value32[4];
+  ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/200426


More information about the libc-commits mailing list