[libc-commits] [libc] [libc][semaphore] Add unnamed semaphore implementation (PR #190851)
Pengxiang Huang via libc-commits
libc-commits at lists.llvm.org
Wed Apr 8 17:32:40 PDT 2026
https://github.com/Pengxiang-Huang updated https://github.com/llvm/llvm-project/pull/190851
>From cb8c1252535c5070c645eb6695c0a67e61d0d923 Mon Sep 17 00:00:00 2001
From: Pengxiang Huang <huangpengxiang70 at gmail.com>
Date: Tue, 7 Apr 2026 16:40:46 -0400
Subject: [PATCH 1/3] add unamed semaphore implementation
---
libc/config/linux/x86_64/entrypoints.txt | 5 ++
libc/hdr/types/CMakeLists.txt | 8 +++
libc/hdr/types/sem_t.h | 22 ++++++
libc/include/CMakeLists.txt | 9 +++
libc/include/limits.yaml | 2 +
libc/include/llvm-libc-macros/limits-macros.h | 4 ++
libc/include/llvm-libc-types/CMakeLists.txt | 1 +
libc/include/llvm-libc-types/sem_t.h | 20 ++++++
libc/include/semaphore.yaml | 21 ++++++
libc/src/CMakeLists.txt | 1 +
libc/src/semaphore/CMakeLists.txt | 49 +++++++++++++
libc/src/semaphore/posix_semaphore.h | 72 +++++++++++++++++++
libc/src/semaphore/sem_destroy.cpp | 29 ++++++++
libc/src/semaphore/sem_destroy.h | 21 ++++++
libc/src/semaphore/sem_getvalue.cpp | 33 +++++++++
libc/src/semaphore/sem_getvalue.h | 21 ++++++
libc/src/semaphore/sem_init.cpp | 32 +++++++++
libc/src/semaphore/sem_init.h | 21 ++++++
libc/test/src/CMakeLists.txt | 1 +
libc/test/src/semaphore/CMakeLists.txt | 19 +++++
libc/test/src/semaphore/semaphore_test.cpp | 51 +++++++++++++
21 files changed, 442 insertions(+)
create mode 100644 libc/hdr/types/sem_t.h
create mode 100644 libc/include/llvm-libc-types/sem_t.h
create mode 100644 libc/include/semaphore.yaml
create mode 100644 libc/src/semaphore/CMakeLists.txt
create mode 100644 libc/src/semaphore/posix_semaphore.h
create mode 100644 libc/src/semaphore/sem_destroy.cpp
create mode 100644 libc/src/semaphore/sem_destroy.h
create mode 100644 libc/src/semaphore/sem_getvalue.cpp
create mode 100644 libc/src/semaphore/sem_getvalue.h
create mode 100644 libc/src/semaphore/sem_init.cpp
create mode 100644 libc/src/semaphore/sem_init.h
create mode 100644 libc/test/src/semaphore/CMakeLists.txt
create mode 100644 libc/test/src/semaphore/semaphore_test.cpp
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 90a0dade5435a..72fc463aac362 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1233,6 +1233,11 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_spin_lock
libc.src.pthread.pthread_spin_trylock
libc.src.pthread.pthread_spin_unlock
+
+ # semaphore.h entrypoints
+ libc.src.semaphore.sem_destroy
+ libc.src.semaphore.sem_getvalue
+ libc.src.semaphore.sem_init
libc.src.pthread.pthread_self
libc.src.pthread.pthread_setname_np
libc.src.pthread.pthread_setspecific
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index 7e1a8974fa486..0862f0f9efecf 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -282,6 +282,14 @@ add_proxy_header_library(
libc.include.llvm-libc-types.pid_t
)
+add_proxy_header_library(
+ sem_t
+ HDRS
+ sem_t.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.sem_t
+)
+
add_proxy_header_library(
pthread_barrier_t
HDRS
diff --git a/libc/hdr/types/sem_t.h b/libc/hdr/types/sem_t.h
new file mode 100644
index 0000000000000..e057bca6b98df
--- /dev/null
+++ b/libc/hdr/types/sem_t.h
@@ -0,0 +1,22 @@
+//===-- Definition of sem_t type -----------------------------------------===//
+//
+// 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_TYPES_SEM_T_H
+#define LLVM_LIBC_HDR_TYPES_SEM_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/sem_t.h"
+
+#else // Overlay mode
+
+#error "Cannot overlay sem_t"
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_SEM_T_H
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 3375e4e21e338..aa289a4f6fa88 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -471,6 +471,15 @@ add_header_macro(
.llvm-libc-types.struct_timespec
)
+add_header_macro(
+ semaphore
+ ../libc/include/semaphore.yaml
+ semaphore.h
+ DEPENDS
+ .llvm-libc-types.sem_t
+ .llvm_libc_common_h
+)
+
add_header_macro(
spawn
../libc/include/spawn.yaml
diff --git a/libc/include/limits.yaml b/libc/include/limits.yaml
index 1f0956128fb00..f7576d89a5d80 100644
--- a/libc/include/limits.yaml
+++ b/libc/include/limits.yaml
@@ -52,6 +52,8 @@ macros:
macro_header: limits-macros.h
- macro_name: ULLONG_MAX
macro_header: limits-macros.h
+ - macro_name: SEM_VALUE_MAX
+ macro_header: limits-macros.h
- macro_name: SCHAR_MIN
macro_header: limits-macros.h
- macro_name: UCHAR_MIN
diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index 79bbbe401eb02..0f999b2bedd19 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -173,6 +173,10 @@
#define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
#endif // ULLONG_MAX
+#ifndef SEM_VALUE_MAX
+#define SEM_VALUE_MAX INT_MAX
+#endif // SEM_VALUE_MAX
+
// *_MIN macros
#ifndef SCHAR_MIN
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 0d6bc0982b847..ec4719a5e57a1 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -84,6 +84,7 @@ add_header(pthread_rwlockattr_t HDR pthread_rwlockattr_t.h)
add_header(pthread_spinlock_t HDR pthread_spinlock_t.h DEPENDS .pid_t)
add_header(pthread_t HDR pthread_t.h DEPENDS .__thread_type)
add_header(rlim_t HDR rlim_t.h)
+add_header(sem_t HDR sem_t.h DEPENDS .__futex_word)
if(LIBC_TYPES_TIME_T_IS_32_BIT)
add_header(time_t HDR time_t_32.h DEST_HDR time_t.h)
else()
diff --git a/libc/include/llvm-libc-types/sem_t.h b/libc/include/llvm-libc-types/sem_t.h
new file mode 100644
index 0000000000000..b9596f4e65707
--- /dev/null
+++ b/libc/include/llvm-libc-types/sem_t.h
@@ -0,0 +1,20 @@
+//===-- Definition of sem_t type -----------------------------------------===//
+//
+// 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_TYPES_SEM_T_H
+#define LLVM_LIBC_TYPES_SEM_T_H
+
+#include "__futex_word.h"
+
+typedef struct {
+ __futex_word __value; // current semaphore count
+ unsigned int __canary; // used for sanity check
+ unsigned char __reserved[8]; // for future usage, total fixed size 16 bytes
+} sem_t;
+
+#endif // LLVM_LIBC_TYPES_SEM_T_H
diff --git a/libc/include/semaphore.yaml b/libc/include/semaphore.yaml
new file mode 100644
index 0000000000000..a56e2eca1c390
--- /dev/null
+++ b/libc/include/semaphore.yaml
@@ -0,0 +1,21 @@
+header: semaphore.h
+standards:
+ - posix
+types:
+ - type_name: sem_t
+functions:
+ - name: sem_destroy
+ return_type: int
+ arguments:
+ - type: sem_t *
+ - name: sem_getvalue
+ return_type: int
+ arguments:
+ - type: sem_t *__restrict
+ - type: int *__restrict
+ - name: sem_init
+ return_type: int
+ arguments:
+ - type: sem_t *
+ - type: int
+ - type: unsigned int
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 8a0acccaed708..e4b0de3d5c75d 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -25,6 +25,7 @@ if(${LIBC_TARGET_OS} STREQUAL "linux")
add_subdirectory(poll)
add_subdirectory(pthread)
add_subdirectory(sched)
+ add_subdirectory(semaphore)
add_subdirectory(sys)
add_subdirectory(termios)
endif()
diff --git a/libc/src/semaphore/CMakeLists.txt b/libc/src/semaphore/CMakeLists.txt
new file mode 100644
index 0000000000000..83572bc0464c3
--- /dev/null
+++ b/libc/src/semaphore/CMakeLists.txt
@@ -0,0 +1,49 @@
+add_header_library(
+ posix_semaphore
+ HDRS
+ posix_semaphore.h
+ DEPENDS
+ libc.hdr.types.sem_t
+ libc.src.__support.CPP.atomic
+ libc.src.__support.threads.linux.futex_word_type
+)
+
+add_entrypoint_object(
+ sem_init
+ SRCS
+ sem_init.cpp
+ HDRS
+ sem_init.h
+ DEPENDS
+ .posix_semaphore
+ libc.hdr.errno_macros
+ libc.hdr.limits_macros
+ libc.include.semaphore
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sem_destroy
+ SRCS
+ sem_destroy.cpp
+ HDRS
+ sem_destroy.h
+ DEPENDS
+ .posix_semaphore
+ libc.hdr.errno_macros
+ libc.include.semaphore
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sem_getvalue
+ SRCS
+ sem_getvalue.cpp
+ HDRS
+ sem_getvalue.h
+ DEPENDS
+ .posix_semaphore
+ libc.hdr.errno_macros
+ libc.include.semaphore
+ libc.src.errno.errno
+)
diff --git a/libc/src/semaphore/posix_semaphore.h b/libc/src/semaphore/posix_semaphore.h
new file mode 100644
index 0000000000000..50bcba63f5a7d
--- /dev/null
+++ b/libc/src/semaphore/posix_semaphore.h
@@ -0,0 +1,72 @@
+//===-- Shared helpers for POSIX semaphores -------------------------------===//
+//
+// 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_SEMAPHORE_POSIX_SEMAPHORE_H
+#define LLVM_LIBC_SRC_SEMAPHORE_POSIX_SEMAPHORE_H
+
+#include "hdr/types/sem_t.h"
+#include "src/__support/CPP/atomic.h"
+#include "src/__support/common.h"
+#include "src/__support/threads/linux/futex_word.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace sem_utils {
+
+// 0x53 = S, 0x45 = E, 0x4D = M, 0x31 = 1
+// canary value: SEM1 in hex
+LIBC_INLINE_VAR constexpr unsigned int SEM_CANARY = 0x53454D31U;
+
+static_assert(sizeof(__futex_word) == sizeof(FutexWordType));
+static_assert(alignof(__futex_word) >= alignof(FutexWordType));
+
+// TODO:
+// 1. Add named semaphore support: sem_open, sem_close, sem_unlink
+// 2. Add the posting and waiting operations: sem_post, sem_wait,
+// sem_trywait, sem_timedwait, sem_clockwait.
+
+LIBC_INLINE FutexWordType *value_ptr(sem_t *sem) {
+ return &sem->__value.__word;
+}
+
+// get the atomic reference for sem->__value
+LIBC_INLINE cpp::AtomicRef<FutexWordType> value(sem_t *sem) {
+ return cpp::AtomicRef<FutexWordType>(*value_ptr(sem));
+}
+
+LIBC_INLINE void initialize(sem_t *sem, unsigned int initial_value) {
+ // used in sem_init
+ // init happens before the semaphore is published to any threads
+ // initialize a initialized semaphore is undefined
+ // so RELAXED ordering is enough
+ value(sem).store(initial_value, cpp::MemoryOrder::RELAXED);
+ sem->__canary = SEM_CANARY;
+ for (unsigned char &byte : sem->__reserved)
+ byte = 0;
+}
+
+LIBC_INLINE bool is_valid(const sem_t *sem) {
+ // sanity check for a given semaphore pointer
+ return sem != nullptr && sem->__canary == SEM_CANARY;
+}
+
+LIBC_INLINE void invalidate(sem_t *sem) {
+ // used in sem_destroy
+ // invalidate is safe only when no threads is using
+ // blocked by destroyed semaphore is undefined
+ // use a destroyed semaphore is undefined
+ // RELAXED ordering is enough
+ value(sem).store(0, cpp::MemoryOrder::RELAXED);
+ sem->__canary = 0;
+ for (unsigned char &byte : sem->__reserved)
+ byte = 0;
+}
+
+} // namespace sem_utils
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SEMAPHORE_POSIX_SEMAPHORE_H
diff --git a/libc/src/semaphore/sem_destroy.cpp b/libc/src/semaphore/sem_destroy.cpp
new file mode 100644
index 0000000000000..c64e18a88e639
--- /dev/null
+++ b/libc/src/semaphore/sem_destroy.cpp
@@ -0,0 +1,29 @@
+//===-- Implementation of sem_destroy ------------------------------------===//
+//
+// 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/semaphore/sem_destroy.h"
+
+#include "src/semaphore/posix_semaphore.h"
+
+#include "hdr/errno_macros.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, sem_destroy, (sem_t * sem)) {
+ if (!sem_utils::is_valid(sem)) {
+ libc_errno = EINVAL;
+ return -1;
+ }
+
+ sem_utils::invalidate(sem);
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/semaphore/sem_destroy.h b/libc/src/semaphore/sem_destroy.h
new file mode 100644
index 0000000000000..b664cf97eecf0
--- /dev/null
+++ b/libc/src/semaphore/sem_destroy.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for sem_destroy ------------------*- 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_SEMAPHORE_SEM_DESTROY_H
+#define LLVM_LIBC_SRC_SEMAPHORE_SEM_DESTROY_H
+
+#include "hdr/types/sem_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int sem_destroy(sem_t *sem);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SEMAPHORE_SEM_DESTROY_H
diff --git a/libc/src/semaphore/sem_getvalue.cpp b/libc/src/semaphore/sem_getvalue.cpp
new file mode 100644
index 0000000000000..ea84c1e8a6241
--- /dev/null
+++ b/libc/src/semaphore/sem_getvalue.cpp
@@ -0,0 +1,33 @@
+//===-- Implementation of sem_getvalue -----------------------------------===//
+//
+// 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/semaphore/sem_getvalue.h"
+
+#include "src/semaphore/posix_semaphore.h"
+
+#include "hdr/errno_macros.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, sem_getvalue,
+ (sem_t *__restrict sem, int *__restrict sval)) {
+ if (!sem_utils::is_valid(sem) || sval == nullptr) {
+ libc_errno = EINVAL;
+ return -1;
+ }
+
+ // get value is informational but not a synchronization op
+ // RELAXED ordering is enough
+ *sval =
+ static_cast<int>(sem_utils::value(sem).load(cpp::MemoryOrder::RELAXED));
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/semaphore/sem_getvalue.h b/libc/src/semaphore/sem_getvalue.h
new file mode 100644
index 0000000000000..4ba49491746b1
--- /dev/null
+++ b/libc/src/semaphore/sem_getvalue.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for sem_getvalue -----------------*- 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_SEMAPHORE_SEM_GETVALUE_H
+#define LLVM_LIBC_SRC_SEMAPHORE_SEM_GETVALUE_H
+
+#include "hdr/types/sem_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int sem_getvalue(sem_t *__restrict sem, int *__restrict sval);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SEMAPHORE_SEM_GETVALUE_H
diff --git a/libc/src/semaphore/sem_init.cpp b/libc/src/semaphore/sem_init.cpp
new file mode 100644
index 0000000000000..a3f6e452b6e6c
--- /dev/null
+++ b/libc/src/semaphore/sem_init.cpp
@@ -0,0 +1,32 @@
+//===-- Implementation of sem_init ---------------------------------------===//
+//
+// 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/semaphore/sem_init.h"
+
+#include "src/semaphore/posix_semaphore.h"
+
+#include "hdr/errno_macros.h"
+#include "hdr/limits_macros.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, sem_init,
+ (sem_t * sem, int pshared, unsigned int value)) {
+ if (sem == nullptr || value > SEM_VALUE_MAX) {
+ libc_errno = EINVAL;
+ return -1;
+ }
+
+ (void)pshared;
+ sem_utils::initialize(sem, value);
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/semaphore/sem_init.h b/libc/src/semaphore/sem_init.h
new file mode 100644
index 0000000000000..8a3114ddfa10f
--- /dev/null
+++ b/libc/src/semaphore/sem_init.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for sem_init ----------------------*- 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_SEMAPHORE_SEM_INIT_H
+#define LLVM_LIBC_SRC_SEMAPHORE_SEM_INIT_H
+
+#include "hdr/types/sem_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int sem_init(sem_t *sem, int pshared, unsigned int value);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SEMAPHORE_SEM_INIT_H
diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index 5e61c739c066a..236bee337d525 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -106,4 +106,5 @@ add_subdirectory(spawn)
if(${LIBC_TARGET_OS} STREQUAL "linux")
add_subdirectory(pthread)
+ add_subdirectory(semaphore)
endif()
diff --git a/libc/test/src/semaphore/CMakeLists.txt b/libc/test/src/semaphore/CMakeLists.txt
new file mode 100644
index 0000000000000..259c11fe55f07
--- /dev/null
+++ b/libc/test/src/semaphore/CMakeLists.txt
@@ -0,0 +1,19 @@
+add_custom_target(libc_semaphore_unittests)
+
+add_libc_unittest(
+ semaphore_test
+ SUITE
+ libc_semaphore_unittests
+ SRCS
+ semaphore_test.cpp
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.include.limits
+ libc.include.semaphore
+ libc.src.errno.errno
+ libc.src.semaphore.sem_destroy
+ libc.src.semaphore.sem_getvalue
+ libc.src.semaphore.sem_init
+ libc.test.UnitTest.ErrnoCheckingTest
+ libc.test.UnitTest.ErrnoSetterMatcher
+)
diff --git a/libc/test/src/semaphore/semaphore_test.cpp b/libc/test/src/semaphore/semaphore_test.cpp
new file mode 100644
index 0000000000000..1e67bb046ad5f
--- /dev/null
+++ b/libc/test/src/semaphore/semaphore_test.cpp
@@ -0,0 +1,51 @@
+//===-- Unittests for POSIX semaphores -----------------------------------===//
+//
+// 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/errno_macros.h"
+#include "src/semaphore/sem_destroy.h"
+#include "src/semaphore/sem_getvalue.h"
+#include "src/semaphore/sem_init.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#include <limits.h>
+#include <semaphore.h>
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+
+namespace {
+
+using LlvmLibcSemaphoreTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+} // namespace
+
+TEST_F(LlvmLibcSemaphoreTest, PublicSurface) {
+ sem_t sem = {};
+ (void)sem;
+ ASSERT_GE(SEM_VALUE_MAX, 32767);
+}
+
+TEST_F(LlvmLibcSemaphoreTest, UnnamedLifecycle) {
+ sem_t sem;
+ int value = -1;
+
+ ASSERT_THAT(LIBC_NAMESPACE::sem_init(&sem, 0, 3), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::sem_getvalue(&sem, &value), Succeeds());
+ ASSERT_EQ(value, 3);
+
+ ASSERT_THAT(LIBC_NAMESPACE::sem_destroy(&sem), Succeeds());
+ ASSERT_THAT(LIBC_NAMESPACE::sem_getvalue(&sem, &value), Fails(EINVAL));
+}
+
+TEST_F(LlvmLibcSemaphoreTest, UnnamedInitRejectsTooLargeValue) {
+ sem_t sem;
+ ASSERT_THAT(LIBC_NAMESPACE::sem_init(
+ &sem, 0, static_cast<unsigned int>(SEM_VALUE_MAX) + 1U),
+ Fails(EINVAL));
+}
>From f06596f1b4af73fc41f7f51d96e9f4d38dd828fd Mon Sep 17 00:00:00 2001
From: Pengxiang Huang <huangpengxiang70 at gmail.com>
Date: Wed, 8 Apr 2026 11:05:05 -0400
Subject: [PATCH 2/3] overlay the sem_t with internal Semaphore type
---
libc/src/semaphore/CMakeLists.txt | 2 +-
libc/src/semaphore/posix_semaphore.h | 85 +++++++++++++---------------
libc/src/semaphore/sem_destroy.cpp | 5 +-
libc/src/semaphore/sem_getvalue.cpp | 8 +--
libc/src/semaphore/sem_init.cpp | 2 +-
5 files changed, 48 insertions(+), 54 deletions(-)
diff --git a/libc/src/semaphore/CMakeLists.txt b/libc/src/semaphore/CMakeLists.txt
index 83572bc0464c3..4a805059ca20f 100644
--- a/libc/src/semaphore/CMakeLists.txt
+++ b/libc/src/semaphore/CMakeLists.txt
@@ -5,7 +5,7 @@ add_header_library(
DEPENDS
libc.hdr.types.sem_t
libc.src.__support.CPP.atomic
- libc.src.__support.threads.linux.futex_word_type
+ libc.src.__support.threads.linux.futex_utils
)
add_entrypoint_object(
diff --git a/libc/src/semaphore/posix_semaphore.h b/libc/src/semaphore/posix_semaphore.h
index 50bcba63f5a7d..f42dbbb720420 100644
--- a/libc/src/semaphore/posix_semaphore.h
+++ b/libc/src/semaphore/posix_semaphore.h
@@ -1,4 +1,4 @@
-//===-- Shared helpers for POSIX semaphores -------------------------------===//
+//===-- Internal Semaphore types and helpers for POSIX semaphores ---------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -12,61 +12,56 @@
#include "hdr/types/sem_t.h"
#include "src/__support/CPP/atomic.h"
#include "src/__support/common.h"
-#include "src/__support/threads/linux/futex_word.h"
+#include "src/__support/threads/linux/futex_utils.h"
namespace LIBC_NAMESPACE_DECL {
-namespace sem_utils {
-// 0x53 = S, 0x45 = E, 0x4D = M, 0x31 = 1
-// canary value: SEM1 in hex
-LIBC_INLINE_VAR constexpr unsigned int SEM_CANARY = 0x53454D31U;
+class Semaphore {
+ Futex value;
+ unsigned int canary;
-static_assert(sizeof(__futex_word) == sizeof(FutexWordType));
-static_assert(alignof(__futex_word) >= alignof(FutexWordType));
+ // 0x53 = S, 0x45 = E, 0x4D = M, 0x31 = 1
+ static constexpr unsigned int SEM_CANARY = 0x53454D31U;
-// TODO:
-// 1. Add named semaphore support: sem_open, sem_close, sem_unlink
-// 2. Add the posting and waiting operations: sem_post, sem_wait,
-// sem_trywait, sem_timedwait, sem_clockwait.
+public:
+ // TODO:
+ // 1. Add named semaphore support: sem_open, sem_close, sem_unlink
+ // 2. Add the posting and waiting operations: sem_post, sem_wait,
+ // sem_trywait, sem_timedwait, sem_clockwait.
-LIBC_INLINE FutexWordType *value_ptr(sem_t *sem) {
- return &sem->__value.__word;
-}
+ LIBC_INLINE void init(unsigned int initial_value) {
+ // init happens before the semaphore is published to any threads
+ // initialize a initialized semaphore is undefined
+ // so RELAXED ordering is enough
+ value.store(initial_value, cpp::MemoryOrder::RELAXED);
+ canary = SEM_CANARY;
+ }
-// get the atomic reference for sem->__value
-LIBC_INLINE cpp::AtomicRef<FutexWordType> value(sem_t *sem) {
- return cpp::AtomicRef<FutexWordType>(*value_ptr(sem));
-}
+ // sanity check for a given semaphore pointer
+ LIBC_INLINE bool is_valid() const { return canary == SEM_CANARY; }
-LIBC_INLINE void initialize(sem_t *sem, unsigned int initial_value) {
- // used in sem_init
- // init happens before the semaphore is published to any threads
- // initialize a initialized semaphore is undefined
- // so RELAXED ordering is enough
- value(sem).store(initial_value, cpp::MemoryOrder::RELAXED);
- sem->__canary = SEM_CANARY;
- for (unsigned char &byte : sem->__reserved)
- byte = 0;
-}
+ LIBC_INLINE void destroy() {
+ // invalidate is safe only when no threads is using
+ // blocked by destroyed semaphore is undefined
+ // use a destroyed semaphore is undefined
+ // RELAXED ordering is enough
+ value.store(0, cpp::MemoryOrder::RELAXED);
+ canary = 0;
+ }
-LIBC_INLINE bool is_valid(const sem_t *sem) {
- // sanity check for a given semaphore pointer
- return sem != nullptr && sem->__canary == SEM_CANARY;
-}
+ LIBC_INLINE int getvalue() const {
+ // get value is informational but not a synchronization op
+ // RELAXED ordering is enough
+ return static_cast<int>(
+ const_cast<Futex &>(value).load(cpp::MemoryOrder::RELAXED));
+ }
+};
-LIBC_INLINE void invalidate(sem_t *sem) {
- // used in sem_destroy
- // invalidate is safe only when no threads is using
- // blocked by destroyed semaphore is undefined
- // use a destroyed semaphore is undefined
- // RELAXED ordering is enough
- value(sem).store(0, cpp::MemoryOrder::RELAXED);
- sem->__canary = 0;
- for (unsigned char &byte : sem->__reserved)
- byte = 0;
-}
+static_assert(sizeof(Semaphore) <= sizeof(sem_t),
+ "Semaphore must fit within sem_t.");
+static_assert(alignof(Semaphore) <= alignof(sem_t),
+ "Semaphore alignment must be compatible with sem_t.");
-} // namespace sem_utils
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SEMAPHORE_POSIX_SEMAPHORE_H
diff --git a/libc/src/semaphore/sem_destroy.cpp b/libc/src/semaphore/sem_destroy.cpp
index c64e18a88e639..67d003697910e 100644
--- a/libc/src/semaphore/sem_destroy.cpp
+++ b/libc/src/semaphore/sem_destroy.cpp
@@ -17,12 +17,13 @@
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, sem_destroy, (sem_t * sem)) {
- if (!sem_utils::is_valid(sem)) {
+ auto *s = reinterpret_cast<Semaphore *>(sem);
+ if (sem == nullptr || !s->is_valid()) {
libc_errno = EINVAL;
return -1;
}
- sem_utils::invalidate(sem);
+ s->destroy();
return 0;
}
diff --git a/libc/src/semaphore/sem_getvalue.cpp b/libc/src/semaphore/sem_getvalue.cpp
index ea84c1e8a6241..574a91fe0229b 100644
--- a/libc/src/semaphore/sem_getvalue.cpp
+++ b/libc/src/semaphore/sem_getvalue.cpp
@@ -18,15 +18,13 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, sem_getvalue,
(sem_t *__restrict sem, int *__restrict sval)) {
- if (!sem_utils::is_valid(sem) || sval == nullptr) {
+ auto *s = reinterpret_cast<Semaphore *>(sem);
+ if (sem == nullptr || !s->is_valid() || sval == nullptr) {
libc_errno = EINVAL;
return -1;
}
- // get value is informational but not a synchronization op
- // RELAXED ordering is enough
- *sval =
- static_cast<int>(sem_utils::value(sem).load(cpp::MemoryOrder::RELAXED));
+ *sval = s->getvalue();
return 0;
}
diff --git a/libc/src/semaphore/sem_init.cpp b/libc/src/semaphore/sem_init.cpp
index a3f6e452b6e6c..68bcca1041bf7 100644
--- a/libc/src/semaphore/sem_init.cpp
+++ b/libc/src/semaphore/sem_init.cpp
@@ -25,7 +25,7 @@ LLVM_LIBC_FUNCTION(int, sem_init,
}
(void)pshared;
- sem_utils::initialize(sem, value);
+ reinterpret_cast<Semaphore *>(sem)->init(value);
return 0;
}
>From 03e19e6207b5958bfc54bffab88b8f2e3c2ff790 Mon Sep 17 00:00:00 2001
From: Pengxiang Huang <huangpengxiang70 at gmail.com>
Date: Wed, 8 Apr 2026 20:31:50 -0400
Subject: [PATCH 3/3] remove sem_t class; improve comments
---
libc/config/linux/x86_64/entrypoints.txt | 5 --
libc/hdr/types/CMakeLists.txt | 8 ---
libc/hdr/types/sem_t.h | 22 --------
libc/include/CMakeLists.txt | 9 ----
libc/include/limits.yaml | 2 -
libc/include/llvm-libc-macros/limits-macros.h | 4 --
libc/include/llvm-libc-types/CMakeLists.txt | 1 -
libc/include/llvm-libc-types/sem_t.h | 20 --------
libc/include/semaphore.yaml | 21 --------
libc/src/semaphore/CMakeLists.txt | 41 ---------------
libc/src/semaphore/posix_semaphore.h | 36 ++++++-------
libc/src/semaphore/sem_destroy.cpp | 30 -----------
libc/src/semaphore/sem_destroy.h | 21 --------
libc/src/semaphore/sem_getvalue.cpp | 31 ------------
libc/src/semaphore/sem_getvalue.h | 21 --------
libc/src/semaphore/sem_init.cpp | 32 ------------
libc/src/semaphore/sem_init.h | 21 --------
libc/test/src/semaphore/CMakeLists.txt | 10 +---
libc/test/src/semaphore/semaphore_test.cpp | 50 +++++--------------
19 files changed, 27 insertions(+), 358 deletions(-)
delete mode 100644 libc/hdr/types/sem_t.h
delete mode 100644 libc/include/llvm-libc-types/sem_t.h
delete mode 100644 libc/include/semaphore.yaml
delete mode 100644 libc/src/semaphore/sem_destroy.cpp
delete mode 100644 libc/src/semaphore/sem_destroy.h
delete mode 100644 libc/src/semaphore/sem_getvalue.cpp
delete mode 100644 libc/src/semaphore/sem_getvalue.h
delete mode 100644 libc/src/semaphore/sem_init.cpp
delete mode 100644 libc/src/semaphore/sem_init.h
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 72fc463aac362..90a0dade5435a 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1233,11 +1233,6 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_spin_lock
libc.src.pthread.pthread_spin_trylock
libc.src.pthread.pthread_spin_unlock
-
- # semaphore.h entrypoints
- libc.src.semaphore.sem_destroy
- libc.src.semaphore.sem_getvalue
- libc.src.semaphore.sem_init
libc.src.pthread.pthread_self
libc.src.pthread.pthread_setname_np
libc.src.pthread.pthread_setspecific
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index 0862f0f9efecf..7e1a8974fa486 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -282,14 +282,6 @@ add_proxy_header_library(
libc.include.llvm-libc-types.pid_t
)
-add_proxy_header_library(
- sem_t
- HDRS
- sem_t.h
- FULL_BUILD_DEPENDS
- libc.include.llvm-libc-types.sem_t
-)
-
add_proxy_header_library(
pthread_barrier_t
HDRS
diff --git a/libc/hdr/types/sem_t.h b/libc/hdr/types/sem_t.h
deleted file mode 100644
index e057bca6b98df..0000000000000
--- a/libc/hdr/types/sem_t.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//===-- Definition of sem_t type -----------------------------------------===//
-//
-// 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_TYPES_SEM_T_H
-#define LLVM_LIBC_HDR_TYPES_SEM_T_H
-
-#ifdef LIBC_FULL_BUILD
-
-#include "include/llvm-libc-types/sem_t.h"
-
-#else // Overlay mode
-
-#error "Cannot overlay sem_t"
-
-#endif // LLVM_LIBC_FULL_BUILD
-
-#endif // LLVM_LIBC_HDR_TYPES_SEM_T_H
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index aa289a4f6fa88..3375e4e21e338 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -471,15 +471,6 @@ add_header_macro(
.llvm-libc-types.struct_timespec
)
-add_header_macro(
- semaphore
- ../libc/include/semaphore.yaml
- semaphore.h
- DEPENDS
- .llvm-libc-types.sem_t
- .llvm_libc_common_h
-)
-
add_header_macro(
spawn
../libc/include/spawn.yaml
diff --git a/libc/include/limits.yaml b/libc/include/limits.yaml
index f7576d89a5d80..1f0956128fb00 100644
--- a/libc/include/limits.yaml
+++ b/libc/include/limits.yaml
@@ -52,8 +52,6 @@ macros:
macro_header: limits-macros.h
- macro_name: ULLONG_MAX
macro_header: limits-macros.h
- - macro_name: SEM_VALUE_MAX
- macro_header: limits-macros.h
- macro_name: SCHAR_MIN
macro_header: limits-macros.h
- macro_name: UCHAR_MIN
diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index 0f999b2bedd19..79bbbe401eb02 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -173,10 +173,6 @@
#define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
#endif // ULLONG_MAX
-#ifndef SEM_VALUE_MAX
-#define SEM_VALUE_MAX INT_MAX
-#endif // SEM_VALUE_MAX
-
// *_MIN macros
#ifndef SCHAR_MIN
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index ec4719a5e57a1..0d6bc0982b847 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -84,7 +84,6 @@ add_header(pthread_rwlockattr_t HDR pthread_rwlockattr_t.h)
add_header(pthread_spinlock_t HDR pthread_spinlock_t.h DEPENDS .pid_t)
add_header(pthread_t HDR pthread_t.h DEPENDS .__thread_type)
add_header(rlim_t HDR rlim_t.h)
-add_header(sem_t HDR sem_t.h DEPENDS .__futex_word)
if(LIBC_TYPES_TIME_T_IS_32_BIT)
add_header(time_t HDR time_t_32.h DEST_HDR time_t.h)
else()
diff --git a/libc/include/llvm-libc-types/sem_t.h b/libc/include/llvm-libc-types/sem_t.h
deleted file mode 100644
index b9596f4e65707..0000000000000
--- a/libc/include/llvm-libc-types/sem_t.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//===-- Definition of sem_t type -----------------------------------------===//
-//
-// 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_TYPES_SEM_T_H
-#define LLVM_LIBC_TYPES_SEM_T_H
-
-#include "__futex_word.h"
-
-typedef struct {
- __futex_word __value; // current semaphore count
- unsigned int __canary; // used for sanity check
- unsigned char __reserved[8]; // for future usage, total fixed size 16 bytes
-} sem_t;
-
-#endif // LLVM_LIBC_TYPES_SEM_T_H
diff --git a/libc/include/semaphore.yaml b/libc/include/semaphore.yaml
deleted file mode 100644
index a56e2eca1c390..0000000000000
--- a/libc/include/semaphore.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-header: semaphore.h
-standards:
- - posix
-types:
- - type_name: sem_t
-functions:
- - name: sem_destroy
- return_type: int
- arguments:
- - type: sem_t *
- - name: sem_getvalue
- return_type: int
- arguments:
- - type: sem_t *__restrict
- - type: int *__restrict
- - name: sem_init
- return_type: int
- arguments:
- - type: sem_t *
- - type: int
- - type: unsigned int
diff --git a/libc/src/semaphore/CMakeLists.txt b/libc/src/semaphore/CMakeLists.txt
index 4a805059ca20f..ac73eb8e87b56 100644
--- a/libc/src/semaphore/CMakeLists.txt
+++ b/libc/src/semaphore/CMakeLists.txt
@@ -3,47 +3,6 @@ add_header_library(
HDRS
posix_semaphore.h
DEPENDS
- libc.hdr.types.sem_t
libc.src.__support.CPP.atomic
libc.src.__support.threads.linux.futex_utils
)
-
-add_entrypoint_object(
- sem_init
- SRCS
- sem_init.cpp
- HDRS
- sem_init.h
- DEPENDS
- .posix_semaphore
- libc.hdr.errno_macros
- libc.hdr.limits_macros
- libc.include.semaphore
- libc.src.errno.errno
-)
-
-add_entrypoint_object(
- sem_destroy
- SRCS
- sem_destroy.cpp
- HDRS
- sem_destroy.h
- DEPENDS
- .posix_semaphore
- libc.hdr.errno_macros
- libc.include.semaphore
- libc.src.errno.errno
-)
-
-add_entrypoint_object(
- sem_getvalue
- SRCS
- sem_getvalue.cpp
- HDRS
- sem_getvalue.h
- DEPENDS
- .posix_semaphore
- libc.hdr.errno_macros
- libc.include.semaphore
- libc.src.errno.errno
-)
diff --git a/libc/src/semaphore/posix_semaphore.h b/libc/src/semaphore/posix_semaphore.h
index f42dbbb720420..7b14d41165a96 100644
--- a/libc/src/semaphore/posix_semaphore.h
+++ b/libc/src/semaphore/posix_semaphore.h
@@ -1,4 +1,4 @@
-//===-- Internal Semaphore types and helpers for POSIX semaphores ---------===//
+//===-- Internal Semaphore implementation for POSIX semaphores ------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -9,7 +9,6 @@
#ifndef LLVM_LIBC_SRC_SEMAPHORE_POSIX_SEMAPHORE_H
#define LLVM_LIBC_SRC_SEMAPHORE_POSIX_SEMAPHORE_H
-#include "hdr/types/sem_t.h"
#include "src/__support/CPP/atomic.h"
#include "src/__support/common.h"
#include "src/__support/threads/linux/futex_utils.h"
@@ -20,7 +19,9 @@ class Semaphore {
Futex value;
unsigned int canary;
- // 0x53 = S, 0x45 = E, 0x4D = M, 0x31 = 1
+ // A private constant canary used to detect use of uninitialized or
+ // destroyed semaphores. Chose "SEM1" in ASCII (0x53='S', 0x45='E',
+ // 0x4D='M', 0x31='1').
static constexpr unsigned int SEM_CANARY = 0x53454D31U;
public:
@@ -29,39 +30,30 @@ class Semaphore {
// 2. Add the posting and waiting operations: sem_post, sem_wait,
// sem_trywait, sem_timedwait, sem_clockwait.
- LIBC_INLINE void init(unsigned int initial_value) {
- // init happens before the semaphore is published to any threads
- // initialize a initialized semaphore is undefined
- // so RELAXED ordering is enough
- value.store(initial_value, cpp::MemoryOrder::RELAXED);
- canary = SEM_CANARY;
- }
+ LIBC_INLINE constexpr Semaphore(unsigned int value)
+ : value(value), canary(SEM_CANARY) {}
- // sanity check for a given semaphore pointer
+ // Sanity check to detect use of uninitialized or destroyed semaphores.
LIBC_INLINE bool is_valid() const { return canary == SEM_CANARY; }
LIBC_INLINE void destroy() {
- // invalidate is safe only when no threads is using
- // blocked by destroyed semaphore is undefined
- // use a destroyed semaphore is undefined
- // RELAXED ordering is enough
+ // Destroying a semaphore while threads are blocked on it is undefined
+ // behavior. Similarly, using a destroyed semaphore is undefined.
+ // Therefore no concurrency safe destruction is required here,
+ // RELAXED memory ordering is sufficient.
value.store(0, cpp::MemoryOrder::RELAXED);
canary = 0;
}
LIBC_INLINE int getvalue() const {
- // get value is informational but not a synchronization op
- // RELAXED ordering is enough
+ // get value is informational, not a synchronization op.
+ // RELAXED ordering is enough.
+ // TODO: handle the case where the semaphore is locked.
return static_cast<int>(
const_cast<Futex &>(value).load(cpp::MemoryOrder::RELAXED));
}
};
-static_assert(sizeof(Semaphore) <= sizeof(sem_t),
- "Semaphore must fit within sem_t.");
-static_assert(alignof(Semaphore) <= alignof(sem_t),
- "Semaphore alignment must be compatible with sem_t.");
-
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SEMAPHORE_POSIX_SEMAPHORE_H
diff --git a/libc/src/semaphore/sem_destroy.cpp b/libc/src/semaphore/sem_destroy.cpp
deleted file mode 100644
index 67d003697910e..0000000000000
--- a/libc/src/semaphore/sem_destroy.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//===-- Implementation of sem_destroy ------------------------------------===//
-//
-// 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/semaphore/sem_destroy.h"
-
-#include "src/semaphore/posix_semaphore.h"
-
-#include "hdr/errno_macros.h"
-#include "src/__support/common.h"
-#include "src/__support/libc_errno.h"
-
-namespace LIBC_NAMESPACE_DECL {
-
-LLVM_LIBC_FUNCTION(int, sem_destroy, (sem_t * sem)) {
- auto *s = reinterpret_cast<Semaphore *>(sem);
- if (sem == nullptr || !s->is_valid()) {
- libc_errno = EINVAL;
- return -1;
- }
-
- s->destroy();
- return 0;
-}
-
-} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/semaphore/sem_destroy.h b/libc/src/semaphore/sem_destroy.h
deleted file mode 100644
index b664cf97eecf0..0000000000000
--- a/libc/src/semaphore/sem_destroy.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//===-- Implementation header for sem_destroy ------------------*- 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_SEMAPHORE_SEM_DESTROY_H
-#define LLVM_LIBC_SRC_SEMAPHORE_SEM_DESTROY_H
-
-#include "hdr/types/sem_t.h"
-#include "src/__support/macros/config.h"
-
-namespace LIBC_NAMESPACE_DECL {
-
-int sem_destroy(sem_t *sem);
-
-} // namespace LIBC_NAMESPACE_DECL
-
-#endif // LLVM_LIBC_SRC_SEMAPHORE_SEM_DESTROY_H
diff --git a/libc/src/semaphore/sem_getvalue.cpp b/libc/src/semaphore/sem_getvalue.cpp
deleted file mode 100644
index 574a91fe0229b..0000000000000
--- a/libc/src/semaphore/sem_getvalue.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-//===-- Implementation of sem_getvalue -----------------------------------===//
-//
-// 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/semaphore/sem_getvalue.h"
-
-#include "src/semaphore/posix_semaphore.h"
-
-#include "hdr/errno_macros.h"
-#include "src/__support/common.h"
-#include "src/__support/libc_errno.h"
-
-namespace LIBC_NAMESPACE_DECL {
-
-LLVM_LIBC_FUNCTION(int, sem_getvalue,
- (sem_t *__restrict sem, int *__restrict sval)) {
- auto *s = reinterpret_cast<Semaphore *>(sem);
- if (sem == nullptr || !s->is_valid() || sval == nullptr) {
- libc_errno = EINVAL;
- return -1;
- }
-
- *sval = s->getvalue();
- return 0;
-}
-
-} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/semaphore/sem_getvalue.h b/libc/src/semaphore/sem_getvalue.h
deleted file mode 100644
index 4ba49491746b1..0000000000000
--- a/libc/src/semaphore/sem_getvalue.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//===-- Implementation header for sem_getvalue -----------------*- 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_SEMAPHORE_SEM_GETVALUE_H
-#define LLVM_LIBC_SRC_SEMAPHORE_SEM_GETVALUE_H
-
-#include "hdr/types/sem_t.h"
-#include "src/__support/macros/config.h"
-
-namespace LIBC_NAMESPACE_DECL {
-
-int sem_getvalue(sem_t *__restrict sem, int *__restrict sval);
-
-} // namespace LIBC_NAMESPACE_DECL
-
-#endif // LLVM_LIBC_SRC_SEMAPHORE_SEM_GETVALUE_H
diff --git a/libc/src/semaphore/sem_init.cpp b/libc/src/semaphore/sem_init.cpp
deleted file mode 100644
index 68bcca1041bf7..0000000000000
--- a/libc/src/semaphore/sem_init.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===-- Implementation of sem_init ---------------------------------------===//
-//
-// 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/semaphore/sem_init.h"
-
-#include "src/semaphore/posix_semaphore.h"
-
-#include "hdr/errno_macros.h"
-#include "hdr/limits_macros.h"
-#include "src/__support/common.h"
-#include "src/__support/libc_errno.h"
-
-namespace LIBC_NAMESPACE_DECL {
-
-LLVM_LIBC_FUNCTION(int, sem_init,
- (sem_t * sem, int pshared, unsigned int value)) {
- if (sem == nullptr || value > SEM_VALUE_MAX) {
- libc_errno = EINVAL;
- return -1;
- }
-
- (void)pshared;
- reinterpret_cast<Semaphore *>(sem)->init(value);
- return 0;
-}
-
-} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/semaphore/sem_init.h b/libc/src/semaphore/sem_init.h
deleted file mode 100644
index 8a3114ddfa10f..0000000000000
--- a/libc/src/semaphore/sem_init.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//===-- Implementation header for sem_init ----------------------*- 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_SEMAPHORE_SEM_INIT_H
-#define LLVM_LIBC_SRC_SEMAPHORE_SEM_INIT_H
-
-#include "hdr/types/sem_t.h"
-#include "src/__support/macros/config.h"
-
-namespace LIBC_NAMESPACE_DECL {
-
-int sem_init(sem_t *sem, int pshared, unsigned int value);
-
-} // namespace LIBC_NAMESPACE_DECL
-
-#endif // LLVM_LIBC_SRC_SEMAPHORE_SEM_INIT_H
diff --git a/libc/test/src/semaphore/CMakeLists.txt b/libc/test/src/semaphore/CMakeLists.txt
index 259c11fe55f07..0c458db5d3669 100644
--- a/libc/test/src/semaphore/CMakeLists.txt
+++ b/libc/test/src/semaphore/CMakeLists.txt
@@ -7,13 +7,5 @@ add_libc_unittest(
SRCS
semaphore_test.cpp
DEPENDS
- libc.hdr.errno_macros
- libc.include.limits
- libc.include.semaphore
- libc.src.errno.errno
- libc.src.semaphore.sem_destroy
- libc.src.semaphore.sem_getvalue
- libc.src.semaphore.sem_init
- libc.test.UnitTest.ErrnoCheckingTest
- libc.test.UnitTest.ErrnoSetterMatcher
+ libc.src.semaphore.posix_semaphore
)
diff --git a/libc/test/src/semaphore/semaphore_test.cpp b/libc/test/src/semaphore/semaphore_test.cpp
index 1e67bb046ad5f..241078ef5a09c 100644
--- a/libc/test/src/semaphore/semaphore_test.cpp
+++ b/libc/test/src/semaphore/semaphore_test.cpp
@@ -1,4 +1,4 @@
-//===-- Unittests for POSIX semaphores -----------------------------------===//
+//===-- Unittests for the internal Semaphore class ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,46 +6,20 @@
//
//===----------------------------------------------------------------------===//
-#include "hdr/errno_macros.h"
-#include "src/semaphore/sem_destroy.h"
-#include "src/semaphore/sem_getvalue.h"
-#include "src/semaphore/sem_init.h"
-#include "test/UnitTest/ErrnoCheckingTest.h"
-#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "src/semaphore/posix_semaphore.h"
#include "test/UnitTest/Test.h"
-#include <limits.h>
-#include <semaphore.h>
+using LIBC_NAMESPACE::Semaphore;
-using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
-
-namespace {
-
-using LlvmLibcSemaphoreTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
-
-} // namespace
-
-TEST_F(LlvmLibcSemaphoreTest, PublicSurface) {
- sem_t sem = {};
- (void)sem;
- ASSERT_GE(SEM_VALUE_MAX, 32767);
-}
-
-TEST_F(LlvmLibcSemaphoreTest, UnnamedLifecycle) {
- sem_t sem;
- int value = -1;
-
- ASSERT_THAT(LIBC_NAMESPACE::sem_init(&sem, 0, 3), Succeeds());
- ASSERT_THAT(LIBC_NAMESPACE::sem_getvalue(&sem, &value), Succeeds());
- ASSERT_EQ(value, 3);
-
- ASSERT_THAT(LIBC_NAMESPACE::sem_destroy(&sem), Succeeds());
- ASSERT_THAT(LIBC_NAMESPACE::sem_getvalue(&sem, &value), Fails(EINVAL));
+TEST(LlvmLibcSemaphoreTest, InitAndGetValue) {
+ Semaphore sem(3);
+ ASSERT_TRUE(sem.is_valid());
+ ASSERT_EQ(sem.getvalue(), 3);
}
-TEST_F(LlvmLibcSemaphoreTest, UnnamedInitRejectsTooLargeValue) {
- sem_t sem;
- ASSERT_THAT(LIBC_NAMESPACE::sem_init(
- &sem, 0, static_cast<unsigned int>(SEM_VALUE_MAX) + 1U),
- Fails(EINVAL));
+TEST(LlvmLibcSemaphoreTest, Destroy) {
+ Semaphore sem(5);
+ ASSERT_TRUE(sem.is_valid());
+ sem.destroy();
+ ASSERT_FALSE(sem.is_valid());
}
More information about the libc-commits
mailing list