| //===-- Linux 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_LINUX_SEMAPHORE_H |
| #define LLVM_LIBC_SRC_SEMAPHORE_LINUX_SEMAPHORE_H |
| |
| #include "hdr/types/mode_t.h" |
| #include "src/__support/CPP/atomic.h" |
| #include "src/__support/common.h" |
| #include "src/__support/error_or.h" |
| #include "src/__support/threads/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: |
| // 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)); |
| } |
| |
| // Named semaphore operations. |
| // creates or opens a named semaphore backed by a file in /dev/shm/. |
| // When O_CREAT is specified in oflag, mode and value are used for |
| // initialization. |
| static ErrorOr<Semaphore *> open(const char *name, int oflag, mode_t mode, |
| unsigned int value); |
| |
| // unmaps a named semaphore. |
| static int close(Semaphore *sem); |
| |
| // removes a named semaphore from the filesystem. |
| static int unlink(const char *name); |
| }; |
| |
| } // namespace LIBC_NAMESPACE_DECL |
| |
| #endif // LLVM_LIBC_SRC_SEMAPHORE_LINUX_SEMAPHORE_H |