blob: 3ea81c752352847fd0981df2fbc7f776f2d708b7 [file] [log] [blame]
Austin Schuh208337d2022-01-01 14:29:11 -08001/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include "pico/mutex.h"
8#include "pico/time.h"
9
10void mutex_init(mutex_t *mtx) {
11 lock_init(&mtx->core, next_striped_spin_lock_num());
12 mtx->owner = LOCK_INVALID_OWNER_ID;
13#if PICO_MUTEX_ENABLE_SDK120_COMPATIBILITY
14 mtx->recursive = false;
15#endif
16 __mem_fence_release();
17}
18
19void recursive_mutex_init(recursive_mutex_t *mtx) {
20 lock_init(&mtx->core, next_striped_spin_lock_num());
21 mtx->owner = LOCK_INVALID_OWNER_ID;
22 mtx->enter_count = 0;
23#if PICO_MUTEX_ENABLE_SDK120_COMPATIBILITY
24 mtx->recursive = true;
25#endif
26 __mem_fence_release();
27}
28
29void __time_critical_func(mutex_enter_blocking)(mutex_t *mtx) {
30#if PICO_MUTEX_ENABLE_SDK120_COMPATIBILITY
31 if (mtx->recursive) {
32 recursive_mutex_enter_blocking(mtx);
33 return;
34 }
35#endif
36 lock_owner_id_t caller = lock_get_caller_owner_id();
37 do {
38 uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
39 if (!lock_is_owner_id_valid(mtx->owner)) {
40 mtx->owner = caller;
41 spin_unlock(mtx->core.spin_lock, save);
42 break;
43 }
44 lock_internal_spin_unlock_with_wait(&mtx->core, save);
45 } while (true);
46}
47
48void __time_critical_func(recursive_mutex_enter_blocking)(recursive_mutex_t *mtx) {
49 lock_owner_id_t caller = lock_get_caller_owner_id();
50 do {
51 uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
52 if (mtx->owner == caller || !lock_is_owner_id_valid(mtx->owner)) {
53 mtx->owner = caller;
54 uint __unused total = ++mtx->enter_count;
55 spin_unlock(mtx->core.spin_lock, save);
56 assert(total); // check for overflow
57 return;
58 } else {
59 lock_internal_spin_unlock_with_wait(&mtx->core, save);
60 }
61 } while (true);
62}
63
64bool __time_critical_func(mutex_try_enter)(mutex_t *mtx, uint32_t *owner_out) {
65#if PICO_MUTEX_ENABLE_SDK120_COMPATIBILITY
66 if (mtx->recursive) {
67 return recursive_mutex_try_enter(mtx, owner_out);
68 }
69#endif
70 bool entered;
71 uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
72 if (!lock_is_owner_id_valid(mtx->owner)) {
73 mtx->owner = lock_get_caller_owner_id();
74 entered = true;
75 } else {
76 if (owner_out) *owner_out = (uint32_t) mtx->owner;
77 entered = false;
78 }
79 spin_unlock(mtx->core.spin_lock, save);
80 return entered;
81}
82
83bool __time_critical_func(recursive_mutex_try_enter)(recursive_mutex_t *mtx, uint32_t *owner_out) {
84 bool entered;
85 lock_owner_id_t caller = lock_get_caller_owner_id();
86 uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
87 if (!lock_is_owner_id_valid(mtx->owner) || mtx->owner == caller) {
88 mtx->owner = caller;
89 uint __unused total = ++mtx->enter_count;
90 assert(total); // check for overflow
91 entered = true;
92 } else {
93 if (owner_out) *owner_out = (uint32_t) mtx->owner;
94 entered = false;
95 }
96 spin_unlock(mtx->core.spin_lock, save);
97 return entered;
98}
99
100bool __time_critical_func(mutex_enter_timeout_ms)(mutex_t *mtx, uint32_t timeout_ms) {
101 return mutex_enter_block_until(mtx, make_timeout_time_ms(timeout_ms));
102}
103
104bool __time_critical_func(recursive_mutex_enter_timeout_ms)(recursive_mutex_t *mtx, uint32_t timeout_ms) {
105 return recursive_mutex_enter_block_until(mtx, make_timeout_time_ms(timeout_ms));
106}
107
108bool __time_critical_func(mutex_enter_timeout_us)(mutex_t *mtx, uint32_t timeout_us) {
109 return mutex_enter_block_until(mtx, make_timeout_time_us(timeout_us));
110}
111
112bool __time_critical_func(recursive_mutex_enter_timeout_us)(recursive_mutex_t *mtx, uint32_t timeout_us) {
113 return recursive_mutex_enter_block_until(mtx, make_timeout_time_us(timeout_us));
114}
115
116bool __time_critical_func(mutex_enter_block_until)(mutex_t *mtx, absolute_time_t until) {
117#if PICO_MUTEX_ENABLE_SDK120_COMPATIBILITY
118 if (mtx->recursive) {
119 return recursive_mutex_enter_block_until(mtx, until);
120 }
121#endif
122 assert(mtx->core.spin_lock);
123 lock_owner_id_t caller = lock_get_caller_owner_id();
124 do {
125 uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
126 if (!lock_is_owner_id_valid(mtx->owner)) {
127 mtx->owner = caller;
128 spin_unlock(mtx->core.spin_lock, save);
129 return true;
130 } else {
131 if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&mtx->core, save, until)) {
132 // timed out
133 return false;
134 }
135 // not timed out; spin lock already unlocked, so loop again
136 }
137 } while (true);
138}
139
140bool __time_critical_func(recursive_mutex_enter_block_until)(recursive_mutex_t *mtx, absolute_time_t until) {
141 assert(mtx->core.spin_lock);
142 lock_owner_id_t caller = lock_get_caller_owner_id();
143 do {
144 uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
145 if (!lock_is_owner_id_valid(mtx->owner) || mtx->owner == caller) {
146 mtx->owner = caller;
147 uint __unused total = ++mtx->enter_count;
148 spin_unlock(mtx->core.spin_lock, save);
149 assert(total); // check for overflow
150 return true;
151 } else {
152 if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&mtx->core, save, until)) {
153 // timed out
154 return false;
155 }
156 // not timed out; spin lock already unlocked, so loop again
157 }
158 } while (true);
159}
160
161void __time_critical_func(mutex_exit)(mutex_t *mtx) {
162#if PICO_MUTEX_ENABLE_SDK120_COMPATIBILITY
163 if (mtx->recursive) {
164 recursive_mutex_exit(mtx);
165 return;
166 }
167#endif
168 uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
169 assert(lock_is_owner_id_valid(mtx->owner));
170 mtx->owner = LOCK_INVALID_OWNER_ID;
171 lock_internal_spin_unlock_with_notify(&mtx->core, save);
172}
173
174void __time_critical_func(recursive_mutex_exit)(recursive_mutex_t *mtx) {
175 uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
176 assert(lock_is_owner_id_valid(mtx->owner));
177 assert(mtx->enter_count);
178 if (!--mtx->enter_count) {
179 mtx->owner = LOCK_INVALID_OWNER_ID;
180 lock_internal_spin_unlock_with_notify(&mtx->core, save);
181 } else {
182 spin_unlock(mtx->core.spin_lock, save);
183 }
184}