80 lines
2.1 KiB
C
80 lines
2.1 KiB
C
/*
|
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "pico/mutex.h"
|
|
#include "pico/time.h"
|
|
|
|
#if !PICO_NO_HARDWARE
|
|
static_assert(sizeof(mutex_t) == 8, "");
|
|
#endif
|
|
|
|
void mutex_init(mutex_t *mtx) {
|
|
lock_init(&mtx->core, next_striped_spin_lock_num());
|
|
mtx->owner = -1;
|
|
__mem_fence_release();
|
|
}
|
|
|
|
void __time_critical_func(mutex_enter_blocking)(mutex_t *mtx) {
|
|
assert(mtx->core.spin_lock);
|
|
bool block = true;
|
|
do {
|
|
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
|
if (mtx->owner < 0) {
|
|
mtx->owner = get_core_num();
|
|
block = false;
|
|
}
|
|
spin_unlock(mtx->core.spin_lock, save);
|
|
if (block) {
|
|
__wfe();
|
|
}
|
|
} while (block);
|
|
}
|
|
|
|
bool __time_critical_func(mutex_try_enter)(mutex_t *mtx, uint32_t *owner_out) {
|
|
bool entered;
|
|
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
|
if (mtx->owner < 0) {
|
|
mtx->owner = get_core_num();
|
|
entered = true;
|
|
} else {
|
|
if (owner_out) *owner_out = mtx->owner;
|
|
entered = false;
|
|
}
|
|
spin_unlock(mtx->core.spin_lock, save);
|
|
return entered;
|
|
}
|
|
|
|
bool __time_critical_func(mutex_enter_timeout_ms)(mutex_t *mtx, uint32_t timeout_ms) {
|
|
return mutex_enter_block_until(mtx, make_timeout_time_ms(timeout_ms));
|
|
}
|
|
|
|
bool __time_critical_func(mutex_enter_block_until)(mutex_t *mtx, absolute_time_t until) {
|
|
assert(mtx->core.spin_lock);
|
|
bool block = true;
|
|
do {
|
|
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
|
if (mtx->owner < 0) {
|
|
mtx->owner = get_core_num();
|
|
block = false;
|
|
}
|
|
spin_unlock(mtx->core.spin_lock, save);
|
|
if (block) {
|
|
if (best_effort_wfe_or_timeout(until)) {
|
|
return false;
|
|
}
|
|
}
|
|
} while (block);
|
|
return true;
|
|
}
|
|
|
|
void __time_critical_func(mutex_exit)(mutex_t *mtx) {
|
|
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
|
assert(mtx->owner >= 0);
|
|
mtx->owner = -1;
|
|
__sev();
|
|
spin_unlock(mtx->core.spin_lock, save);
|
|
}
|