[libc-commits] [libc] [libc][time] Implement timer_create. (PR #217920)

via libc-commits libc-commits at lists.llvm.org
Fri Aug 21 10:47:29 PDT 2026


https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/217920

>From bebb71142c288086e504ea4a52f845f8089262ea Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 21 Aug 2026 14:10:33 +0000
Subject: [PATCH 1/2] [libc][time] Implement timer_create.

---
 libc/config/linux/aarch64/entrypoints.txt     |  1 +
 libc/config/linux/riscv/entrypoints.txt       |  1 +
 libc/config/linux/x86_64/entrypoints.txt      |  1 +
 libc/include/time.yaml                        |  8 ++
 .../linux/syscall_wrappers/CMakeLists.txt     | 16 ++++
 .../linux/syscall_wrappers/timer_create.h     | 81 +++++++++++++++++++
 libc/src/time/CMakeLists.txt                  |  7 ++
 libc/src/time/linux/CMakeLists.txt            | 17 ++++
 libc/src/time/linux/timer_create.cpp          | 33 ++++++++
 libc/src/time/timer_create.h                  | 29 +++++++
 libc/test/src/time/CMakeLists.txt             | 19 +++++
 libc/test/src/time/timer_create_test.cpp      | 78 ++++++++++++++++++
 12 files changed, 291 insertions(+)
 create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/timer_create.h
 create mode 100644 libc/src/time/linux/timer_create.cpp
 create mode 100644 libc/src/time/timer_create.h
 create mode 100644 libc/test/src/time/timer_create_test.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 468b00efad35e..08ecf19bdba86 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1330,6 +1330,7 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.time.nanosleep
     libc.src.time.time
     libc.src.time.timespec_get
+    libc.src.time.timer_create
 
     # unistd.h entrypoints
     libc.src.unistd.__llvm_libc_syscall
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index ca6a3d872c71d..50dfdc0985e5d 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1525,6 +1525,7 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.time.strftime_l
     libc.src.time.time
     libc.src.time.timespec_get
+    libc.src.time.timer_create
 
     # locale.h entrypoints
     libc.src.locale.localeconv
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 9f7da5e10b66c..8f6d7bce8abb7 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1539,6 +1539,7 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.time.strftime_l
     libc.src.time.time
     libc.src.time.timespec_get
+    libc.src.time.timer_create
 
     # locale.h entrypoints
     libc.src.locale.localeconv
diff --git a/libc/include/time.yaml b/libc/include/time.yaml
index a7c0cc7cc3e8e..71ea97dabb522 100644
--- a/libc/include/time.yaml
+++ b/libc/include/time.yaml
@@ -154,3 +154,11 @@ functions:
     arguments:
       - type: struct timespec *
       - type: int
+  - name: timer_create
+    standards:
+      - posix
+    return_type: int
+    arguments:
+      - type: clockid_t
+      - type: struct sigevent *__restrict
+      - type: timer_t *__restrict
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index 0041db9a24cbd..b41bc16f0438a 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -1005,3 +1005,19 @@ add_header_library(
     libc.src.__support.macros.config
     libc.include.sys_syscall
 )
+
+add_header_library(
+  timer_create
+  HDRS
+    timer_create.h
+  DEPENDS
+    libc.hdr.types.clockid_t
+    libc.hdr.types.pid_t
+    libc.hdr.types.struct_sigevent
+    libc.hdr.types.timer_t
+    libc.include.sys_syscall
+    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/timer_create.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/timer_create.h
new file mode 100644
index 0000000000000..9124d8c250bb7
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/timer_create.h
@@ -0,0 +1,81 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 timer_create syscall wrapper.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_TIMER_CREATE_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_TIMER_CREATE_H
+
+#include "hdr/types/clockid_t.h"
+#include "hdr/types/pid_t.h"
+#include "hdr/types/struct_sigevent.h"
+#include "hdr/types/timer_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // For syscall_checked
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+#define __SIGEV_MAX_SIZE 64
+#define __SIGEV_PAD_SIZE                                                       \
+  ((__SIGEV_MAX_SIZE - sizeof(int) * 2 - sizeof(sigval)) / sizeof(int))
+
+// Linux kernel ABI layout for struct sigevent (64 bytes total):
+// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/siginfo.h
+// https://man7.org/linux/man-pages/man2/timer_create.2.html
+struct KernelSigevent {
+  sigval sigev_value;
+  int sigev_signo;
+  int sigev_notify;
+  union {
+    int _pad[__SIGEV_PAD_SIZE];
+    pid_t _tid;
+    struct {
+      void (*_function)(sigval);
+      void *_attribute;
+    } _sigev_thread;
+  } _sigev_un;
+
+  LIBC_INLINE KernelSigevent() = default;
+
+  LIBC_INLINE KernelSigevent(const sigevent &sev) {
+    sigev_value = sev.sigev_value;
+    sigev_signo = sev.sigev_signo;
+    sigev_notify = sev.sigev_notify;
+    _sigev_un._tid = sev.sigev_notify_thread_id;
+    _sigev_un._sigev_thread._function = sev.sigev_notify_function;
+    _sigev_un._sigev_thread._attribute = sev.sigev_notify_attributes;
+  }
+};
+
+#undef __SIGEV_MAX_SIZE
+#undef __SIGEV_PAD_SIZE
+
+LIBC_INLINE ErrorOr<int> timer_create(clockid_t clockid, const sigevent *sevp,
+                                      timer_t *timerid) {
+#ifdef SYS_timer_create
+  if (!sevp)
+    return syscall_checked<int>(SYS_timer_create, clockid, nullptr, timerid);
+
+  KernelSigevent ksev(*sevp);
+  return syscall_checked<int>(SYS_timer_create, clockid, &ksev, timerid);
+#else
+#error "SYS_timer_create syscall not available."
+#endif
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_TIMER_CREATE_H
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index 8a4c71968712c..9006a35c00bc7 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -299,3 +299,10 @@ add_entrypoint_object(
   DEPENDS
     .${LIBC_TARGET_OS}.clock_settime
 )
+
+add_entrypoint_object(
+  timer_create
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.timer_create
+)
diff --git a/libc/src/time/linux/CMakeLists.txt b/libc/src/time/linux/CMakeLists.txt
index f3cd822498a57..1c0ec1c67c31a 100644
--- a/libc/src/time/linux/CMakeLists.txt
+++ b/libc/src/time/linux/CMakeLists.txt
@@ -72,3 +72,20 @@ add_entrypoint_object(
     libc.src.__support.time.clock_settime
     libc.src.errno.errno
 )
+
+add_entrypoint_object(
+  timer_create
+  SRCS
+    timer_create.cpp
+  HDRS
+    ../timer_create.h
+  DEPENDS
+    libc.hdr.types.clockid_t
+    libc.hdr.types.struct_sigevent
+    libc.hdr.types.timer_t
+    libc.src.__support.OSUtil.linux.syscall_wrappers.timer_create
+    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/timer_create.cpp b/libc/src/time/linux/timer_create.cpp
new file mode 100644
index 0000000000000..a5ca734c10da6
--- /dev/null
+++ b/libc/src/time/linux/timer_create.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 timer_create function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/time/timer_create.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/timer_create.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, timer_create,
+                   (clockid_t clockid, sigevent *__restrict sevp,
+                    timer_t *__restrict timerid)) {
+  auto result = linux_syscalls::timer_create(clockid, sevp, timerid);
+  if (!result) {
+    libc_errno = result.error();
+    return -1;
+  }
+  return result.value();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/timer_create.h b/libc/src/time/timer_create.h
new file mode 100644
index 0000000000000..c8466536b7d4e
--- /dev/null
+++ b/libc/src/time/timer_create.h
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 timer_create function.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_TIME_TIMER_CREATE_H
+#define LLVM_LIBC_SRC_TIME_TIMER_CREATE_H
+
+#include "hdr/types/clockid_t.h"
+#include "hdr/types/struct_sigevent.h"
+#include "hdr/types/timer_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int timer_create(clockid_t clockid, sigevent *__restrict sevp,
+                 timer_t *__restrict timerid);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_TIME_TIMER_CREATE_H
diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt
index 58f19ebf0d060..adb61d2f6633b 100644
--- a/libc/test/src/time/CMakeLists.txt
+++ b/libc/test/src/time/CMakeLists.txt
@@ -143,6 +143,25 @@ add_libc_test(
     libc.test.UnitTest.ErrnoCheckingTest
 )
 
+add_libc_test(
+  timer_create_test
+  SUITE
+    libc_time_unittests
+  SRCS
+    timer_create_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.signal_macros
+    libc.hdr.time_macros
+    libc.hdr.types.clockid_t
+    libc.hdr.types.struct_sigevent
+    libc.hdr.types.timer_t
+    libc.src.__support.OSUtil.osutil
+    libc.src.time.timer_create
+    libc.test.UnitTest.ErrnoCheckingTest
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
+
 add_libc_test(
   difftime_test
   SUITE
diff --git a/libc/test/src/time/timer_create_test.cpp b/libc/test/src/time/timer_create_test.cpp
new file mode 100644
index 0000000000000..339bede11de66
--- /dev/null
+++ b/libc/test/src/time/timer_create_test.cpp
@@ -0,0 +1,78 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 timer_create.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "hdr/signal_macros.h"
+#include "hdr/time_macros.h"
+#include "hdr/types/clockid_t.h"
+#include "hdr/types/struct_sigevent.h"
+#include "hdr/types/timer_t.h"
+#include "src/__support/OSUtil/syscall.h"
+#include "src/time/timer_create.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+#include <sys/syscall.h>
+
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::any_of;
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+using LlvmLibcTimerCreateTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcTimerCreateTest, NullSigevent) {
+  timer_t timerid;
+  ASSERT_THAT(LIBC_NAMESPACE::timer_create(CLOCK_REALTIME, nullptr, &timerid),
+              Succeeds(0));
+
+#ifdef SYS_timer_delete
+  LIBC_NAMESPACE::syscall_impl<int>(SYS_timer_delete, timerid);
+#endif
+}
+
+TEST_F(LlvmLibcTimerCreateTest, ValidSigeventSigevNone) {
+  struct sigevent se;
+  se.sigev_notify = SIGEV_NONE;
+  timer_t timerid;
+  ASSERT_THAT(LIBC_NAMESPACE::timer_create(CLOCK_MONOTONIC, &se, &timerid),
+              Succeeds(0));
+
+#ifdef SYS_timer_delete
+  LIBC_NAMESPACE::syscall_impl<int>(SYS_timer_delete, timerid);
+#endif
+}
+
+TEST_F(LlvmLibcTimerCreateTest, ValidSigeventSigevSignal) {
+  struct sigevent se;
+  se.sigev_notify = SIGEV_SIGNAL;
+  se.sigev_signo = SIGALRM;
+  se.sigev_value.sival_int = 42;
+  timer_t timerid;
+  ASSERT_THAT(LIBC_NAMESPACE::timer_create(CLOCK_REALTIME, &se, &timerid),
+              Succeeds(0));
+
+#ifdef SYS_timer_delete
+  LIBC_NAMESPACE::syscall_impl<int>(SYS_timer_delete, timerid);
+#endif
+}
+
+TEST_F(LlvmLibcTimerCreateTest, InvalidClockId) {
+  timer_t timerid;
+  ASSERT_THAT(LIBC_NAMESPACE::timer_create(static_cast<clockid_t>(-1), nullptr,
+                                           &timerid),
+              Fails(EINVAL));
+}
+
+TEST_F(LlvmLibcTimerCreateTest, NullTimerId) {
+  ASSERT_THAT(LIBC_NAMESPACE::timer_create(CLOCK_REALTIME, nullptr, nullptr),
+              Fails(any_of(EINVAL, EFAULT)));
+}

>From af9089dff8fd0a059b45ce9086db907ef6e9cff1 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Fri, 21 Aug 2026 17:46:56 +0000
Subject: [PATCH 2/2] Fix timer_create and add timer_delete.

---
 libc/config/linux/aarch64/entrypoints.txt     |  2 +
 libc/config/linux/riscv/entrypoints.txt       |  2 +
 libc/config/linux/x86_64/entrypoints.txt      |  2 +
 libc/include/time.yaml                        |  7 +++
 .../linux/syscall_wrappers/CMakeLists.txt     | 16 ++++++
 .../linux/syscall_wrappers/timer_create.h     | 16 ++++--
 .../linux/syscall_wrappers/timer_delete.h     | 38 +++++++++++++
 libc/src/time/CMakeLists.txt                  |  8 +++
 libc/src/time/linux/CMakeLists.txt            | 16 ++++++
 libc/src/time/linux/timer_delete.cpp          | 31 +++++++++++
 libc/src/time/timer_delete.h                  | 26 +++++++++
 libc/test/src/time/CMakeLists.txt             |  5 +-
 .../{timer_create_test.cpp => timer_test.cpp} | 55 +++++++++++++------
 13 files changed, 200 insertions(+), 24 deletions(-)
 create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/timer_delete.h
 create mode 100644 libc/src/time/linux/timer_delete.cpp
 create mode 100644 libc/src/time/timer_delete.h
 rename libc/test/src/time/{timer_create_test.cpp => timer_test.cpp} (55%)

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 08ecf19bdba86..eb4ad38db3cd3 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1331,6 +1331,8 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.time.time
     libc.src.time.timespec_get
     libc.src.time.timer_create
+    libc.src.time.timer_delete
+
 
     # unistd.h entrypoints
     libc.src.unistd.__llvm_libc_syscall
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 50dfdc0985e5d..12f004989597c 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1526,6 +1526,8 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.time.time
     libc.src.time.timespec_get
     libc.src.time.timer_create
+    libc.src.time.timer_delete
+
 
     # locale.h entrypoints
     libc.src.locale.localeconv
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 8f6d7bce8abb7..34733ed9346d4 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1540,6 +1540,8 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.time.time
     libc.src.time.timespec_get
     libc.src.time.timer_create
+    libc.src.time.timer_delete
+
 
     # locale.h entrypoints
     libc.src.locale.localeconv
diff --git a/libc/include/time.yaml b/libc/include/time.yaml
index 71ea97dabb522..147bd6f5643a6 100644
--- a/libc/include/time.yaml
+++ b/libc/include/time.yaml
@@ -162,3 +162,10 @@ functions:
       - type: clockid_t
       - type: struct sigevent *__restrict
       - type: timer_t *__restrict
+  - name: timer_delete
+    standards:
+      - posix
+    return_type: int
+    arguments:
+      - type: timer_t
+
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index b41bc16f0438a..d0dd04bfb1d59 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -1011,13 +1011,29 @@ add_header_library(
   HDRS
     timer_create.h
   DEPENDS
+    libc.hdr.signal_macros
     libc.hdr.types.clockid_t
     libc.hdr.types.pid_t
     libc.hdr.types.struct_sigevent
     libc.hdr.types.timer_t
     libc.include.sys_syscall
+    libc.src.__support.CPP.cstddef
     libc.src.__support.OSUtil.osutil
     libc.src.__support.common
     libc.src.__support.error_or
     libc.src.__support.macros.config
 )
+
+add_header_library(
+  timer_delete
+  HDRS
+    timer_delete.h
+  DEPENDS
+    libc.hdr.types.timer_t
+    libc.include.sys_syscall
+    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/timer_create.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/timer_create.h
index 9124d8c250bb7..f23a22126e67f 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/timer_create.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/timer_create.h
@@ -14,10 +14,12 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_TIMER_CREATE_H
 #define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_TIMER_CREATE_H
 
+#include "hdr/signal_macros.h"
 #include "hdr/types/clockid_t.h"
 #include "hdr/types/pid_t.h"
 #include "hdr/types/struct_sigevent.h"
 #include "hdr/types/timer_t.h"
+#include "src/__support/CPP/cstddef.h"
 #include "src/__support/OSUtil/linux/syscall.h" // For syscall_checked
 #include "src/__support/common.h"
 #include "src/__support/error_or.h"
@@ -49,13 +51,19 @@ struct KernelSigevent {
 
   LIBC_INLINE KernelSigevent() = default;
 
-  LIBC_INLINE KernelSigevent(const sigevent &sev) {
+  LIBC_INLINE KernelSigevent(const sigevent &sev) : _sigev_un{} {
     sigev_value = sev.sigev_value;
     sigev_signo = sev.sigev_signo;
     sigev_notify = sev.sigev_notify;
-    _sigev_un._tid = sev.sigev_notify_thread_id;
-    _sigev_un._sigev_thread._function = sev.sigev_notify_function;
-    _sigev_un._sigev_thread._attribute = sev.sigev_notify_attributes;
+    // Zero initialize `_sigev_un`.
+    for (size_t i = 0; i < __SIGEV_PAD_SIZE; ++i)
+      _sigev_un._pad[i] = 0;
+    if ((sev.sigev_notify & SIGEV_THREAD_ID) != 0) {
+      _sigev_un._tid = sev.sigev_notify_thread_id;
+    } else if (sev.sigev_notify == SIGEV_THREAD) {
+      _sigev_un._sigev_thread._function = sev.sigev_notify_function;
+      _sigev_un._sigev_thread._attribute = sev.sigev_notify_attributes;
+    }
   }
 };
 
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/timer_delete.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/timer_delete.h
new file mode 100644
index 0000000000000..bc41a6d6d2ed1
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/timer_delete.h
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 timer_delete syscall wrapper.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_TIMER_DELETE_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_TIMER_DELETE_H
+
+#include "hdr/types/timer_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // For syscall_checked
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<int> timer_delete(timer_t timerid) {
+#ifdef SYS_timer_delete
+  return syscall_checked<int>(SYS_timer_delete, timerid);
+#else
+#error "SYS_timer_delete syscall not available."
+#endif
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_TIMER_DELETE_H
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index 9006a35c00bc7..49ca72376090c 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -306,3 +306,11 @@ add_entrypoint_object(
   DEPENDS
     .${LIBC_TARGET_OS}.timer_create
 )
+
+add_entrypoint_object(
+  timer_delete
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.timer_delete
+)
+
diff --git a/libc/src/time/linux/CMakeLists.txt b/libc/src/time/linux/CMakeLists.txt
index 1c0ec1c67c31a..3f91aa3528405 100644
--- a/libc/src/time/linux/CMakeLists.txt
+++ b/libc/src/time/linux/CMakeLists.txt
@@ -89,3 +89,19 @@ add_entrypoint_object(
     libc.src.__support.macros.config
     libc.src.errno.errno
 )
+
+add_entrypoint_object(
+  timer_delete
+  SRCS
+    timer_delete.cpp
+  HDRS
+    ../timer_delete.h
+  DEPENDS
+    libc.hdr.types.timer_t
+    libc.src.__support.OSUtil.linux.syscall_wrappers.timer_delete
+    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/timer_delete.cpp b/libc/src/time/linux/timer_delete.cpp
new file mode 100644
index 0000000000000..bbf2d621003e1
--- /dev/null
+++ b/libc/src/time/linux/timer_delete.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 timer_delete function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/time/timer_delete.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/timer_delete.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, timer_delete, (timer_t timerid)) {
+  auto result = linux_syscalls::timer_delete(timerid);
+  if (!result) {
+    libc_errno = result.error();
+    return -1;
+  }
+  return result.value();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/timer_delete.h b/libc/src/time/timer_delete.h
new file mode 100644
index 0000000000000..cc326b1a16e2a
--- /dev/null
+++ b/libc/src/time/timer_delete.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 timer_delete function.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_TIME_TIMER_DELETE_H
+#define LLVM_LIBC_SRC_TIME_TIMER_DELETE_H
+
+#include "hdr/types/timer_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int timer_delete(timer_t timerid);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_TIME_TIMER_DELETE_H
diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt
index adb61d2f6633b..a2247ed4cd679 100644
--- a/libc/test/src/time/CMakeLists.txt
+++ b/libc/test/src/time/CMakeLists.txt
@@ -144,11 +144,11 @@ add_libc_test(
 )
 
 add_libc_test(
-  timer_create_test
+  timer_test
   SUITE
     libc_time_unittests
   SRCS
-    timer_create_test.cpp
+    timer_test.cpp
   DEPENDS
     libc.hdr.errno_macros
     libc.hdr.signal_macros
@@ -158,6 +158,7 @@ add_libc_test(
     libc.hdr.types.timer_t
     libc.src.__support.OSUtil.osutil
     libc.src.time.timer_create
+    libc.src.time.timer_delete
     libc.test.UnitTest.ErrnoCheckingTest
     libc.test.UnitTest.ErrnoSetterMatcher
 )
diff --git a/libc/test/src/time/timer_create_test.cpp b/libc/test/src/time/timer_test.cpp
similarity index 55%
rename from libc/test/src/time/timer_create_test.cpp
rename to libc/test/src/time/timer_test.cpp
index 339bede11de66..3d9d02f6c84eb 100644
--- a/libc/test/src/time/timer_create_test.cpp
+++ b/libc/test/src/time/timer_test.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 ///
 /// \file
-/// Unittests for timer_create.
+/// Unittests for posix timers (timer_create, timer_delete).
 ///
 //===----------------------------------------------------------------------===//
 
@@ -19,6 +19,7 @@
 #include "hdr/types/timer_t.h"
 #include "src/__support/OSUtil/syscall.h"
 #include "src/time/timer_create.h"
+#include "src/time/timer_delete.h"
 #include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
@@ -27,31 +28,25 @@
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::any_of;
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
-using LlvmLibcTimerCreateTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+using LlvmLibcTimerTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
 
-TEST_F(LlvmLibcTimerCreateTest, NullSigevent) {
+TEST_F(LlvmLibcTimerTest, NullSigevent) {
   timer_t timerid;
   ASSERT_THAT(LIBC_NAMESPACE::timer_create(CLOCK_REALTIME, nullptr, &timerid),
               Succeeds(0));
-
-#ifdef SYS_timer_delete
-  LIBC_NAMESPACE::syscall_impl<int>(SYS_timer_delete, timerid);
-#endif
+  ASSERT_THAT(LIBC_NAMESPACE::timer_delete(timerid), Succeeds(0));
 }
 
-TEST_F(LlvmLibcTimerCreateTest, ValidSigeventSigevNone) {
+TEST_F(LlvmLibcTimerTest, ValidSigeventSigevNone) {
   struct sigevent se;
   se.sigev_notify = SIGEV_NONE;
   timer_t timerid;
   ASSERT_THAT(LIBC_NAMESPACE::timer_create(CLOCK_MONOTONIC, &se, &timerid),
               Succeeds(0));
-
-#ifdef SYS_timer_delete
-  LIBC_NAMESPACE::syscall_impl<int>(SYS_timer_delete, timerid);
-#endif
+  ASSERT_THAT(LIBC_NAMESPACE::timer_delete(timerid), Succeeds(0));
 }
 
-TEST_F(LlvmLibcTimerCreateTest, ValidSigeventSigevSignal) {
+TEST_F(LlvmLibcTimerTest, ValidSigeventSigevSignal) {
   struct sigevent se;
   se.sigev_notify = SIGEV_SIGNAL;
   se.sigev_signo = SIGALRM;
@@ -59,20 +54,44 @@ TEST_F(LlvmLibcTimerCreateTest, ValidSigeventSigevSignal) {
   timer_t timerid;
   ASSERT_THAT(LIBC_NAMESPACE::timer_create(CLOCK_REALTIME, &se, &timerid),
               Succeeds(0));
+  ASSERT_THAT(LIBC_NAMESPACE::timer_delete(timerid), Succeeds(0));
+}
 
-#ifdef SYS_timer_delete
-  LIBC_NAMESPACE::syscall_impl<int>(SYS_timer_delete, timerid);
-#endif
+#if defined(SYS_gettid) && defined(SIGEV_THREAD_ID)
+TEST_F(LlvmLibcTimerTest, ValidSigeventSigevThreadId) {
+  struct sigevent se;
+  se.sigev_notify = SIGEV_THREAD_ID;
+  se.sigev_signo = SIGALRM;
+  se.sigev_value.sival_int = 42;
+  se.sigev_notify_thread_id = LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_gettid);
+  timer_t timerid;
+  ASSERT_THAT(LIBC_NAMESPACE::timer_create(CLOCK_REALTIME, &se, &timerid),
+              Succeeds(0));
+  ASSERT_THAT(LIBC_NAMESPACE::timer_delete(timerid), Succeeds(0));
 }
+#endif
 
-TEST_F(LlvmLibcTimerCreateTest, InvalidClockId) {
+TEST_F(LlvmLibcTimerTest, InvalidClockId) {
   timer_t timerid;
   ASSERT_THAT(LIBC_NAMESPACE::timer_create(static_cast<clockid_t>(-1), nullptr,
                                            &timerid),
               Fails(EINVAL));
 }
 
-TEST_F(LlvmLibcTimerCreateTest, NullTimerId) {
+TEST_F(LlvmLibcTimerTest, NullTimerId) {
   ASSERT_THAT(LIBC_NAMESPACE::timer_create(CLOCK_REALTIME, nullptr, nullptr),
               Fails(any_of(EINVAL, EFAULT)));
 }
+
+TEST_F(LlvmLibcTimerTest, DeleteInvalidTimerId) {
+  ASSERT_THAT(LIBC_NAMESPACE::timer_delete(reinterpret_cast<timer_t>(-1)),
+              Fails(EINVAL));
+}
+
+TEST_F(LlvmLibcTimerTest, CreateAndDelete) {
+  timer_t timerid;
+  ASSERT_THAT(LIBC_NAMESPACE::timer_create(CLOCK_REALTIME, nullptr, &timerid),
+              Succeeds(0));
+  ASSERT_THAT(LIBC_NAMESPACE::timer_delete(timerid), Succeeds(0));
+  ASSERT_THAT(LIBC_NAMESPACE::timer_delete(timerid), Fails(EINVAL));
+}



More information about the libc-commits mailing list