1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /******************************************************************************* |
3 | * |
4 | * Module Name: utmutex - local mutex support |
5 | * |
6 | ******************************************************************************/ |
7 | |
8 | #include <acpi/acpi.h> |
9 | #include "accommon.h" |
10 | |
11 | #define _COMPONENT ACPI_UTILITIES |
12 | ACPI_MODULE_NAME("utmutex" ) |
13 | |
14 | /* Local prototypes */ |
15 | static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id); |
16 | |
17 | static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id); |
18 | |
19 | /******************************************************************************* |
20 | * |
21 | * FUNCTION: acpi_ut_mutex_initialize |
22 | * |
23 | * PARAMETERS: None. |
24 | * |
25 | * RETURN: Status |
26 | * |
27 | * DESCRIPTION: Create the system mutex objects. This includes mutexes, |
28 | * spin locks, and reader/writer locks. |
29 | * |
30 | ******************************************************************************/ |
31 | |
32 | acpi_status acpi_ut_mutex_initialize(void) |
33 | { |
34 | u32 i; |
35 | acpi_status status; |
36 | |
37 | ACPI_FUNCTION_TRACE(ut_mutex_initialize); |
38 | |
39 | /* Create each of the predefined mutex objects */ |
40 | |
41 | for (i = 0; i < ACPI_NUM_MUTEX; i++) { |
42 | status = acpi_ut_create_mutex(mutex_id: i); |
43 | if (ACPI_FAILURE(status)) { |
44 | return_ACPI_STATUS(status); |
45 | } |
46 | } |
47 | |
48 | /* Create the spinlocks for use at interrupt level or for speed */ |
49 | |
50 | status = acpi_os_create_lock (&acpi_gbl_gpe_lock); |
51 | if (ACPI_FAILURE (status)) { |
52 | return_ACPI_STATUS (status); |
53 | } |
54 | |
55 | status = acpi_os_create_raw_lock(&acpi_gbl_hardware_lock); |
56 | if (ACPI_FAILURE (status)) { |
57 | return_ACPI_STATUS (status); |
58 | } |
59 | |
60 | status = acpi_os_create_lock(&acpi_gbl_reference_count_lock); |
61 | if (ACPI_FAILURE(status)) { |
62 | return_ACPI_STATUS(status); |
63 | } |
64 | |
65 | /* Mutex for _OSI support */ |
66 | |
67 | status = acpi_os_create_mutex(&acpi_gbl_osi_mutex); |
68 | if (ACPI_FAILURE(status)) { |
69 | return_ACPI_STATUS(status); |
70 | } |
71 | |
72 | /* Create the reader/writer lock for namespace access */ |
73 | |
74 | status = acpi_ut_create_rw_lock(lock: &acpi_gbl_namespace_rw_lock); |
75 | if (ACPI_FAILURE(status)) { |
76 | return_ACPI_STATUS(status); |
77 | } |
78 | |
79 | return_ACPI_STATUS(status); |
80 | } |
81 | |
82 | /******************************************************************************* |
83 | * |
84 | * FUNCTION: acpi_ut_mutex_terminate |
85 | * |
86 | * PARAMETERS: None. |
87 | * |
88 | * RETURN: None. |
89 | * |
90 | * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, |
91 | * spin locks, and reader/writer locks. |
92 | * |
93 | ******************************************************************************/ |
94 | |
95 | void acpi_ut_mutex_terminate(void) |
96 | { |
97 | u32 i; |
98 | |
99 | ACPI_FUNCTION_TRACE(ut_mutex_terminate); |
100 | |
101 | /* Delete each predefined mutex object */ |
102 | |
103 | for (i = 0; i < ACPI_NUM_MUTEX; i++) { |
104 | acpi_ut_delete_mutex(mutex_id: i); |
105 | } |
106 | |
107 | acpi_os_delete_mutex(acpi_gbl_osi_mutex); |
108 | |
109 | /* Delete the spinlocks */ |
110 | |
111 | acpi_os_delete_lock(handle: acpi_gbl_gpe_lock); |
112 | acpi_os_delete_raw_lock(handle: acpi_gbl_hardware_lock); |
113 | acpi_os_delete_lock(handle: acpi_gbl_reference_count_lock); |
114 | |
115 | /* Delete the reader/writer lock */ |
116 | |
117 | acpi_ut_delete_rw_lock(lock: &acpi_gbl_namespace_rw_lock); |
118 | return_VOID; |
119 | } |
120 | |
121 | /******************************************************************************* |
122 | * |
123 | * FUNCTION: acpi_ut_create_mutex |
124 | * |
125 | * PARAMETERS: mutex_ID - ID of the mutex to be created |
126 | * |
127 | * RETURN: Status |
128 | * |
129 | * DESCRIPTION: Create a mutex object. |
130 | * |
131 | ******************************************************************************/ |
132 | |
133 | static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id) |
134 | { |
135 | acpi_status status = AE_OK; |
136 | |
137 | ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id); |
138 | |
139 | if (!acpi_gbl_mutex_info[mutex_id].mutex) { |
140 | status = |
141 | acpi_os_create_mutex(&acpi_gbl_mutex_info[mutex_id].mutex); |
142 | acpi_gbl_mutex_info[mutex_id].thread_id = |
143 | ACPI_MUTEX_NOT_ACQUIRED; |
144 | acpi_gbl_mutex_info[mutex_id].use_count = 0; |
145 | } |
146 | |
147 | return_ACPI_STATUS(status); |
148 | } |
149 | |
150 | /******************************************************************************* |
151 | * |
152 | * FUNCTION: acpi_ut_delete_mutex |
153 | * |
154 | * PARAMETERS: mutex_ID - ID of the mutex to be deleted |
155 | * |
156 | * RETURN: Status |
157 | * |
158 | * DESCRIPTION: Delete a mutex object. |
159 | * |
160 | ******************************************************************************/ |
161 | |
162 | static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id) |
163 | { |
164 | |
165 | ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id); |
166 | |
167 | acpi_os_delete_mutex(acpi_gbl_mutex_info[mutex_id].mutex); |
168 | |
169 | acpi_gbl_mutex_info[mutex_id].mutex = NULL; |
170 | acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; |
171 | |
172 | return_VOID; |
173 | } |
174 | |
175 | /******************************************************************************* |
176 | * |
177 | * FUNCTION: acpi_ut_acquire_mutex |
178 | * |
179 | * PARAMETERS: mutex_ID - ID of the mutex to be acquired |
180 | * |
181 | * RETURN: Status |
182 | * |
183 | * DESCRIPTION: Acquire a mutex object. |
184 | * |
185 | ******************************************************************************/ |
186 | |
187 | acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) |
188 | { |
189 | acpi_status status; |
190 | acpi_thread_id this_thread_id; |
191 | |
192 | ACPI_FUNCTION_NAME(ut_acquire_mutex); |
193 | |
194 | if (mutex_id > ACPI_MAX_MUTEX) { |
195 | return (AE_BAD_PARAMETER); |
196 | } |
197 | |
198 | this_thread_id = acpi_os_get_thread_id(); |
199 | |
200 | #ifdef ACPI_MUTEX_DEBUG |
201 | { |
202 | u32 i; |
203 | /* |
204 | * Mutex debug code, for internal debugging only. |
205 | * |
206 | * Deadlock prevention. Check if this thread owns any mutexes of value |
207 | * greater than or equal to this one. If so, the thread has violated |
208 | * the mutex ordering rule. This indicates a coding error somewhere in |
209 | * the ACPI subsystem code. |
210 | */ |
211 | for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) { |
212 | if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { |
213 | if (i == mutex_id) { |
214 | ACPI_ERROR((AE_INFO, |
215 | "Mutex [%s] already acquired by this thread [%u]" , |
216 | acpi_ut_get_mutex_name |
217 | (mutex_id), |
218 | (u32)this_thread_id)); |
219 | |
220 | return (AE_ALREADY_ACQUIRED); |
221 | } |
222 | |
223 | ACPI_ERROR((AE_INFO, |
224 | "Invalid acquire order: Thread %u owns [%s], wants [%s]" , |
225 | (u32)this_thread_id, |
226 | acpi_ut_get_mutex_name(i), |
227 | acpi_ut_get_mutex_name(mutex_id))); |
228 | |
229 | return (AE_ACQUIRE_DEADLOCK); |
230 | } |
231 | } |
232 | } |
233 | #endif |
234 | |
235 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, |
236 | "Thread %u attempting to acquire Mutex [%s]\n" , |
237 | (u32)this_thread_id, |
238 | acpi_ut_get_mutex_name(mutex_id))); |
239 | |
240 | status = |
241 | acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex, |
242 | ACPI_WAIT_FOREVER); |
243 | if (ACPI_SUCCESS(status)) { |
244 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, |
245 | "Thread %u acquired Mutex [%s]\n" , |
246 | (u32)this_thread_id, |
247 | acpi_ut_get_mutex_name(mutex_id))); |
248 | |
249 | acpi_gbl_mutex_info[mutex_id].use_count++; |
250 | acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id; |
251 | } else { |
252 | ACPI_EXCEPTION((AE_INFO, status, |
253 | "Thread %u could not acquire Mutex [%s] (0x%X)" , |
254 | (u32)this_thread_id, |
255 | acpi_ut_get_mutex_name(mutex_id), mutex_id)); |
256 | } |
257 | |
258 | return (status); |
259 | } |
260 | |
261 | /******************************************************************************* |
262 | * |
263 | * FUNCTION: acpi_ut_release_mutex |
264 | * |
265 | * PARAMETERS: mutex_ID - ID of the mutex to be released |
266 | * |
267 | * RETURN: Status |
268 | * |
269 | * DESCRIPTION: Release a mutex object. |
270 | * |
271 | ******************************************************************************/ |
272 | |
273 | acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) |
274 | { |
275 | ACPI_FUNCTION_NAME(ut_release_mutex); |
276 | |
277 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n" , |
278 | (u32)acpi_os_get_thread_id(), |
279 | acpi_ut_get_mutex_name(mutex_id))); |
280 | |
281 | if (mutex_id > ACPI_MAX_MUTEX) { |
282 | return (AE_BAD_PARAMETER); |
283 | } |
284 | |
285 | /* |
286 | * Mutex must be acquired in order to release it! |
287 | */ |
288 | if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) { |
289 | ACPI_ERROR((AE_INFO, |
290 | "Mutex [%s] (0x%X) is not acquired, cannot release" , |
291 | acpi_ut_get_mutex_name(mutex_id), mutex_id)); |
292 | |
293 | return (AE_NOT_ACQUIRED); |
294 | } |
295 | #ifdef ACPI_MUTEX_DEBUG |
296 | { |
297 | u32 i; |
298 | /* |
299 | * Mutex debug code, for internal debugging only. |
300 | * |
301 | * Deadlock prevention. Check if this thread owns any mutexes of value |
302 | * greater than this one. If so, the thread has violated the mutex |
303 | * ordering rule. This indicates a coding error somewhere in |
304 | * the ACPI subsystem code. |
305 | */ |
306 | for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) { |
307 | if (acpi_gbl_mutex_info[i].thread_id == |
308 | acpi_os_get_thread_id()) { |
309 | if (i == mutex_id) { |
310 | continue; |
311 | } |
312 | |
313 | ACPI_ERROR((AE_INFO, |
314 | "Invalid release order: owns [%s], releasing [%s]" , |
315 | acpi_ut_get_mutex_name(i), |
316 | acpi_ut_get_mutex_name(mutex_id))); |
317 | |
318 | return (AE_RELEASE_DEADLOCK); |
319 | } |
320 | } |
321 | } |
322 | #endif |
323 | |
324 | /* Mark unlocked FIRST */ |
325 | |
326 | acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; |
327 | |
328 | acpi_os_release_mutex(acpi_gbl_mutex_info[mutex_id].mutex); |
329 | return (AE_OK); |
330 | } |
331 | |