mutex: use uint8_t instead of int for lock value
This commit is contained in:
parent
d20da423ec
commit
f54a4a0fa9
2 changed files with 108 additions and 19 deletions
|
@ -2,32 +2,51 @@
|
||||||
|
|
||||||
.include "asm.S"
|
.include "asm.S"
|
||||||
|
|
||||||
.text
|
.section .text.shared
|
||||||
|
|
||||||
/* int _mutex_lock(int *lock); */
|
/* void _mutex_lock(uint8_t *lock); */
|
||||||
func_begin _mutex_lock
|
func_begin _mutex_lock
|
||||||
|
|
||||||
mov r1, #1
|
mov r1, #1 /* uint8_t newval = 1; */
|
||||||
|
|
||||||
1: ldrex r2, [r0]
|
1: ldrexb r2, [r0] /* uint8_t tmp = __ldrexb(lock); */
|
||||||
cmp r2, #0
|
|
||||||
itt eq
|
|
||||||
strexeq r2, r1, [r0]
|
|
||||||
cmpeq r2, #0
|
|
||||||
|
|
||||||
bne 1b
|
cmp r2, #0
|
||||||
|
itt eq
|
||||||
|
strexbeq r2, r1, [r0] /* tmp = __strexb(newval, lock); */
|
||||||
|
cmpeq r2, #0
|
||||||
|
|
||||||
|
bne 1b
|
||||||
|
|
||||||
dmb
|
dmb
|
||||||
eor r0, r0
|
bx lr
|
||||||
bx lr
|
|
||||||
|
|
||||||
func_end _mutex_lock
|
func_end _mutex_lock
|
||||||
|
|
||||||
/* int _mutex_unlock(int *lock); */
|
/* int _mutex_trylock(uint8_t *lock); */
|
||||||
|
func_begin _mutex_trylock
|
||||||
|
|
||||||
|
mov r1, #1 /* uint8_t newval = 1; */
|
||||||
|
/* move lock to r2 to make room in r0 for the return value */
|
||||||
|
mov r2, r0
|
||||||
|
|
||||||
|
ldrexb r0, [r2] /* uint8_t tmp = __ldrexb(lock); */
|
||||||
|
|
||||||
|
cmp r0, #0
|
||||||
|
ittt eq
|
||||||
|
strexbeq r0, r1, [r2] /* tmp = __strexb(newval, lock); */
|
||||||
|
cmpeq r0, #0
|
||||||
|
dmbeq /* if (tmp == 0) __dmb(); */
|
||||||
|
|
||||||
|
bx lr /* return tmp; */
|
||||||
|
|
||||||
|
func_end _mutex_trylock
|
||||||
|
|
||||||
|
/* void _mutex_unlock(uint8_t *lock); */
|
||||||
func_begin _mutex_unlock
|
func_begin _mutex_unlock
|
||||||
|
|
||||||
mov r1, #0
|
mov r1, #0
|
||||||
str r1, [r0]
|
strb r1, [r0]
|
||||||
dmb
|
dmb
|
||||||
bx lr
|
bx lr
|
||||||
|
|
||||||
|
|
|
@ -2,38 +2,108 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ardix/types.h>
|
||||||
|
|
||||||
#include <toolchain.h>
|
#include <toolchain.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup mutex Synchronization Primitives
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A simple mutex.
|
||||||
|
*
|
||||||
|
* Mutexes can be locked using the `mutex_lock()` and `mutex_unlock()` methods
|
||||||
|
* respectively. The former will block until the lock is acquired and thus
|
||||||
|
* should never be used from interrupt context. Use `mutex_trylock()` if you
|
||||||
|
* don't want blocking.
|
||||||
|
*/
|
||||||
struct mutex {
|
struct mutex {
|
||||||
int lock;
|
uint8_t lock; /**< Current lock value, don't read directly */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int _mutex_lock(int *lock);
|
/**
|
||||||
extern int _mutex_trylock(int *lock);
|
* @brief Internal assembly routine for `mutex_lock()`.
|
||||||
extern void _mutex_unlock(int *lock);
|
* @private
|
||||||
|
*/
|
||||||
|
extern void _mutex_lock(uint8_t *lock);
|
||||||
|
/**
|
||||||
|
* @brief Internal assembly routine for `mutex_trylock()`.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
extern int _mutex_trylock(uint8_t *lock);
|
||||||
|
/**
|
||||||
|
* @brief Internal assembly routine for `mutex_unlock()`.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
extern void _mutex_unlock(uint8_t *lock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a mutex and set it to unlocked.
|
||||||
|
*
|
||||||
|
* @param mutex Mutex to initialize
|
||||||
|
*/
|
||||||
__always_inline void mutex_init(struct mutex *mutex)
|
__always_inline void mutex_init(struct mutex *mutex)
|
||||||
{
|
{
|
||||||
mutex->lock = 0;
|
mutex->lock = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__always_inline int mutex_lock(struct mutex *mutex)
|
/**
|
||||||
|
* @brief Acquire an exclusive lock on a mutex.
|
||||||
|
* This call will block until the lock was acquired and therefore cannot fail.
|
||||||
|
*
|
||||||
|
* @param mutex Mutex to lock
|
||||||
|
*/
|
||||||
|
__always_inline void mutex_lock(struct mutex *mutex)
|
||||||
{
|
{
|
||||||
return _mutex_lock(&mutex->lock);
|
_mutex_lock(&mutex->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release an exclusive lock on a mutex.
|
||||||
|
*
|
||||||
|
* @param mutex Mutex to unlock
|
||||||
|
*/
|
||||||
__always_inline void mutex_unlock(struct mutex *mutex)
|
__always_inline void mutex_unlock(struct mutex *mutex)
|
||||||
{
|
{
|
||||||
_mutex_unlock(&mutex->lock);
|
_mutex_unlock(&mutex->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Attempt to acquire an exclusive lock on a mutex.
|
||||||
|
* The return value is zero if the claim succeeds, and nonzero otherwise.
|
||||||
|
*
|
||||||
|
* @param mutex Mutex to attempt to lock
|
||||||
|
* @returns 0 if the lock was acquired, a nonzero value otherwise
|
||||||
|
*/
|
||||||
__always_inline int mutex_trylock(struct mutex *mutex)
|
__always_inline int mutex_trylock(struct mutex *mutex)
|
||||||
{
|
{
|
||||||
return _mutex_trylock(&mutex->lock);
|
return _mutex_trylock(&mutex->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Determine whether a mutex is locked.
|
||||||
|
*
|
||||||
|
* @param mutex Mutex to get the lock value of
|
||||||
|
* @returns Nonzero if the mutex is locked, zero otherwise
|
||||||
|
*/
|
||||||
|
__always_inline int mutex_is_locked(struct mutex *mutex)
|
||||||
|
{
|
||||||
|
return mutex->lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Statically declare and define a mutex (file scope only).
|
||||||
|
* The mutex does not need to be initialized using `mutex_init()`.
|
||||||
|
*
|
||||||
|
* @param name Name of the `struct mutex` that will be defined
|
||||||
|
*/
|
||||||
#define MUTEX(name) struct mutex name = { .lock = 0 }
|
#define MUTEX(name) struct mutex name = { .lock = 0 }
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file is part of Ardix.
|
* This file is part of Ardix.
|
||||||
* Copyright (c) 2020, 2021 Felix Kopp <owo@fef.moe>.
|
* Copyright (c) 2020, 2021 Felix Kopp <owo@fef.moe>.
|
||||||
|
|
Loading…
Reference in a new issue