1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
36
37
38
39
40
41
42
43
51
52
61
62
80
81
96
97
98
99
103
104
105
112
113
114
115
116
126
127
128
129
130
131
140
141
142
143
144
147
148
151
152
155
156
159
160
183
184
204
205
206
207
212
213
214
215
216
217
218
/* ... */
#include "pico/mutex.h"
#include "pico/time.h"
#include "pico/runtime_init.h"
#if !PICO_RUNTIME_NO_INIT_MUTEX
void __weak runtime_init_mutex(void) {
static_assert(!(sizeof(mutex_t)&3), "");
static_assert(!(sizeof(recursive_mutex_t)&3), "");
static_assert(!offsetof(mutex_t, core), "");
static_assert(!offsetof(recursive_mutex_t, core), "");
extern lock_core_t __mutex_array_start;
extern lock_core_t __mutex_array_end;
for (lock_core_t *l = &__mutex_array_start; l < &__mutex_array_end; ) {
if (l->spin_lock) {
assert(1 == (uintptr_t)l->spin_lock);
recursive_mutex_t *rm = (recursive_mutex_t *)l;
recursive_mutex_init(rm);
l = &rm[1].core;
}if (l->spin_lock) { ... } else {
mutex_t *m = (mutex_t *)l;
mutex_init(m);
l = &m[1].core;
}else { ... }
}for (lock_core_t *l = &__mutex_array_start; l < &__mutex_array_end;) { ... }
}{ ... }
/* ... */#endif
#if defined(PICO_RUNTIME_INIT_MUTEX) && !PICO_RUNTIME_SKIP_INIT_MUTEX
PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_mutex, PICO_RUNTIME_INIT_MUTEX);
#endif
void mutex_init(mutex_t *mtx) {
lock_init(&mtx->core, next_striped_spin_lock_num());
mtx->owner = LOCK_INVALID_OWNER_ID;
#if PICO_MUTEX_ENABLE_SDK120_COMPATIBILITY
mtx->recursive = false;
#endif
__mem_fence_release();
}{ ... }
void recursive_mutex_init(recursive_mutex_t *mtx) {
lock_init(&mtx->core, next_striped_spin_lock_num());
mtx->owner = LOCK_INVALID_OWNER_ID;
mtx->enter_count = 0;
#if PICO_MUTEX_ENABLE_SDK120_COMPATIBILITY
mtx->recursive = true;
#endif
__mem_fence_release();
}{ ... }
void __time_critical_func(mutex_enter_blocking)(mutex_t *mtx) {
#if PICO_MUTEX_ENABLE_SDK120_COMPATIBILITY
if (mtx->recursive) {
recursive_mutex_enter_blocking(mtx);
return;
}if (mtx->recursive) { ... }
/* ... */#endif
lock_owner_id_t caller = lock_get_caller_owner_id();
do {
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
if (!lock_is_owner_id_valid(mtx->owner)) {
mtx->owner = caller;
spin_unlock(mtx->core.spin_lock, save);
break;
}if (!lock_is_owner_id_valid(mtx->owner)) { ... }
lock_internal_spin_unlock_with_wait(&mtx->core, save);
...} while (true);
...}
void __time_critical_func(recursive_mutex_enter_blocking)(recursive_mutex_t *mtx) {
lock_owner_id_t caller = lock_get_caller_owner_id();
do {
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
if (mtx->owner == caller || !lock_is_owner_id_valid(mtx->owner)) {
mtx->owner = caller;
uint __unused total = ++mtx->enter_count;
spin_unlock(mtx->core.spin_lock, save);
assert(total);
return;
}if (mtx->owner == caller || !lock_is_owner_id_valid(mtx->owner)) { ... } else {
lock_internal_spin_unlock_with_wait(&mtx->core, save);
}else { ... }
...} while (true);
...}
bool __time_critical_func(mutex_try_enter)(mutex_t *mtx, uint32_t *owner_out) {
#if PICO_MUTEX_ENABLE_SDK120_COMPATIBILITY
if (mtx->recursive) {
return recursive_mutex_try_enter(mtx, owner_out);
}if (mtx->recursive) { ... }
/* ... */#endif
bool entered;
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
if (!lock_is_owner_id_valid(mtx->owner)) {
mtx->owner = lock_get_caller_owner_id();
entered = true;
}if (!lock_is_owner_id_valid(mtx->owner)) { ... } else {
if (owner_out) *owner_out = (uint32_t) mtx->owner;
entered = false;
}else { ... }
spin_unlock(mtx->core.spin_lock, save);
return entered;
...}
bool __time_critical_func(mutex_try_enter_block_until)(mutex_t *mtx, absolute_time_t until) {
static_assert(sizeof(lock_owner_id_t) <= 4, "");
uint32_t owner;
if (!mutex_try_enter(mtx, &owner)) {
if ((lock_owner_id_t)owner == lock_get_caller_owner_id()) return false;
return mutex_enter_block_until(mtx, until);
}if (!mutex_try_enter(mtx, &owner)) { ... }
return true;
...}
bool __time_critical_func(recursive_mutex_try_enter)(recursive_mutex_t *mtx, uint32_t *owner_out) {
bool entered;
lock_owner_id_t caller = lock_get_caller_owner_id();
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
if (!lock_is_owner_id_valid(mtx->owner) || mtx->owner == caller) {
mtx->owner = caller;
uint __unused total = ++mtx->enter_count;
assert(total);
entered = true;
}if (!lock_is_owner_id_valid(mtx->owner) || mtx->owner == caller) { ... } else {
if (owner_out) *owner_out = (uint32_t) mtx->owner;
entered = false;
}else { ... }
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(recursive_mutex_enter_timeout_ms)(recursive_mutex_t *mtx, uint32_t timeout_ms) {
return recursive_mutex_enter_block_until(mtx, make_timeout_time_ms(timeout_ms));
...}
bool __time_critical_func(mutex_enter_timeout_us)(mutex_t *mtx, uint32_t timeout_us) {
return mutex_enter_block_until(mtx, make_timeout_time_us(timeout_us));
...}
bool __time_critical_func(recursive_mutex_enter_timeout_us)(recursive_mutex_t *mtx, uint32_t timeout_us) {
return recursive_mutex_enter_block_until(mtx, make_timeout_time_us(timeout_us));
...}
bool __time_critical_func(mutex_enter_block_until)(mutex_t *mtx, absolute_time_t until) {
#if PICO_MUTEX_ENABLE_SDK120_COMPATIBILITY
if (mtx->recursive) {
return recursive_mutex_enter_block_until(mtx, until);
}if (mtx->recursive) { ... }
/* ... */#endif
assert(mtx->core.spin_lock);
lock_owner_id_t caller = lock_get_caller_owner_id();
do {
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
if (!lock_is_owner_id_valid(mtx->owner)) {
mtx->owner = caller;
spin_unlock(mtx->core.spin_lock, save);
return true;
}if (!lock_is_owner_id_valid(mtx->owner)) { ... } else {
if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&mtx->core, save, until)) {
return false;
}if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&mtx->core, save, until)) { ... }
}else { ... }
...} while (true);
...}
bool __time_critical_func(recursive_mutex_enter_block_until)(recursive_mutex_t *mtx, absolute_time_t until) {
assert(mtx->core.spin_lock);
lock_owner_id_t caller = lock_get_caller_owner_id();
do {
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
if (!lock_is_owner_id_valid(mtx->owner) || mtx->owner == caller) {
mtx->owner = caller;
uint __unused total = ++mtx->enter_count;
spin_unlock(mtx->core.spin_lock, save);
assert(total);
return true;
}if (!lock_is_owner_id_valid(mtx->owner) || mtx->owner == caller) { ... } else {
if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&mtx->core, save, until)) {
return false;
}if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&mtx->core, save, until)) { ... }
}else { ... }
...} while (true);
...}
void __time_critical_func(mutex_exit)(mutex_t *mtx) {
#if PICO_MUTEX_ENABLE_SDK120_COMPATIBILITY
if (mtx->recursive) {
recursive_mutex_exit(mtx);
return;
}if (mtx->recursive) { ... }
/* ... */#endif
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
assert(lock_is_owner_id_valid(mtx->owner));
mtx->owner = LOCK_INVALID_OWNER_ID;
lock_internal_spin_unlock_with_notify(&mtx->core, save);
...}
void __time_critical_func(recursive_mutex_exit)(recursive_mutex_t *mtx) {
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
assert(lock_is_owner_id_valid(mtx->owner));
assert(mtx->enter_count);
if (!--mtx->enter_count) {
mtx->owner = LOCK_INVALID_OWNER_ID;
lock_internal_spin_unlock_with_notify(&mtx->core, save);
}if (!--mtx->enter_count) { ... } else {
spin_unlock(mtx->core.spin_lock, save);
}else { ... }
...}