[libc-commits] [libc] 8877db4 - [libc] Implement sleep and usleep for Linux (#213912)

via libc-commits libc-commits at lists.llvm.org
Thu Aug 6 00:14:46 PDT 2026


Author: Pavel Labath
Date: 2026-08-06T09:14:41+02:00
New Revision: 8877db40d77e1a2e1cc3cb3a01bcf963bd4cda01

URL: https://github.com/llvm/llvm-project/commit/8877db40d77e1a2e1cc3cb3a01bcf963bd4cda01
DIFF: https://github.com/llvm/llvm-project/commit/8877db40d77e1a2e1cc3cb3a01bcf963bd4cda01.diff

LOG: [libc] Implement sleep and usleep for Linux (#213912)

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

Fixes #214293.

Co-authored-by: Jeff Bailey <jbailey at raspberryginger.com>

Added: 
    libc/hdr/types/useconds_t.h
    libc/src/__support/OSUtil/linux/syscall_wrappers/nanosleep.h
    libc/src/unistd/linux/sleep.cpp
    libc/src/unistd/linux/usleep.cpp
    libc/src/unistd/sleep.h
    libc/src/unistd/usleep.h
    libc/test/src/unistd/sleep_test.cpp
    libc/test/src/unistd/usleep_test.cpp

Modified: 
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/riscv/entrypoints.txt
    libc/config/linux/x86_64/entrypoints.txt
    libc/hdr/types/CMakeLists.txt
    libc/include/CMakeLists.txt
    libc/include/unistd.yaml
    libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
    libc/src/time/linux/CMakeLists.txt
    libc/src/time/linux/nanosleep.cpp
    libc/src/unistd/CMakeLists.txt
    libc/src/unistd/linux/CMakeLists.txt
    libc/test/src/time/CMakeLists.txt
    libc/test/src/unistd/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index c2c037c51ea08d..1d5244b9c443e3 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -411,12 +411,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 4e3a383baa3ede..0f7822b36a761b 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -447,12 +447,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 5e848146594bb9..7a9e741310c6ac 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -452,12 +452,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/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index 23dbd98d52203b..f56ddda2dc9fe4 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -298,6 +298,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
@@ -711,7 +719,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 00000000000000..c6e26bdbf81ef2
--- /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 add1411a9f95ce..b77f149b2f65de 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -490,6 +490,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
 )
 

diff  --git a/libc/include/unistd.yaml b/libc/include/unistd.yaml
index c1ae4567bfc026..4b3703af7798ea 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 a45641483bbef2..2b22bb8e733de3 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -745,7 +745,6 @@ add_header_library(
     libc.include.sys_syscall
 )
 
-
 add_header_library(
   dup
   HDRS
@@ -927,3 +926,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.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.include.sys_syscall
+)

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 00000000000000..694becbd395b58
--- /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/time_macros.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_checked
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.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 4b4b84277e7bf1..e605b53b9eb29c 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 15b119ead20c6f..872a1b27110dee 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 c8f1b8d3ef15f4..98444e7b31631e 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 7e7a551d9539e7..7a8b51e9514aaa 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -541,6 +541,20 @@ add_entrypoint_object(
     libc.src.__support.OSUtil.osutil
 )
 
+add_entrypoint_object(
+  sleep
+  SRCS
+    sleep.cpp
+  HDRS
+    ../sleep.h
+  DEPENDS
+    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
@@ -638,6 +652,22 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  usleep
+  SRCS
+    usleep.cpp
+  HDRS
+    ../usleep.h
+  DEPENDS
+    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 00000000000000..8c2a85043e1807
--- /dev/null
+++ b/libc/src/unistd/linux/sleep.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/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 {
+
+LLVM_LIBC_FUNCTION(unsigned int, sleep, (unsigned int seconds)) {
+  static_assert(sizeof(unsigned int) <= sizeof(time_t), "Avoids overflow");
+  struct timespec req = {seconds, 0};
+  struct timespec rem = {};
+  ErrorOr<int> result = linux_syscalls::nanosleep(&req, &rem);
+  if (!result) {
+    // Cast does not lose information as `remaining` cannot be greater than
+    // `seconds`.
+    return static_cast<unsigned int>(rem.tv_sec);
+  }
+  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 00000000000000..1eadc44bb8005b
--- /dev/null
+++ b/libc/src/unistd/linux/usleep.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/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)) {
+  static_assert(sizeof(useconds_t) >= 4, "Avoids overflow in ns computation");
+  constexpr useconds_t US_IN_S = 1'000'000;
+  struct timespec ts = {usec / US_IN_S, (usec % US_IN_S) * 1000};
+  auto result = linux_syscalls::nanosleep(&ts, 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 00000000000000..52eb0d7ce7f493
--- /dev/null
+++ b/libc/src/unistd/sleep.h
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 sleep.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_UNISTD_SLEEP_H
+#define LLVM_LIBC_SRC_UNISTD_SLEEP_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned int sleep(unsigned int seconds);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UNISTD_SLEEP_H

diff  --git a/libc/src/unistd/usleep.h b/libc/src/unistd/usleep.h
new file mode 100644
index 00000000000000..f9def0b304c35d
--- /dev/null
+++ b/libc/src/unistd/usleep.h
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 usleep.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_UNISTD_USLEEP_H
+#define LLVM_LIBC_SRC_UNISTD_USLEEP_H
+
+#include "hdr/types/useconds_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int usleep(useconds_t usec);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UNISTD_USLEEP_H

diff  --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt
index ad5017369b0a77..e4d7dce066c7b0 100644
--- a/libc/test/src/time/CMakeLists.txt
+++ b/libc/test/src/time/CMakeLists.txt
@@ -209,9 +209,10 @@ add_libc_test(
   SRCS
     nanosleep_test.cpp
   DEPENDS
-    libc.include.time
     libc.hdr.types.struct_timespec
+    libc.hdr.signal_macros
     libc.src.time.nanosleep
+    libc.src.__support.macros.config
     libc.test.UnitTest.ErrnoCheckingTest
 )
 

diff  --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index 7d92fa258214b7..4cdf5d0e4fc606 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -403,6 +403,19 @@ add_libc_unittest(
     libc.src.unistd.setsid
 )
 
+add_libc_unittest(
+  sleep_test
+  SUITE
+    libc_unistd_unittests
+  SRCS
+    sleep_test.cpp
+  DEPENDS
+    libc.hdr.time_macros
+    libc.hdr.types.struct_timespec
+    libc.src.__support.time.clock_gettime
+    libc.src.unistd.sleep
+)
+
 add_libc_unittest(
   symlink_test
   SUITE
@@ -495,6 +508,20 @@ add_libc_unittest(
     libc.test.UnitTest.ErrnoSetterMatcher
 )
 
+add_libc_unittest(
+  usleep_test
+  SUITE
+    libc_unistd_unittests
+  SRCS
+    usleep_test.cpp
+  DEPENDS
+    libc.hdr.time_macros
+    libc.hdr.types.struct_timespec
+    libc.src.__support.time.clock_gettime
+    libc.src.unistd.usleep
+    libc.test.UnitTest.ErrnoCheckingTest
+)
+
 add_libc_unittest(
   gethostname_test
   SUITE

diff  --git a/libc/test/src/unistd/sleep_test.cpp b/libc/test/src/unistd/sleep_test.cpp
new file mode 100644
index 00000000000000..a126a7e9e76e26
--- /dev/null
+++ b/libc/test/src/unistd/sleep_test.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Unittests for sleep.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/time_macros.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/time/clock_gettime.h"
+#include "src/unistd/sleep.h"
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcSleepTest, SmokeTest) {
+  struct timespec start, end;
+  ASSERT_TRUE(LIBC_NAMESPACE::internal::clock_gettime(CLOCK_MONOTONIC, &start)
+                  .has_value());
+
+  // Sleep for 1 second.
+  ASSERT_EQ(LIBC_NAMESPACE::sleep(1), 0u);
+
+  ASSERT_TRUE(LIBC_NAMESPACE::internal::clock_gettime(CLOCK_MONOTONIC, &end)
+                  .has_value());
+
+  // Calculate elapsed time in seconds.
+  uint64_t elapsed_sec = static_cast<uint64_t>(end.tv_sec - start.tv_sec);
+  if (end.tv_nsec < start.tv_nsec)
+    --elapsed_sec;
+
+  // It should have slept for at least 1 second.
+  ASSERT_GE(elapsed_sec, uint64_t{1});
+}
+
+TEST(LlvmLibcSleepTest, Zero) { ASSERT_EQ(LIBC_NAMESPACE::sleep(0), 0u); }

diff  --git a/libc/test/src/unistd/usleep_test.cpp b/libc/test/src/unistd/usleep_test.cpp
new file mode 100644
index 00000000000000..18a797c28eccb6
--- /dev/null
+++ b/libc/test/src/unistd/usleep_test.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
+/// Unittests for usleep.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/time_macros.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/time/clock_gettime.h"
+#include "src/unistd/usleep.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcUsleepTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcUsleepTest, SmokeTest) {
+  struct timespec start, end;
+  ASSERT_TRUE(LIBC_NAMESPACE::internal::clock_gettime(CLOCK_MONOTONIC, &start)
+                  .has_value());
+
+  // Sleep for 10000 microseconds (10 ms).
+  ASSERT_EQ(LIBC_NAMESPACE::usleep(10000), 0);
+
+  ASSERT_TRUE(LIBC_NAMESPACE::internal::clock_gettime(CLOCK_MONOTONIC, &end)
+                  .has_value());
+
+  // Calculate elapsed time in nanoseconds.
+  int64_t 
diff _sec = end.tv_sec - start.tv_sec;
+  int64_t 
diff _nsec = end.tv_nsec - start.tv_nsec;
+  int64_t elapsed_ns = 
diff _sec * 1000000000LL + 
diff _nsec;
+
+  // It should have slept for at least 10 ms (10,000,000 ns).
+  ASSERT_GE(elapsed_ns, int64_t{10000000});
+}
+
+TEST_F(LlvmLibcUsleepTest, Zero) { ASSERT_EQ(LIBC_NAMESPACE::usleep(0), 0); }


        


More information about the libc-commits mailing list