1 /******************************************************************************* 2 * 3 * Module Name: utmutex - local mutex support 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2022, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include "acpi.h" 45 #include "accommon.h" 46 47 #define _COMPONENT ACPI_UTILITIES 48 ACPI_MODULE_NAME ("utmutex") 49 50 /* Local prototypes */ 51 52 static ACPI_STATUS 53 AcpiUtCreateMutex ( 54 ACPI_MUTEX_HANDLE MutexId); 55 56 static void 57 AcpiUtDeleteMutex ( 58 ACPI_MUTEX_HANDLE MutexId); 59 60 61 /******************************************************************************* 62 * 63 * FUNCTION: AcpiUtMutexInitialize 64 * 65 * PARAMETERS: None. 66 * 67 * RETURN: Status 68 * 69 * DESCRIPTION: Create the system mutex objects. This includes mutexes, 70 * spin locks, and reader/writer locks. 71 * 72 ******************************************************************************/ 73 74 ACPI_STATUS 75 AcpiUtMutexInitialize ( 76 void) 77 { 78 UINT32 i; 79 ACPI_STATUS Status; 80 81 82 ACPI_FUNCTION_TRACE (UtMutexInitialize); 83 84 85 /* Create each of the predefined mutex objects */ 86 87 for (i = 0; i < ACPI_NUM_MUTEX; i++) 88 { 89 Status = AcpiUtCreateMutex (i); 90 if (ACPI_FAILURE (Status)) 91 { 92 return_ACPI_STATUS (Status); 93 } 94 } 95 96 /* Create the spinlocks for use at interrupt level or for speed */ 97 98 Status = AcpiOsCreateLock (&AcpiGbl_GpeLock); 99 if (ACPI_FAILURE (Status)) 100 { 101 return_ACPI_STATUS (Status); 102 } 103 104 Status = AcpiOsCreateLock (&AcpiGbl_HardwareLock); 105 if (ACPI_FAILURE (Status)) 106 { 107 return_ACPI_STATUS (Status); 108 } 109 110 Status = AcpiOsCreateLock (&AcpiGbl_ReferenceCountLock); 111 if (ACPI_FAILURE (Status)) 112 { 113 return_ACPI_STATUS (Status); 114 } 115 116 /* Mutex for _OSI support */ 117 118 Status = AcpiOsCreateMutex (&AcpiGbl_OsiMutex); 119 if (ACPI_FAILURE (Status)) 120 { 121 return_ACPI_STATUS (Status); 122 } 123 124 /* Create the reader/writer lock for namespace access */ 125 126 Status = AcpiUtCreateRwLock (&AcpiGbl_NamespaceRwLock); 127 if (ACPI_FAILURE (Status)) 128 { 129 return_ACPI_STATUS (Status); 130 } 131 132 return_ACPI_STATUS (Status); 133 } 134 135 136 /******************************************************************************* 137 * 138 * FUNCTION: AcpiUtMutexTerminate 139 * 140 * PARAMETERS: None. 141 * 142 * RETURN: None. 143 * 144 * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, 145 * spin locks, and reader/writer locks. 146 * 147 ******************************************************************************/ 148 149 void 150 AcpiUtMutexTerminate ( 151 void) 152 { 153 UINT32 i; 154 155 156 ACPI_FUNCTION_TRACE (UtMutexTerminate); 157 158 159 /* Delete each predefined mutex object */ 160 161 for (i = 0; i < ACPI_NUM_MUTEX; i++) 162 { 163 AcpiUtDeleteMutex (i); 164 } 165 166 AcpiOsDeleteMutex (AcpiGbl_OsiMutex); 167 168 /* Delete the spinlocks */ 169 170 AcpiOsDeleteLock (AcpiGbl_GpeLock); 171 AcpiOsDeleteLock (AcpiGbl_HardwareLock); 172 AcpiOsDeleteLock (AcpiGbl_ReferenceCountLock); 173 174 /* Delete the reader/writer lock */ 175 176 AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock); 177 return_VOID; 178 } 179 180 181 /******************************************************************************* 182 * 183 * FUNCTION: AcpiUtCreateMutex 184 * 185 * PARAMETERS: MutexID - ID of the mutex to be created 186 * 187 * RETURN: Status 188 * 189 * DESCRIPTION: Create a mutex object. 190 * 191 ******************************************************************************/ 192 193 static ACPI_STATUS 194 AcpiUtCreateMutex ( 195 ACPI_MUTEX_HANDLE MutexId) 196 { 197 ACPI_STATUS Status = AE_OK; 198 199 200 ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId); 201 202 203 if (!AcpiGbl_MutexInfo[MutexId].Mutex) 204 { 205 Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex); 206 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 207 AcpiGbl_MutexInfo[MutexId].UseCount = 0; 208 } 209 210 return_ACPI_STATUS (Status); 211 } 212 213 214 /******************************************************************************* 215 * 216 * FUNCTION: AcpiUtDeleteMutex 217 * 218 * PARAMETERS: MutexID - ID of the mutex to be deleted 219 * 220 * RETURN: Status 221 * 222 * DESCRIPTION: Delete a mutex object. 223 * 224 ******************************************************************************/ 225 226 static void 227 AcpiUtDeleteMutex ( 228 ACPI_MUTEX_HANDLE MutexId) 229 { 230 231 ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId); 232 233 234 AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 235 236 AcpiGbl_MutexInfo[MutexId].Mutex = NULL; 237 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 238 239 return_VOID; 240 } 241 242 243 /******************************************************************************* 244 * 245 * FUNCTION: AcpiUtAcquireMutex 246 * 247 * PARAMETERS: MutexID - ID of the mutex to be acquired 248 * 249 * RETURN: Status 250 * 251 * DESCRIPTION: Acquire a mutex object. 252 * 253 ******************************************************************************/ 254 255 ACPI_STATUS 256 AcpiUtAcquireMutex ( 257 ACPI_MUTEX_HANDLE MutexId) 258 { 259 ACPI_STATUS Status; 260 ACPI_THREAD_ID ThisThreadId; 261 262 263 ACPI_FUNCTION_NAME (UtAcquireMutex); 264 265 266 if (MutexId > ACPI_MAX_MUTEX) 267 { 268 return (AE_BAD_PARAMETER); 269 } 270 271 ThisThreadId = AcpiOsGetThreadId (); 272 273 #ifdef ACPI_MUTEX_DEBUG 274 { 275 UINT32 i; 276 /* 277 * Mutex debug code, for internal debugging only. 278 * 279 * Deadlock prevention. Check if this thread owns any mutexes of value 280 * greater than or equal to this one. If so, the thread has violated 281 * the mutex ordering rule. This indicates a coding error somewhere in 282 * the ACPI subsystem code. 283 */ 284 for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 285 { 286 if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) 287 { 288 if (i == MutexId) 289 { 290 ACPI_ERROR ((AE_INFO, 291 "Mutex [%s] already acquired by this thread [%u]", 292 AcpiUtGetMutexName (MutexId), 293 (UINT32) ThisThreadId)); 294 295 return (AE_ALREADY_ACQUIRED); 296 } 297 298 ACPI_ERROR ((AE_INFO, 299 "Invalid acquire order: Thread %u owns [%s], wants [%s]", 300 (UINT32) ThisThreadId, AcpiUtGetMutexName (i), 301 AcpiUtGetMutexName (MutexId))); 302 303 return (AE_ACQUIRE_DEADLOCK); 304 } 305 } 306 } 307 #endif 308 309 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 310 "Thread %u attempting to acquire Mutex [%s]\n", 311 (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 312 313 Status = AcpiOsAcquireMutex ( 314 AcpiGbl_MutexInfo[MutexId].Mutex, ACPI_WAIT_FOREVER); 315 if (ACPI_SUCCESS (Status)) 316 { 317 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 318 "Thread %u acquired Mutex [%s]\n", 319 (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 320 321 AcpiGbl_MutexInfo[MutexId].UseCount++; 322 AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId; 323 } 324 else 325 { 326 ACPI_EXCEPTION ((AE_INFO, Status, 327 "Thread %u could not acquire Mutex [%s] (0x%X)", 328 (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId), MutexId)); 329 } 330 331 return (Status); 332 } 333 334 335 /******************************************************************************* 336 * 337 * FUNCTION: AcpiUtReleaseMutex 338 * 339 * PARAMETERS: MutexID - ID of the mutex to be released 340 * 341 * RETURN: Status 342 * 343 * DESCRIPTION: Release a mutex object. 344 * 345 ******************************************************************************/ 346 347 ACPI_STATUS 348 AcpiUtReleaseMutex ( 349 ACPI_MUTEX_HANDLE MutexId) 350 { 351 ACPI_FUNCTION_NAME (UtReleaseMutex); 352 353 354 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", 355 (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId))); 356 357 if (MutexId > ACPI_MAX_MUTEX) 358 { 359 return (AE_BAD_PARAMETER); 360 } 361 362 /* 363 * Mutex must be acquired in order to release it! 364 */ 365 if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED) 366 { 367 ACPI_ERROR ((AE_INFO, 368 "Mutex [%s] (0x%X) is not acquired, cannot release", 369 AcpiUtGetMutexName (MutexId), MutexId)); 370 371 return (AE_NOT_ACQUIRED); 372 } 373 374 #ifdef ACPI_MUTEX_DEBUG 375 { 376 UINT32 i; 377 /* 378 * Mutex debug code, for internal debugging only. 379 * 380 * Deadlock prevention. Check if this thread owns any mutexes of value 381 * greater than this one. If so, the thread has violated the mutex 382 * ordering rule. This indicates a coding error somewhere in 383 * the ACPI subsystem code. 384 */ 385 for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 386 { 387 if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ()) 388 { 389 if (i == MutexId) 390 { 391 continue; 392 } 393 394 ACPI_ERROR ((AE_INFO, 395 "Invalid release order: owns [%s], releasing [%s]", 396 AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); 397 398 return (AE_RELEASE_DEADLOCK); 399 } 400 } 401 } 402 #endif 403 404 /* Mark unlocked FIRST */ 405 406 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 407 408 AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 409 return (AE_OK); 410 } 411