[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