[libc-commits] [libc] [libc] Implement ppoll in poll (PR #225767)
Aman Maurya via libc-commits
libc-commits at lists.llvm.org
Wed Sep 23 07:26:14 PDT 2026
https://github.com/amanmaurya92 updated https://github.com/llvm/llvm-project/pull/225767
>From e2d847bbcbd37c45d55aa459705688004c5d2689 Mon Sep 17 00:00:00 2001
From: amanmaurya92 <amanmaurya9209 at gmail.com>
Date: Wed, 23 Sep 2026 18:38:40 +0530
Subject: [PATCH] [libc] Implement ppoll in poll
Assisted by Antigravity and Gemini.
---
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/hdr/CMakeLists.txt | 8 +++
libc/hdr/poll_macros.h | 22 ++++++
libc/include/CMakeLists.txt | 2 +
libc/include/poll.yaml | 11 +++
libc/src/poll/CMakeLists.txt | 7 ++
libc/src/poll/linux/CMakeLists.txt | 17 +++++
libc/src/poll/linux/ppoll.cpp | 57 +++++++++++++++
libc/src/poll/ppoll.h | 25 +++++++
libc/test/src/poll/CMakeLists.txt | 22 ++++++
libc/test/src/poll/ppoll_test.cpp | 86 +++++++++++++++++++++++
13 files changed, 260 insertions(+)
create mode 100644 libc/hdr/poll_macros.h
create mode 100644 libc/src/poll/linux/ppoll.cpp
create mode 100644 libc/src/poll/ppoll.h
create mode 100644 libc/test/src/poll/ppoll_test.cpp
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 479a70846714f0..e4cfff496d59a6 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -57,6 +57,7 @@ set(TARGET_LIBC_ENTRYPOINTS
# poll.h entrypoints
libc.src.poll.poll
+ libc.src.poll.ppoll
# pwd.h entrypoints
libc.src.pwd.endpwent
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index c841b28d9e544e..7f1a82b77b395e 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -76,6 +76,7 @@ set(TARGET_LIBC_ENTRYPOINTS
# poll.h entrypoints
libc.src.poll.poll
+ libc.src.poll.ppoll
# pwd.h entrypoints
libc.src.pwd.endpwent
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 786a1ea0743055..7733a4fb1de48d 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -76,6 +76,7 @@ set(TARGET_LIBC_ENTRYPOINTS
# poll.h entrypoints
libc.src.poll.poll
+ libc.src.poll.ppoll
# pwd.h entrypoints
libc.src.pwd.endpwent
diff --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt
index fa01bc55785daa..64efe4968b51ac 100644
--- a/libc/hdr/CMakeLists.txt
+++ b/libc/hdr/CMakeLists.txt
@@ -120,6 +120,14 @@ add_proxy_header_library(
libc.include.llvm-libc-macros.netinet_in_macros
)
+add_proxy_header_library(
+ poll_macros
+ HDRS
+ poll_macros.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-macros.poll-macros
+)
+
add_proxy_header_library(
pthread_macros
HDRS
diff --git a/libc/hdr/poll_macros.h b/libc/hdr/poll_macros.h
new file mode 100644
index 00000000000000..f24d93956ca231
--- /dev/null
+++ b/libc/hdr/poll_macros.h
@@ -0,0 +1,22 @@
+//===-- Definition of macros from poll.h ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_POLL_MACROS_H
+#define LLVM_LIBC_HDR_POLL_MACROS_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-macros/poll-macros.h"
+
+#else // Overlay mode
+
+#include <poll.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_POLL_MACROS_H
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index f63e7e3dc6a734..e46f8c163ef2d2 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -1257,6 +1257,8 @@ add_header_macro(
DEPENDS
.llvm-libc-types.struct_pollfd
.llvm-libc-types.nfds_t
+ .llvm-libc-types.struct_timespec
+ .llvm-libc-types.sigset_t
.llvm-libc-macros.poll-macros
)
diff --git a/libc/include/poll.yaml b/libc/include/poll.yaml
index bb7d99e87aa078..085445da1304f0 100644
--- a/libc/include/poll.yaml
+++ b/libc/include/poll.yaml
@@ -25,6 +25,8 @@ macros:
types:
- type_name: struct_pollfd
- type_name: nfds_t
+ - type_name: struct_timespec
+ - type_name: sigset_t
enums: []
functions:
- name: poll
@@ -35,3 +37,12 @@ functions:
- type: struct pollfd *
- type: nfds_t
- type: int
+ - name: ppoll
+ standards:
+ - posix
+ return_type: int
+ arguments:
+ - type: struct pollfd *
+ - type: nfds_t
+ - type: const struct timespec *
+ - type: const sigset_t *
diff --git a/libc/src/poll/CMakeLists.txt b/libc/src/poll/CMakeLists.txt
index 65fbe46bb46128..c5bd970bb9a74e 100644
--- a/libc/src/poll/CMakeLists.txt
+++ b/libc/src/poll/CMakeLists.txt
@@ -8,3 +8,10 @@ add_entrypoint_object(
DEPENDS
.${LIBC_TARGET_OS}.poll
)
+
+add_entrypoint_object(
+ ppoll
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.ppoll
+)
diff --git a/libc/src/poll/linux/CMakeLists.txt b/libc/src/poll/linux/CMakeLists.txt
index a9ef596c36c893..12871edf630ec4 100644
--- a/libc/src/poll/linux/CMakeLists.txt
+++ b/libc/src/poll/linux/CMakeLists.txt
@@ -12,3 +12,20 @@ add_entrypoint_object(
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
+
+add_entrypoint_object(
+ ppoll
+ SRCS
+ ppoll.cpp
+ HDRS
+ ../ppoll.h
+ DEPENDS
+ libc.hdr.signal_macros
+ libc.hdr.types.nfds_t
+ libc.hdr.types.sigset_t
+ libc.hdr.types.struct_pollfd
+ libc.hdr.types.struct_timespec
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
diff --git a/libc/src/poll/linux/ppoll.cpp b/libc/src/poll/linux/ppoll.cpp
new file mode 100644
index 00000000000000..245ba4acd41e51
--- /dev/null
+++ b/libc/src/poll/linux/ppoll.cpp
@@ -0,0 +1,57 @@
+//===-- Linux implementation of ppoll ------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/poll/ppoll.h"
+
+#include "hdr/signal_macros.h"
+#include "hdr/types/nfds_t.h"
+#include "hdr/types/sigset_t.h"
+#include "hdr/types/struct_pollfd.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/OSUtil/syscall.h" // syscall_impl
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+#include <sys/syscall.h> // SYS_ppoll, SYS_ppoll_time64
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, ppoll,
+ (struct pollfd * fds, nfds_t nfds,
+ const struct timespec *tmo_p, const sigset_t *sigmask)) {
+ timespec ts;
+ timespec *tsp = nullptr;
+ if (tmo_p != nullptr) {
+ ts = *tmo_p;
+ tsp = &ts;
+ }
+
+#if defined(SYS_ppoll_time64)
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_ppoll_time64, fds, nfds, tsp,
+ sigmask, NSIG / 8);
+#elif defined(SYS_ppoll)
+ static_assert(
+ sizeof(timespec::tv_nsec) == sizeof(long),
+ "This legacy syscall fallback is only safe on platforms where tv_nsec "
+ "matches the register size (long). It is unsafe on 32-bit platforms "
+ "with 64-bit tv_nsec.");
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_ppoll, fds, nfds, tsp,
+ sigmask, NSIG / 8);
+#else
+#error "ppoll and ppoll_time64 syscalls not available."
+#endif
+
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/poll/ppoll.h b/libc/src/poll/ppoll.h
new file mode 100644
index 00000000000000..71b90e4ac69c64
--- /dev/null
+++ b/libc/src/poll/ppoll.h
@@ -0,0 +1,25 @@
+//===-- Implementation header for ppoll -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_POLL_PPOLL_H
+#define LLVM_LIBC_SRC_POLL_PPOLL_H
+
+#include "hdr/types/nfds_t.h"
+#include "hdr/types/sigset_t.h"
+#include "hdr/types/struct_pollfd.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p,
+ const sigset_t *sigmask);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_POLL_PPOLL_H
diff --git a/libc/test/src/poll/CMakeLists.txt b/libc/test/src/poll/CMakeLists.txt
index b6f18c5dbf4bfb..5097f05bbddb90 100644
--- a/libc/test/src/poll/CMakeLists.txt
+++ b/libc/test/src/poll/CMakeLists.txt
@@ -12,3 +12,25 @@ add_libc_test(
libc.src.poll.poll
libc.test.UnitTest.ErrnoCheckingTest
)
+
+add_libc_test(
+ ppoll_test
+ SUITE
+ libc_poll_unittests
+ SRCS
+ ppoll_test.cpp
+ DEPENDS
+ libc.hdr.limits_macros
+ libc.hdr.poll_macros
+ libc.hdr.types.sigset_t
+ libc.hdr.types.struct_pollfd
+ libc.hdr.types.struct_timespec
+ libc.src.__support.CPP.scope
+ libc.src.errno.errno
+ libc.src.poll.ppoll
+ libc.src.unistd.close
+ libc.src.unistd.pipe
+ libc.src.unistd.read
+ libc.src.unistd.write
+ libc.test.UnitTest.ErrnoCheckingTest
+)
diff --git a/libc/test/src/poll/ppoll_test.cpp b/libc/test/src/poll/ppoll_test.cpp
new file mode 100644
index 00000000000000..f6fe9941645866
--- /dev/null
+++ b/libc/test/src/poll/ppoll_test.cpp
@@ -0,0 +1,86 @@
+//===-- Unittests for ppoll -----------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "hdr/limits_macros.h"
+#include "hdr/poll_macros.h"
+#include "hdr/types/sigset_t.h"
+#include "hdr/types/struct_pollfd.h"
+#include "hdr/types/struct_timespec.h"
+#include "src/__support/CPP/scope.h"
+#include "src/poll/ppoll.h"
+#include "src/unistd/close.h"
+#include "src/unistd/pipe.h"
+#include "src/unistd/read.h"
+#include "src/unistd/write.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcPPollTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcPPollTest, SmokeTest) {
+ timespec ts{0, 0};
+ int ret = LIBC_NAMESPACE::ppoll(nullptr, 0, &ts, nullptr);
+ ASSERT_ERRNO_SUCCESS();
+ ASSERT_EQ(0, ret);
+}
+
+TEST_F(LlvmLibcPPollTest, SmokeFailureTest) {
+ int ret = LIBC_NAMESPACE::ppoll(nullptr, UINT_MAX, nullptr, nullptr);
+ ASSERT_ERRNO_EQ(EINVAL);
+ ASSERT_EQ(-1, ret);
+}
+
+TEST_F(LlvmLibcPPollTest, TimeoutNotMutated) {
+ const timespec orig_ts{0, 0};
+ timespec ts = orig_ts;
+ int ret = LIBC_NAMESPACE::ppoll(nullptr, 0, &ts, nullptr);
+ ASSERT_ERRNO_SUCCESS();
+ ASSERT_EQ(0, ret);
+ ASSERT_EQ(ts.tv_sec, orig_ts.tv_sec);
+ ASSERT_EQ(ts.tv_nsec, orig_ts.tv_nsec);
+}
+
+TEST_F(LlvmLibcPPollTest, WithSigmask) {
+ timespec ts{0, 0};
+ sigset_t mask{};
+ int ret = LIBC_NAMESPACE::ppoll(nullptr, 0, &ts, &mask);
+ ASSERT_ERRNO_SUCCESS();
+ ASSERT_EQ(0, ret);
+}
+
+TEST_F(LlvmLibcPPollTest, PipeReadiness) {
+ int pipefd[2];
+ ASSERT_EQ(LIBC_NAMESPACE::pipe(pipefd), 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ LIBC_NAMESPACE::cpp::scope_exit cleanup([&] {
+ LIBC_NAMESPACE::close(pipefd[0]);
+ LIBC_NAMESPACE::close(pipefd[1]);
+ });
+
+ pollfd pfd{pipefd[0], POLLIN, 0};
+ timespec ts{0, 0};
+ int ret = LIBC_NAMESPACE::ppoll(&pfd, 1, &ts, nullptr);
+ ASSERT_ERRNO_SUCCESS();
+ ASSERT_EQ(0, ret);
+ ASSERT_EQ(0, static_cast<int>(pfd.revents));
+
+ char c = 'x';
+ ASSERT_EQ(LIBC_NAMESPACE::write(pipefd[1], &c, 1), static_cast<ssize_t>(1));
+ ASSERT_ERRNO_SUCCESS();
+
+ ret = LIBC_NAMESPACE::ppoll(&pfd, 1, &ts, nullptr);
+ ASSERT_ERRNO_SUCCESS();
+ ASSERT_EQ(1, ret);
+ ASSERT_EQ(POLLIN, pfd.revents & POLLIN);
+
+ char buf = 0;
+ ASSERT_EQ(LIBC_NAMESPACE::read(pipefd[0], &buf, 1), static_cast<ssize_t>(1));
+ ASSERT_ERRNO_SUCCESS();
+ ASSERT_EQ('x', buf);
+}
More information about the libc-commits
mailing list