[libc-commits] [libc] [libc] Implement sleep and usleep for Linux (PR #205922)

via libc-commits libc-commits at lists.llvm.org
Tue Jul 21 06:16:58 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Jeff Bailey (kaladron)

<details>
<summary>Changes</summary>

Implemented the sleep and usleep entrypoints for Linux. Refactored the syscall implementation out of the public nanosleep entrypoint into a standard internal syscall wrapper.

Detailed changes:

* Implement sleep and usleep entrypoints.
* Refactor nanosleep to use a standard internal syscall wrapper, linux_syscalls::nanosleep, to avoid public entrypoint overhead.
* Harden nanosleep with LIBC_CRASH_ON_NULLPTR check.
* Fix potential 32-bit overflow in sleep by looping in time_t chunks.
* Add sys_syscall_macros.h proxy header to avoid direct system includes.
* Add unit tests for sleep and usleep, and expand nanosleep tests to verify invalid arguments and null pointer checks.
* Clean up test namespaces to conform to style guidelines.
* Enable sleep and usleep for x86_64, aarch64, and riscv Linux targets.

Assisted-by: Automated tooling, human reviewed.

---

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


27 Files Affected:

- (modified) libc/config/linux/aarch64/entrypoints.txt (+2) 
- (modified) libc/config/linux/riscv/entrypoints.txt (+2) 
- (modified) libc/config/linux/x86_64/entrypoints.txt (+2) 
- (modified) libc/hdr/CMakeLists.txt (+8) 
- (added) libc/hdr/sys_syscall_macros.h (+19) 
- (modified) libc/hdr/types/CMakeLists.txt (+8-1) 
- (added) libc/hdr/types/useconds_t.h (+27) 
- (modified) libc/include/CMakeLists.txt (+2) 
- (modified) libc/include/llvm-libc-types/CMakeLists.txt (+1) 
- (added) libc/include/llvm-libc-types/useconds_t.h (+19) 
- (modified) libc/include/sys/types.yaml (+1) 
- (modified) libc/include/unistd.yaml (+13) 
- (modified) libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt (+14-1) 
- (added) libc/src/__support/OSUtil/linux/syscall_wrappers/nanosleep.h (+51) 
- (modified) libc/src/time/linux/CMakeLists.txt (+4-4) 
- (modified) libc/src/time/linux/nanosleep.cpp (+11-23) 
- (modified) libc/src/unistd/CMakeLists.txt (+14-1) 
- (modified) libc/src/unistd/linux/CMakeLists.txt (+32) 
- (added) libc/src/unistd/linux/sleep.cpp (+58) 
- (added) libc/src/unistd/linux/usleep.cpp (+43) 
- (added) libc/src/unistd/sleep.h (+25) 
- (added) libc/src/unistd/usleep.h (+26) 
- (modified) libc/test/src/time/CMakeLists.txt (+2-1) 
- (modified) libc/test/src/time/nanosleep_test.cpp (+30-3) 
- (modified) libc/test/src/unistd/CMakeLists.txt (+28) 
- (added) libc/test/src/unistd/sleep_test.cpp (+41) 
- (added) libc/test/src/unistd/usleep_test.cpp (+50) 


``````````diff
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 9fccbe9a6d481..85f73b5f45a72 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -407,12 +407,14 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.unistd.readlinkat
     libc.src.unistd.rmdir
     libc.src.unistd.setsid
+    libc.src.unistd.sleep
     libc.src.unistd.symlink
     libc.src.unistd.symlinkat
     libc.src.unistd.sysconf
     libc.src.unistd.truncate
     libc.src.unistd.unlink
     libc.src.unistd.unlinkat
+    libc.src.unistd.usleep
     libc.src.unistd.write
 
     # wchar.h entrypoints
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index c9eb605423bbc..6866fb6fbabce 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -443,12 +443,14 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.unistd.readlinkat
     libc.src.unistd.rmdir
     libc.src.unistd.setsid
+    libc.src.unistd.sleep
     libc.src.unistd.symlink
     libc.src.unistd.symlinkat
     libc.src.unistd.sysconf
     libc.src.unistd.truncate
     libc.src.unistd.unlink
     libc.src.unistd.unlinkat
+    libc.src.unistd.usleep
     libc.src.unistd.write
 
     # wchar.h entrypoints
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 3aae325b53b38..cdc45d36a2264 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -448,12 +448,14 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.unistd.readlinkat
     libc.src.unistd.rmdir
     libc.src.unistd.setsid
+    libc.src.unistd.sleep
     libc.src.unistd.symlink
     libc.src.unistd.symlinkat
     libc.src.unistd.sysconf
     libc.src.unistd.truncate
     libc.src.unistd.unlink
     libc.src.unistd.unlinkat
+    libc.src.unistd.usleep
     libc.src.unistd.write
 
     # wchar.h entrypoints
diff --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt
index 63e0aba10dc40..f66047b18a6a6 100644
--- a/libc/hdr/CMakeLists.txt
+++ b/libc/hdr/CMakeLists.txt
@@ -449,5 +449,13 @@ add_proxy_header_library(
     libc.include.regex
 )
 
+add_proxy_header_library(
+  sys_syscall_macros
+  HDRS
+    sys_syscall_macros.h
+  FULL_BUILD_DEPENDS
+    libc.include.sys_syscall
+)
+
 add_subdirectory(types)
 add_subdirectory(func)
diff --git a/libc/hdr/sys_syscall_macros.h b/libc/hdr/sys_syscall_macros.h
new file mode 100644
index 0000000000000..67a38fb4d543d
--- /dev/null
+++ b/libc/hdr/sys_syscall_macros.h
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Proxy header for sys/syscall.h macros.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_SYS_SYSCALL_MACROS_H
+#define LLVM_LIBC_HDR_SYS_SYSCALL_MACROS_H
+
+#include <sys/syscall.h>
+
+#endif // LLVM_LIBC_HDR_SYS_SYSCALL_MACROS_H
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index 3f9f4a3a0e092..620e5eb265d39 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -282,6 +282,14 @@ add_proxy_header_library(
     libc.include.sys_time
 )
 
+add_proxy_header_library(
+  useconds_t
+  HDRS
+    useconds_t.h
+  FULL_BUILD_DEPENDS
+    libc.include.llvm-libc-types.useconds_t
+)
+
 add_proxy_header_library(
   struct_timeval
   HDRS
@@ -659,7 +667,6 @@ add_proxy_header_library(
     libc.include.wchar
 )
 
-
 add_proxy_header_library(
   wctype_t
   HDRS
diff --git a/libc/hdr/types/useconds_t.h b/libc/hdr/types/useconds_t.h
new file mode 100644
index 0000000000000..c6e26bdbf81ef
--- /dev/null
+++ b/libc/hdr/types/useconds_t.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Proxy header for the useconds_t type.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_TYPES_USECONDS_T_H
+#define LLVM_LIBC_HDR_TYPES_USECONDS_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/useconds_t.h"
+
+#else // Overlay mode
+
+#include <sys/types.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_USECONDS_T_H
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index b856097c6bd3c..e655bd3323fde 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -448,6 +448,7 @@ add_header_macro(
     .llvm-libc-types.size_t
     .llvm-libc-types.ssize_t
     .llvm-libc-types.uid_t
+    .llvm-libc-types.useconds_t
     .llvm-libc-types.__getoptargv_t
 )
 
@@ -857,6 +858,7 @@ add_header_macro(
     .llvm-libc-types.size_t
     .llvm-libc-types.ssize_t
     .llvm-libc-types.suseconds_t
+    .llvm-libc-types.useconds_t
     .llvm-libc-types.time_t
     .llvm-libc-types.u_char
     .llvm-libc-types.u_int32_t
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 5ea8ca0634834..ba09dcb374237 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -106,6 +106,7 @@ 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)
+add_header(useconds_t HDR useconds_t.h)
 add_header(struct_dirent HDR struct_dirent.h DEPENDS .ino_t .off_t)
 add_header(struct_dl_phdr_info HDR struct_dl_phdr_info.h DEPENDS .size_t libc.include.llvm-libc-macros.link_macros)
 add_header(dl_info HDR Dl_info.h)
diff --git a/libc/include/llvm-libc-types/useconds_t.h b/libc/include/llvm-libc-types/useconds_t.h
new file mode 100644
index 0000000000000..54b05a1bcc3d5
--- /dev/null
+++ b/libc/include/llvm-libc-types/useconds_t.h
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Definition of the useconds_t type.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES_USECONDS_T_H
+#define LLVM_LIBC_TYPES_USECONDS_T_H
+
+typedef unsigned int useconds_t;
+
+#endif // LLVM_LIBC_TYPES_USECONDS_T_H
diff --git a/libc/include/sys/types.yaml b/libc/include/sys/types.yaml
index 37c58e708af34..329abd2b9848f 100644
--- a/libc/include/sys/types.yaml
+++ b/libc/include/sys/types.yaml
@@ -27,6 +27,7 @@ types:
   - type_name: size_t
   - type_name: ssize_t
   - type_name: suseconds_t
+  - type_name: useconds_t
   - type_name: time_t
   - type_name: u_char
   - type_name: u_int32_t
diff --git a/libc/include/unistd.yaml b/libc/include/unistd.yaml
index c1ae4567bfc02..4b3703af7798e 100644
--- a/libc/include/unistd.yaml
+++ b/libc/include/unistd.yaml
@@ -42,6 +42,7 @@ types:
   - type_name: __getoptargv_t
   - type_name: __exec_envp_t
   - type_name: __exec_argv_t
+  - type_name: useconds_t
 enums: []
 objects:
   - object_name: environ
@@ -384,6 +385,12 @@ functions:
     return_type: pid_t
     arguments:
       - type: void
+  - name: sleep
+    standards:
+      - posix
+    return_type: unsigned int
+    arguments:
+      - type: unsigned int
   - name: symlink
     standards:
       - posix
@@ -426,6 +433,12 @@ functions:
       - type: int
       - type: const char *
       - type: int
+  - name: usleep
+    standards:
+      - posix
+    return_type: int
+    arguments:
+      - type: useconds_t
   - name: write
     standards:
       - posix
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index 27df4c3f22afb..6a871a43e944b 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -704,7 +704,6 @@ add_header_library(
     libc.include.sys_syscall
 )
 
-
 add_header_library(
   dup
   HDRS
@@ -860,3 +859,17 @@ add_header_library(
     libc.src.__support.macros.config
     libc.include.sys_syscall
 )
+
+add_header_library(
+  nanosleep
+  HDRS
+    nanosleep.h
+  DEPENDS
+    libc.hdr.types.struct_timespec
+    libc.hdr.time_macros
+    libc.hdr.sys_syscall_macros
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+)
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/nanosleep.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/nanosleep.h
new file mode 100644
index 0000000000000..453da6a28cbf5
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/nanosleep.h
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation header for nanosleep syscall wrapper.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_NANOSLEEP_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_NANOSLEEP_H
+
+#include "hdr/sys_syscall_macros.h"
+#include "hdr/time_macros.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<int> nanosleep(const timespec *req, timespec *rem) {
+#if defined(SYS_clock_nanosleep_time64)
+  static_assert(
+      sizeof(time_t) == sizeof(int64_t),
+      "SYS_clock_nanosleep_time64 requires struct timespec with 64-bit "
+      "members.");
+  return syscall_checked<int>(SYS_clock_nanosleep_time64, CLOCK_REALTIME, 0,
+                              req, rem);
+#elif defined(SYS_nanosleep)
+  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.");
+  return syscall_checked<int>(SYS_nanosleep, req, rem);
+#else
+#error "SYS_nanosleep and SYS_clock_nanosleep_time64 syscalls not available."
+#endif
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_NANOSLEEP_H
diff --git a/libc/src/time/linux/CMakeLists.txt b/libc/src/time/linux/CMakeLists.txt
index 623f01eb0d78c..0d53a52bdaca6 100644
--- a/libc/src/time/linux/CMakeLists.txt
+++ b/libc/src/time/linux/CMakeLists.txt
@@ -40,10 +40,10 @@ add_entrypoint_object(
     ../nanosleep.h
   DEPENDS
     libc.hdr.types.struct_timespec
-    libc.hdr.stdint_proxy
-    libc.include.sys_syscall
-    libc.src.__support.OSUtil.osutil
-    libc.src.__support.CPP.limits
+    libc.src.__support.OSUtil.linux.syscall_wrappers.nanosleep
+    libc.src.__support.common
+    libc.src.__support.libc_errno
+    libc.src.__support.macros.config
     libc.src.errno.errno
 )
 
diff --git a/libc/src/time/linux/nanosleep.cpp b/libc/src/time/linux/nanosleep.cpp
index 15b119ead20c6..872a1b27110de 100644
--- a/libc/src/time/linux/nanosleep.cpp
+++ b/libc/src/time/linux/nanosleep.cpp
@@ -1,43 +1,31 @@
-//===-- Linux implementation of nanosleep function ------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // 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
 //
 //===----------------------------------------------------------------------===//
+///
+/// \file
+/// Linux implementation of nanosleep function.
+///
+//===----------------------------------------------------------------------===//
 
 #include "src/time/nanosleep.h"
-#include "hdr/stdint_proxy.h" // For int64_t.
-#include "hdr/time_macros.h"
-#include "src/__support/OSUtil/syscall.h" // For syscall functions.
+#include "src/__support/OSUtil/linux/syscall_wrappers/nanosleep.h"
 #include "src/__support/common.h"
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
 
-#include <sys/syscall.h> // For syscall numbers.
-
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, nanosleep, (const timespec *req, timespec *rem)) {
-#if defined(SYS_clock_nanosleep_time64)
-  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_nanosleep_time64,
-                                              CLOCK_REALTIME, 0, req, rem);
-#elif defined(SYS_nanosleep)
-  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_nanosleep, req, rem);
-#else
-#error "SYS_nanosleep and SYS_clock_nanosleep_time64 syscalls not available."
-#endif
-
-  if (ret < 0) {
-    libc_errno = -ret;
+  auto result = linux_syscalls::nanosleep(req, rem);
+  if (!result) {
+    libc_errno = result.error();
     return -1;
   }
-  return ret;
+  return result.value();
 }
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt
index c8f1b8d3ef15f..98444e7b31631 100644
--- a/libc/src/unistd/CMakeLists.txt
+++ b/libc/src/unistd/CMakeLists.txt
@@ -236,7 +236,6 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.pathconf
 )
 
-
 add_entrypoint_object(
   pipe
   ALIAS
@@ -300,6 +299,13 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.setsid
 )
 
+add_entrypoint_object(
+  sleep
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.sleep
+)
+
 add_entrypoint_object(
   symlink
   ALIAS
@@ -349,6 +355,13 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.unlinkat
 )
 
+add_entrypoint_object(
+  usleep
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.usleep
+)
+
 add_entrypoint_object(
   write
   ALIAS
diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index 49520c1dcf265..0426a8ad84eeb 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -542,6 +542,21 @@ add_entrypoint_object(
     libc.src.__support.OSUtil.osutil
 )
 
+add_entrypoint_object(
+  sleep
+  SRCS
+    sleep.cpp
+  HDRS
+    ../sleep.h
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.types.struct_timespec
+    libc.hdr.types.time_t
+    libc.src.__support.OSUtil.linux.syscall_wrappers.nanosleep
+    libc.src.__support.common
+    libc.src.__support.macros.config
+)
+
 add_entrypoint_object(
   symlink
   SRCS
@@ -639,6 +654,23 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  usleep
+  SRCS
+    usleep.cpp
+  HDRS
+    ../usleep.h
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.types.useconds_t
+    libc.hdr.types.struct_timespec
+    libc.src.__support.OSUtil.linux.syscall_wrappers.nanosleep
+    libc.src.__support.common
+    libc.src.__support.libc_errno
+    libc.src.__support.macros.config
+    libc.src.errno.errno
+)
+
 add_entrypoint_object(
   write
   SRCS
diff --git a/libc/src/unistd/linux/sleep.cpp b/libc/src/unistd/linux/sleep.cpp
new file mode 100644
index 0000000000000..213224deaafb7
--- /dev/null
+++ b/libc/src/unistd/linux/sleep.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Linux implementation of sleep.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/unistd/sleep.h"
+#include "hdr/errno_macros.h"
+#include "hdr/types/struct_timespec.h"
+#include "hdr/types/time_t.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/nanosleep.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+static_assert(sizeof(time_t) == sizeof(int64_t),
+              "32-bit time_t is not supported");
+
+LLVM_LIBC_FUNCTION(unsigned int, sleep, (unsigned int seconds)) {
+  if (seconds == 0)
+    return 0;
+
+  unsigned int remaining = seconds;
+  while (remaining > 0) {
+    // Since time_t is 64-bit and remaining is 32-bit, remaining always fits
+    // into sleep_time without overflow.
+    time_t sleep_time = remaining;
+
+    timespec req = {sleep_time, 0};
+    timespec rem = {0, 0};
+    auto result = linux_syscalls::nanosleep(&req, &rem);
+    if (!result) {
+      if (result.error() == EINTR) {
+        // If nanosleep was interrupted, calculate the remaining unslept time.
+        // tv_nsec is rounded up to the next full second to match POSIX sleep
+        // return value requirements.
+        unsigned int unslept_this_step =
+            static_cast<unsigned int>(rem.tv_sec + (rem.tv_nsec > 0 ? 1 : 0));
+        return static_cast<unsigned int>(remaining - sleep_time) +
+               unslept_this_step;
+      }
+      // For other errors (e.g. ENOSYS), assume we didn't sleep this step.
+      return remaining;
+    }
+    remaining -= sleep_time;
+  }
+  return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/linux/usleep.cpp b/libc/src/unistd/linux/usleep.cpp
new file mode 100644
index 0000000000000..8cb43a3a7efb4
--- /dev/null
+++ b/libc/src/unistd/linux/usleep.cpp
@@ -0,0 +1,43 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Linux implementation of usleep.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/unistd/usleep.h"
+#include "hdr/errno_macros.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/nanosleep.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, usleep, (useconds_t usec)) {
+  // POSIX.1-2001 specifies that usleep should fail with EINVAL if the
+  // argument is greater than or equal to 1,000,000.
+  if (usec >= 1000000) {
+    libc_errno = EINVAL;
+    return -1;
+  }
+  if (usec == 0)
+    return 0;
+
+  timespec req = {0, static_cast<long>(usec * 1000)};
+  auto result = linux_syscalls::nanosleep(&req, nullptr);
+  if (!result) {
+    libc_errno = result.error();
+    return -1;
+  }
+  return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/sleep.h b/libc/src/unistd/sleep.h
new file mode 100644
index 0000000000000..52eb0d7ce7f49
--- /dev/null
+++ b/libc/src/unistd/sleep.h
@@ -0,0 +1,25 @@
+//===---------------------------------------------------------------...
[truncated]

``````````

</details>


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


More information about the libc-commits mailing list