4#include <cheriot-atomic.hh>
16static constexpr bool DebugLocks =
23using LockDebug = ConditionalDebug<DebugLocks,
"Locking">;
25__clang_ignored_warning_push(
"-Watomic-alignment");
45template<
bool IsPriorityInherited>
56 __always_inline
int try_lock_internal(TimeoutArgument timeout)
58 if constexpr (IsPriorityInherited)
76 __always_inline
bool try_lock(TimeoutArgument timeout)
78 return try_lock_internal(timeout) == 0;
113 auto res = try_lock_internal(&t);
114 LockDebug::Invariant(res == 0,
"FlagLock lock() failed: {}", res);
145 requires(IsPriorityInherited)
165 __always_inline
bool try_lock(TimeoutArgument timeout)
285 { l.try_lock(t) } -> std::same_as<bool>;
296template<
typename Lock>
318 : wrappedLock(&
lock), isOwned(true)
330 : wrappedLock(&
lock), isOwned(false)
337 : wrappedLock(guard.wrappedLock), isOwned(guard.isOwned)
339 guard.wrappedLock =
nullptr;
340 guard.isOwned =
false;
355 LockDebug::Assert(!isOwned,
"Trying to lock an already-locked lock");
366 LockDebug::Assert(isOwned,
"Trying to unlock an unlocked lock");
367 wrappedLock->unlock();
377 wrappedLock =
nullptr;
391 LockDebug::Assert(!isOwned,
"Trying to lock an already-locked lock");
392 isOwned = wrappedLock->try_lock(timeout);
401 wrappedLock->unlock();
430 int yield(TimeoutArgument t, uint32_t ticks = 1)
435 if (
int sleepRes =
thread_sleep(&smallSleep); sleepRes < 0)
440 t.elapse_from(smallSleep);
471 std::numeric_limits<uint32_t>::max());
480 template<TryLockable Mutex>
481 int wait(TimeoutArgument t, Mutex &mutex)
483 auto lock = [](TimeoutArgument t,
void *m) {
484 return static_cast<Mutex *
>(m)->try_lock(t) ? 0 : -ETIMEDOUT;
486 auto unlock = [](
void *m) {
487 static_cast<Mutex *
>(m)->unlock();
501 template<Lockable Mutex>
502 int wait(TimeoutArgument t, Mutex &mutex)
505 auto lock = [](TimeoutArgument t,
void *m) {
506 static_cast<Mutex *
>(m)->lock();
509 auto unlock = [](
void *m) {
510 static_cast<Mutex *
>(m)->unlock();
517__clang_ignored_warning_pop();
Condition variable C++ wrapper.
int broadcast()
Wake all waiters.
int signal()
Wake one waiter.
int wait(TimeoutArgument t, Mutex &mutex)
Atomically release mutex, wait until the condition variable is signalled, and reacquire the mutex.
int wait(TimeoutArgument t, Mutex &mutex)
Atomically release mutex, wait until the condition variable is signalled, and reacquire the mutex.
A simple flag log, wrapping an atomic word used with the futex calls.
void upgrade_for_destruction()
Set the lock in destruction mode.
void unlock()
Release the lock.
void lock()
Acquire the lock, potentially blocking forever.
bool try_lock()
Try to acquire the lock, do not block.
uint16_t get_owner_thread_id()
Return the thread ID of the owner of the lock.
bool try_lock(TimeoutArgument timeout)
Attempt to acquire the lock, blocking until a timeout specified by the timeout parameter has expired.
LockGuard(LockGuard &&guard)
Move constructor, transfers ownership of the lock.
int yield(TimeoutArgument t, uint32_t ticks=1)
Drop and reacquire the lock around a yield.
void release()
Unwrap the lock without unlocking it.
~LockGuard()
Destructor, releases the lock.
LockGuard(Lock &lock, TimeoutArgument timeout)
Constructor, attempts to acquire the lock with a timeout.
void unlock()
Explicitly lock the wrapped lock.
LockGuard(Lock &lock)
Constructor, acquires the lock with unbounded wait.
void lock()
Explicitly lock the wrapped lock.
bool try_lock(TimeoutArgument timeout)
If the wrapped lock type supports locking with a timeout, try to lock it with the specified timeout.
Class that implements the locking concept but does not perform locking.
void unlock()
Release the lock.
bool try_lock(TimeoutArgument timeout)
Attempt to acquire the lock with a timeout.
bool try_lock()
Try to acquire the lock, do not block.
void lock()
Acquire the lock.
Priority-inheriting recursive mutex.
void upgrade_for_destruction()
Set the lock in destruction mode.
void unlock()
Release the lock.
bool try_lock()
Try to acquire the lock, do not block.
bool try_lock(TimeoutArgument timeout)
Attempt to acquire the lock, blocking until a timeout specified by the timeout parameter has expired.
void lock()
Acquire the lock, potentially blocking forever.
void lock()
Acquire the lock.
void unlock()
Release the lock.
C++ APIs for assertions, invariants, and writing formatted debug messages to a UART.
Futex (compare-and-wait) APIs.
C compatible interface to synchronisation primitives.
int __cheri_libcall recursivemutex_unlock(struct RecursiveMutexState *mutex)
Unlock a recursive mutex.
int __cheriot_libcall condition_variable_notify(struct ConditionVariableState *conditionVariable, uint32_t waiters)
Signal the condition variable and wake up to the number of waiters specified by the second argument.
static uint16_t flaglock_priority_inheriting_get_owner_thread_id(struct FlagLockState *lock)
Return the thread ID of the owner of the lock.
void __cheri_libcall flaglock_unlock(struct FlagLockState *lock)
Unlock a flag lock.
void __cheri_libcall flaglock_upgrade_for_destruction(struct FlagLockState *lock)
Set a flag lock in destruction mode.
void __cheri_libcall ticketlock_unlock(struct TicketLockState *lock)
Release a ticket lock.
int __cheri_libcall flaglock_trylock(TimeoutArgument timeout, struct FlagLockState *lock)
Try to lock a flag lock.
int __cheri_libcall flaglock_priority_inheriting_trylock(TimeoutArgument timeout, struct FlagLockState *lock)
Try to lock a flag lock.
int __cheri_libcall recursivemutex_trylock(TimeoutArgument timeout, struct RecursiveMutexState *lock)
Try to acquire a recursive mutex.
int __cheriot_libcall condition_variable_wait(TimeoutArgument t, struct ConditionVariableState *conditionVariable, void *mutex, int(*mutexLock)(TimeoutArgument, void *), int(*mutexUnlock)(void *))
Wait on a condition variable.
void __cheri_libcall ticketlock_lock(struct TicketLockState *lock)
Acquire a ticket lock.
Condition variable state.
State for a recursive mutex.
Ticket locks use two monotonic counters to store the lock state.
Structure representing a timeout.
Functions and types used for thread management.
int thread_sleep(TimeoutArgument timeout, uint32_t flags)
Sleep for at most the specified timeout (see timeout.h).
static const Ticks UnlimitedTimeout
Value indicating an unbounded timeout for use with Timeout.