Select one of the symbols to view example projects that use it.
 
Outline
#include "pico/mutex.h"
#include "pico/time.h"
#include "pico/runtime_init.h"
runtime_init_mutex()
__pre_init_runtime_init_mutex
mutex_init(mutex_t *)
recursive_mutex_init(recursive_mutex_t *)
mutex_enter_blocking(mutex_t *)
recursive_mutex_enter_blocking(recursive_mutex_t *)
mutex_try_enter(mutex_t *, uint32_t *)
mutex_try_enter_block_until(mutex_t *, absolute_time_t)
recursive_mutex_try_enter(recursive_mutex_t *, uint32_t *)
mutex_enter_timeout_ms(mutex_t *, uint32_t)
recursive_mutex_enter_timeout_ms(recursive_mutex_t *, uint32_t)
mutex_enter_timeout_us(mutex_t *, uint32_t)
recursive_mutex_enter_timeout_us(recursive_mutex_t *, uint32_t)
mutex_enter_block_until(mutex_t *, absolute_time_t)
recursive_mutex_enter_block_until(recursive_mutex_t *, absolute_time_t)
mutex_exit(mutex_t *)
recursive_mutex_exit(recursive_mutex_t *)
Files
loading...
SourceVuRaspberry Pi Pico SDK and ExamplesPicoSDKsrc/common/pico_sync/mutex.c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause *//* ... */ #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) { // this is an array of either mutex_t or recursive_mutex_t (i.e. not necessarily the same size) // however each starts with a lock_core_t, and the spin_lock is initialized to address 1 for a recursive // spinlock and 0 for a regular one. 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); // indicator for a recursive mutex recursive_mutex_t *rm = (recursive_mutex_t *)l; recursive_mutex_init(rm); l = &rm[1].core; // next }if (l->spin_lock) { ... } else { mutex_t *m = (mutex_t *)l; mutex_init(m); l = &m[1].core; // next }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); // check for overflow 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) { // not using lock_owner_id_t to avoid backwards incompatibility change to mutex_try_enter API 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; // deadlock, so we can never own it 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); // check for overflow 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)) { // timed out return false; }if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&mtx->core, save, until)) { ... } // not timed out; spin lock already unlocked, so loop again }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); // check for overflow 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)) { // timed out return false; }if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&mtx->core, save, until)) { ... } // not timed out; spin lock already unlocked, so loop again }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 { ... } ...}
Details
Show:
from
Types: Columns:
This file uses the notable symbols shown below. Click anywhere in the file to view more details.