blob: 79506d7e6911a0ce78aa2c2908741ad384bbe16d [file] [log] [blame]
//===--- Implementation of a Linux mutex class ------------------*- 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___SUPPORT_THREADS_LINUX_MUTEX_H
#define LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_MUTEX_H
#include "hdr/types/pid_t.h"
#include "src/__support/CPP/optional.h"
#include "src/__support/libc_assert.h"
#include "src/__support/threads/linux/futex_utils.h"
#include "src/__support/threads/linux/raw_mutex.h"
#include "src/__support/threads/mutex_common.h"
namespace LIBC_NAMESPACE {
// TODO: support shared/recursive/robust mutexes.
class Mutex final : private RawMutex {
// reserved timed, may be useful when combined with other flags.
unsigned char timed;
unsigned char recursive;
unsigned char robust;
unsigned char pshared;
// TLS address may not work across forked processes. Use thread id instead.
pid_t owner;
unsigned long long lock_count;
public:
LIBC_INLINE constexpr Mutex(bool is_timed, bool is_recursive, bool is_robust,
bool is_pshared)
: RawMutex(), timed(is_timed), recursive(is_recursive), robust(is_robust),
pshared(is_pshared), owner(0), lock_count(0) {}
LIBC_INLINE static MutexError init(Mutex *mutex, bool is_timed, bool isrecur,
bool isrobust, bool is_pshared) {
RawMutex::init(mutex);
mutex->timed = is_timed;
mutex->recursive = isrecur;
mutex->robust = isrobust;
mutex->pshared = is_pshared;
mutex->owner = 0;
mutex->lock_count = 0;
return MutexError::NONE;
}
LIBC_INLINE static MutexError destroy(Mutex *lock) {
LIBC_ASSERT(lock->owner == 0 && lock->lock_count == 0 &&
"Mutex destroyed while being locked.");
RawMutex::destroy(lock);
return MutexError::NONE;
}
// TODO: record owner and lock count.
LIBC_INLINE MutexError lock() {
// Since timeout is not specified, we do not need to check the return value.
this->RawMutex::lock(
/* timeout=*/cpp::nullopt, this->pshared);
return MutexError::NONE;
}
// TODO: record owner and lock count.
LIBC_INLINE MutexError timed_lock(internal::AbsTimeout abs_time) {
if (this->RawMutex::lock(abs_time, this->pshared))
return MutexError::NONE;
return MutexError::TIMEOUT;
}
LIBC_INLINE MutexError unlock() {
if (this->RawMutex::unlock(this->pshared))
return MutexError::NONE;
return MutexError::UNLOCK_WITHOUT_LOCK;
}
// TODO: record owner and lock count.
LIBC_INLINE MutexError try_lock() {
if (this->RawMutex::try_lock())
return MutexError::NONE;
return MutexError::BUSY;
}
};
} // namespace LIBC_NAMESPACE
#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_MUTEX_H