libctru/libctru/include/3ds/synchronization.h
2015-12-28 20:46:04 -08:00

117 lines
3.0 KiB
C

/**
* @file synchronization.h
* @brief Provides synchronization locks.
*/
#pragma once
#include <sys/lock.h>
/// A light lock.
typedef _LOCK_T LightLock;
/// A recursive lock.
typedef _LOCK_RECURSIVE_T RecursiveLock;
/// Performs a Data Synchronization Barrier operation.
static inline void __dsb(void)
{
__asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (0) : "memory");
}
/// Performs a clrex operation.
static inline void __clrex(void)
{
__asm__ __volatile__("clrex" ::: "memory");
}
/**
* @brief Performs a ldrex operation.
* @param addr Address to perform the operation on.
* @return The resulting value.
*/
static inline s32 __ldrex(s32* addr)
{
s32 val;
__asm__ __volatile__("ldrex %[val], %[addr]" : [val] "=r" (val) : [addr] "Q" (*addr));
return val;
}
/**
* @brief Performs a strex operation.
* @param addr Address to perform the operation on.
* @param val Value to store.
* @return Whether the operation was successful.
*/
static inline bool __strex(s32* addr, s32 val)
{
bool res;
__asm__ __volatile__("strex %[res], %[val], %[addr]" : [res] "=&r" (res) : [val] "r" (val), [addr] "Q" (*addr));
return res;
}
/// Performs an atomic pre-increment operation.
#define AtomicIncrement(ptr) __atomic_add_fetch((u32*)(ptr), 1, __ATOMIC_SEQ_CST)
/// Performs an atomic pre-decrement operation.
#define AtomicDecrement(ptr) __atomic_sub_fetch((u32*)(ptr), 1, __ATOMIC_SEQ_CST)
/// Performs an atomic post-increment operation.
#define AtomicPostIncrement(ptr) __atomic_fetch_add((u32*)(ptr), 1, __ATOMIC_SEQ_CST)
/// Performs an atomic post-decrement operation.
#define AtomicPostDecrement(ptr) __atomic_fetch_sub((u32*)(ptr), 1, __ATOMIC_SEQ_CST)
/// Performs an atomic swap operation.
#define AtomicSwap(ptr, value) __atomic_exchange_n((u32*)(ptr), (value), __ATOMIC_SEQ_CST)
/**
* @brief Retrieves the synchronization subsystem's address arbiter handle.
* @return The synchronization subsystem's address arbiter handle.
*/
Handle __sync_get_arbiter(void);
/**
* @brief Initializes a light lock.
* @param lock Pointer to the lock.
*/
void LightLock_Init(LightLock* lock);
/**
* @brief Locks a light lock.
* @param lock Pointer to the lock.
*/
void LightLock_Lock(LightLock* lock);
/**
* @brief Attempts to lock a light lock.
* @param lock Pointer to the lock.
* @return Zero on success, non-zero on failure.
*/
int LightLock_TryLock(LightLock* lock);
/**
* @brief Unlocks a light lock.
* @param lock Pointer to the lock.
*/
void LightLock_Unlock(LightLock* lock);
/**
* @brief Initializes a recursive lock.
* @param lock Pointer to the lock.
*/
void RecursiveLock_Init(RecursiveLock* lock);
/**
* @brief Locks a recursive lock.
* @param lock Pointer to the lock.
*/
void RecursiveLock_Lock(RecursiveLock* lock);
/**
* @brief Attempts to lock a recursive lock.
* @param lock Pointer to the lock.
* @return Zero on success, non-zero on failure.
*/
int RecursiveLock_TryLock(RecursiveLock* lock);
/**
* @brief Unlocks a recursive lock.
* @param lock Pointer to the lock.
*/
void RecursiveLock_Unlock(RecursiveLock* lock);