utmutex.c (8580B)
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(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(&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(i); 105 } 106 107 acpi_os_delete_mutex(acpi_gbl_osi_mutex); 108 109 /* Delete the spinlocks */ 110 111 acpi_os_delete_lock(acpi_gbl_gpe_lock); 112 acpi_os_delete_raw_lock(acpi_gbl_hardware_lock); 113 acpi_os_delete_lock(acpi_gbl_reference_count_lock); 114 115 /* Delete the reader/writer lock */ 116 117 acpi_ut_delete_rw_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}