1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /*******************************************************************************
4 * Module Name: utmutex - local mutex support
6 ******************************************************************************/
11 #define _COMPONENT ACPI_UTILITIES
12 ACPI_MODULE_NAME("utmutex")
14 /* Local prototypes */
15 static acpi_status
acpi_ut_create_mutex(acpi_mutex_handle mutex_id
);
17 static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id
);
19 /*******************************************************************************
21 * FUNCTION: acpi_ut_mutex_initialize
27 * DESCRIPTION: Create the system mutex objects. This includes mutexes,
28 * spin locks, and reader/writer locks.
30 ******************************************************************************/
32 acpi_status
acpi_ut_mutex_initialize(void)
37 ACPI_FUNCTION_TRACE(ut_mutex_initialize
);
39 /* Create each of the predefined mutex objects */
41 for (i
= 0; i
< ACPI_NUM_MUTEX
; i
++) {
42 status
= acpi_ut_create_mutex(i
);
43 if (ACPI_FAILURE(status
)) {
44 return_ACPI_STATUS(status
);
48 /* Create the spinlocks for use at interrupt level or for speed */
50 status
= acpi_os_create_lock (&acpi_gbl_gpe_lock
);
51 if (ACPI_FAILURE (status
)) {
52 return_ACPI_STATUS (status
);
55 status
= acpi_os_create_lock (&acpi_gbl_hardware_lock
);
56 if (ACPI_FAILURE (status
)) {
57 return_ACPI_STATUS (status
);
60 status
= acpi_os_create_lock(&acpi_gbl_reference_count_lock
);
61 if (ACPI_FAILURE(status
)) {
62 return_ACPI_STATUS(status
);
65 /* Mutex for _OSI support */
67 status
= acpi_os_create_mutex(&acpi_gbl_osi_mutex
);
68 if (ACPI_FAILURE(status
)) {
69 return_ACPI_STATUS(status
);
72 /* Create the reader/writer lock for namespace access */
74 status
= acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock
);
75 if (ACPI_FAILURE(status
)) {
76 return_ACPI_STATUS(status
);
79 return_ACPI_STATUS(status
);
82 /*******************************************************************************
84 * FUNCTION: acpi_ut_mutex_terminate
90 * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes,
91 * spin locks, and reader/writer locks.
93 ******************************************************************************/
95 void acpi_ut_mutex_terminate(void)
99 ACPI_FUNCTION_TRACE(ut_mutex_terminate
);
101 /* Delete each predefined mutex object */
103 for (i
= 0; i
< ACPI_NUM_MUTEX
; i
++) {
104 acpi_ut_delete_mutex(i
);
107 acpi_os_delete_mutex(acpi_gbl_osi_mutex
);
109 /* Delete the spinlocks */
111 acpi_os_delete_lock(acpi_gbl_gpe_lock
);
112 acpi_os_delete_lock(acpi_gbl_hardware_lock
);
113 acpi_os_delete_lock(acpi_gbl_reference_count_lock
);
115 /* Delete the reader/writer lock */
117 acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock
);
121 /*******************************************************************************
123 * FUNCTION: acpi_ut_create_mutex
125 * PARAMETERS: mutex_ID - ID of the mutex to be created
129 * DESCRIPTION: Create a mutex object.
131 ******************************************************************************/
133 static acpi_status
acpi_ut_create_mutex(acpi_mutex_handle mutex_id
)
135 acpi_status status
= AE_OK
;
137 ACPI_FUNCTION_TRACE_U32(ut_create_mutex
, mutex_id
);
139 if (!acpi_gbl_mutex_info
[mutex_id
].mutex
) {
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;
147 return_ACPI_STATUS(status
);
150 /*******************************************************************************
152 * FUNCTION: acpi_ut_delete_mutex
154 * PARAMETERS: mutex_ID - ID of the mutex to be deleted
158 * DESCRIPTION: Delete a mutex object.
160 ******************************************************************************/
162 static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id
)
165 ACPI_FUNCTION_TRACE_U32(ut_delete_mutex
, mutex_id
);
167 acpi_os_delete_mutex(acpi_gbl_mutex_info
[mutex_id
].mutex
);
169 acpi_gbl_mutex_info
[mutex_id
].mutex
= NULL
;
170 acpi_gbl_mutex_info
[mutex_id
].thread_id
= ACPI_MUTEX_NOT_ACQUIRED
;
175 /*******************************************************************************
177 * FUNCTION: acpi_ut_acquire_mutex
179 * PARAMETERS: mutex_ID - ID of the mutex to be acquired
183 * DESCRIPTION: Acquire a mutex object.
185 ******************************************************************************/
187 acpi_status
acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id
)
190 acpi_thread_id this_thread_id
;
192 ACPI_FUNCTION_NAME(ut_acquire_mutex
);
194 if (mutex_id
> ACPI_MAX_MUTEX
) {
195 return (AE_BAD_PARAMETER
);
198 this_thread_id
= acpi_os_get_thread_id();
200 #ifdef ACPI_MUTEX_DEBUG
204 * Mutex debug code, for internal debugging only.
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.
211 for (i
= mutex_id
; i
< ACPI_NUM_MUTEX
; i
++) {
212 if (acpi_gbl_mutex_info
[i
].thread_id
== this_thread_id
) {
215 "Mutex [%s] already acquired by this thread [%u]",
216 acpi_ut_get_mutex_name
218 (u32
)this_thread_id
));
220 return (AE_ALREADY_ACQUIRED
);
224 "Invalid acquire order: Thread %u owns [%s], wants [%s]",
226 acpi_ut_get_mutex_name(i
),
227 acpi_ut_get_mutex_name(mutex_id
)));
229 return (AE_ACQUIRE_DEADLOCK
);
235 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX
,
236 "Thread %u attempting to acquire Mutex [%s]\n",
238 acpi_ut_get_mutex_name(mutex_id
)));
241 acpi_os_acquire_mutex(acpi_gbl_mutex_info
[mutex_id
].mutex
,
243 if (ACPI_SUCCESS(status
)) {
244 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX
,
245 "Thread %u acquired Mutex [%s]\n",
247 acpi_ut_get_mutex_name(mutex_id
)));
249 acpi_gbl_mutex_info
[mutex_id
].use_count
++;
250 acpi_gbl_mutex_info
[mutex_id
].thread_id
= this_thread_id
;
252 ACPI_EXCEPTION((AE_INFO
, status
,
253 "Thread %u could not acquire Mutex [%s] (0x%X)",
255 acpi_ut_get_mutex_name(mutex_id
), mutex_id
));
261 /*******************************************************************************
263 * FUNCTION: acpi_ut_release_mutex
265 * PARAMETERS: mutex_ID - ID of the mutex to be released
269 * DESCRIPTION: Release a mutex object.
271 ******************************************************************************/
273 acpi_status
acpi_ut_release_mutex(acpi_mutex_handle mutex_id
)
275 ACPI_FUNCTION_NAME(ut_release_mutex
);
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
)));
281 if (mutex_id
> ACPI_MAX_MUTEX
) {
282 return (AE_BAD_PARAMETER
);
286 * Mutex must be acquired in order to release it!
288 if (acpi_gbl_mutex_info
[mutex_id
].thread_id
== ACPI_MUTEX_NOT_ACQUIRED
) {
290 "Mutex [%s] (0x%X) is not acquired, cannot release",
291 acpi_ut_get_mutex_name(mutex_id
), mutex_id
));
293 return (AE_NOT_ACQUIRED
);
295 #ifdef ACPI_MUTEX_DEBUG
299 * Mutex debug code, for internal debugging only.
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.
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()) {
314 "Invalid release order: owns [%s], releasing [%s]",
315 acpi_ut_get_mutex_name(i
),
316 acpi_ut_get_mutex_name(mutex_id
)));
318 return (AE_RELEASE_DEADLOCK
);
324 /* Mark unlocked FIRST */
326 acpi_gbl_mutex_info
[mutex_id
].thread_id
= ACPI_MUTEX_NOT_ACQUIRED
;
328 acpi_os_release_mutex(acpi_gbl_mutex_info
[mutex_id
].mutex
);