blob: b1f7da42901e526b717f945d49f49a51096f9d43 [file] [edit]
//===-- 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