Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libc/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
8 changes: 8 additions & 0 deletions libc/src/semaphore/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
add_header_library(
posix_semaphore
HDRS
posix_semaphore.h
DEPENDS
libc.src.__support.CPP.atomic
libc.src.__support.threads.linux.futex_utils
)
59 changes: 59 additions & 0 deletions libc/src/semaphore/posix_semaphore.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//===-- 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.
// 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 "src/__support/CPP/atomic.h"
#include "src/__support/common.h"
#include "src/__support/threads/linux/futex_utils.h"

namespace LIBC_NAMESPACE_DECL {

class Semaphore {
Futex value;
unsigned int canary;

// 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:
// 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 constexpr Semaphore(unsigned int value)
: value(value), canary(SEM_CANARY) {}

// Sanity check to detect use of uninitialized or destroyed semaphores.
LIBC_INLINE bool is_valid() const { return canary == SEM_CANARY; }

LIBC_INLINE void destroy() {
// 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, 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));
}
};

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_SEMAPHORE_POSIX_SEMAPHORE_H
1 change: 1 addition & 0 deletions libc/test/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,5 @@ add_subdirectory(spawn)

if(${LIBC_TARGET_OS} STREQUAL "linux")
add_subdirectory(pthread)
add_subdirectory(semaphore)
endif()
11 changes: 11 additions & 0 deletions libc/test/src/semaphore/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
add_custom_target(libc_semaphore_unittests)

add_libc_unittest(
semaphore_test
SUITE
libc_semaphore_unittests
SRCS
semaphore_test.cpp
DEPENDS
libc.src.semaphore.posix_semaphore
)
25 changes: 25 additions & 0 deletions libc/test/src/semaphore/semaphore_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//===-- 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.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/semaphore/posix_semaphore.h"
#include "test/UnitTest/Test.h"

using LIBC_NAMESPACE::Semaphore;

TEST(LlvmLibcSemaphoreTest, InitAndGetValue) {
Semaphore sem(3);
ASSERT_TRUE(sem.is_valid());
ASSERT_EQ(sem.getvalue(), 3);
}

TEST(LlvmLibcSemaphoreTest, Destroy) {
Semaphore sem(5);
ASSERT_TRUE(sem.is_valid());
sem.destroy();
ASSERT_FALSE(sem.is_valid());
}
Loading