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

Pavel Labath via libc-commits libc-commits at lists.llvm.org
Tue Aug 4 04:36:20 PDT 2026


https://github.com/labath created https://github.com/llvm/llvm-project/pull/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.

>From 04b9e9d010129ff0f1ce631f1389917d88a5e61a Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Tue, 4 Aug 2026 11:05:47 +0000
Subject: [PATCH] [libc] Implement sleep and usleep for Linux

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

Co-authored-by: Jeff Bailey <jbailey at raspberryginger.com>
---
 libc/config/linux/aarch64/entrypoints.txt     |  2 +
 libc/config/linux/riscv/entrypoints.txt       |  2 +
 libc/config/linux/x86_64/entrypoints.txt      |  2 +
 libc/hdr/types/CMakeLists.txt                 |  9 +++-
 libc/hdr/types/useconds_t.h                   | 27 ++++++++++
 libc/include/CMakeLists.txt                   |  1 +
 libc/include/unistd.yaml                      | 13 +++++
 .../linux/syscall_wrappers/CMakeLists.txt     | 15 +++++-
 .../OSUtil/linux/syscall_wrappers/nanosleep.h | 51 +++++++++++++++++++
 libc/src/time/linux/CMakeLists.txt            |  8 +--
 libc/src/time/linux/nanosleep.cpp             | 34 ++++---------
 libc/src/unistd/CMakeLists.txt                | 15 +++++-
 libc/src/unistd/linux/CMakeLists.txt          | 32 ++++++++++++
 libc/src/unistd/linux/sleep.cpp               | 41 +++++++++++++++
 libc/src/unistd/linux/usleep.cpp              | 36 +++++++++++++
 libc/src/unistd/sleep.h                       | 25 +++++++++
 libc/src/unistd/usleep.h                      | 26 ++++++++++
 libc/test/src/time/CMakeLists.txt             |  3 +-
 libc/test/src/unistd/CMakeLists.txt           | 28 ++++++++++
 libc/test/src/unistd/sleep_test.cpp           | 40 +++++++++++++++
 libc/test/src/unistd/usleep_test.cpp          | 45 ++++++++++++++++
 21 files changed, 424 insertions(+), 31 deletions(-)
 create mode 100644 libc/hdr/types/useconds_t.h
 create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/nanosleep.h
 create mode 100644 libc/src/unistd/linux/sleep.cpp
 create mode 100644 libc/src/unistd/linux/usleep.cpp
 create mode 100644 libc/src/unistd/sleep.h
 create mode 100644 libc/src/unistd/usleep.h
 create mode 100644 libc/test/src/unistd/sleep_test.cpp
 create mode 100644 libc/test/src/unistd/usleep_test.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index c2c037c51ea08..1d5244b9c443e 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 4e3a383baa3ed..0f7822b36a761 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 5e848146594bb..7a9e741310c6a 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 23dbd98d52203..f56ddda2dc9fe 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 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 add1411a9f95c..b77f149b2f65d 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 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 a45641483bbef..2b22bb8e733de 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 0000000000000..694becbd395b5
--- /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 4b4b84277e7bf..e605b53b9eb29 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 7e7a551d9539e..c31f0443b1210 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -541,6 +541,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
@@ -638,6 +653,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..5f75dfd76edde
--- /dev/null
+++ b/libc/src/unistd/linux/sleep.cpp
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// 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)) {
+
+  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 0000000000000..9e87f6708057b
--- /dev/null
+++ b/libc/src/unistd/linux/usleep.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 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)) {
+  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 0000000000000..52eb0d7ce7f49
--- /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 0000000000000..f9def0b304c35
--- /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 ad5017369b0a7..e4d7dce066c7b 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 ddd8729933b90..3290fbdfb0e25 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,21 @@ add_libc_unittest(
     libc.test.UnitTest.ErrnoSetterMatcher
 )
 
+add_libc_unittest(
+  usleep_test
+  SUITE
+    libc_unistd_unittests
+  SRCS
+    usleep_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    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 0000000000000..a126a7e9e76e2
--- /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 0000000000000..61a9557fa4962
--- /dev/null
+++ b/libc/test/src/unistd/usleep_test.cpp
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/errno_macros.h"
+#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/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+
+TEST(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(LlvmLibcUsleepTest, Zero) { ASSERT_EQ(LIBC_NAMESPACE::usleep(0), 0); }



More information about the libc-commits mailing list