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
12ACPI_MODULE_NAME("utmutex")
13
14/* Local prototypes */
15static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id);
16
17static 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
32acpi_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
95void 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
133static 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
162static 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
187acpi_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
273acpi_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

source code of linux/drivers/acpi/acpica/utmutex.c