1 /******************************************************************************* 2 * 3 * Module Name: utmutex - local mutex support 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 MERCHANTIBILITY 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 #ifdef ACPI_DEBUGGER 133 134 /* Debugger Support */ 135 136 Status = AcpiOsCreateMutex (&AcpiGbl_DbCommandReady); 137 if (ACPI_FAILURE (Status)) 138 { 139 return_ACPI_STATUS (Status); 140 } 141 142 Status = AcpiOsCreateMutex (&AcpiGbl_DbCommandComplete); 143 #endif 144 145 return_ACPI_STATUS (Status); 146 } 147 148 149 /******************************************************************************* 150 * 151 * FUNCTION: AcpiUtMutexTerminate 152 * 153 * PARAMETERS: None. 154 * 155 * RETURN: None. 156 * 157 * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, 158 * spin locks, and reader/writer locks. 159 * 160 ******************************************************************************/ 161 162 void 163 AcpiUtMutexTerminate ( 164 void) 165 { 166 UINT32 i; 167 168 169 ACPI_FUNCTION_TRACE (UtMutexTerminate); 170 171 172 /* Delete each predefined mutex object */ 173 174 for (i = 0; i < ACPI_NUM_MUTEX; i++) 175 { 176 AcpiUtDeleteMutex (i); 177 } 178 179 AcpiOsDeleteMutex (AcpiGbl_OsiMutex); 180 181 /* Delete the spinlocks */ 182 183 AcpiOsDeleteLock (AcpiGbl_GpeLock); 184 AcpiOsDeleteLock (AcpiGbl_HardwareLock); 185 AcpiOsDeleteLock (AcpiGbl_ReferenceCountLock); 186 187 /* Delete the reader/writer lock */ 188 189 AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock); 190 191 #ifdef ACPI_DEBUGGER 192 AcpiOsDeleteMutex (AcpiGbl_DbCommandReady); 193 AcpiOsDeleteMutex (AcpiGbl_DbCommandComplete); 194 #endif 195 196 return_VOID; 197 } 198 199 200 /******************************************************************************* 201 * 202 * FUNCTION: AcpiUtCreateMutex 203 * 204 * PARAMETERS: MutexID - ID of the mutex to be created 205 * 206 * RETURN: Status 207 * 208 * DESCRIPTION: Create a mutex object. 209 * 210 ******************************************************************************/ 211 212 static ACPI_STATUS 213 AcpiUtCreateMutex ( 214 ACPI_MUTEX_HANDLE MutexId) 215 { 216 ACPI_STATUS Status = AE_OK; 217 218 219 ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId); 220 221 222 if (!AcpiGbl_MutexInfo[MutexId].Mutex) 223 { 224 Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex); 225 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 226 AcpiGbl_MutexInfo[MutexId].UseCount = 0; 227 } 228 229 return_ACPI_STATUS (Status); 230 } 231 232 233 /******************************************************************************* 234 * 235 * FUNCTION: AcpiUtDeleteMutex 236 * 237 * PARAMETERS: MutexID - ID of the mutex to be deleted 238 * 239 * RETURN: Status 240 * 241 * DESCRIPTION: Delete a mutex object. 242 * 243 ******************************************************************************/ 244 245 static void 246 AcpiUtDeleteMutex ( 247 ACPI_MUTEX_HANDLE MutexId) 248 { 249 250 ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId); 251 252 253 AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 254 255 AcpiGbl_MutexInfo[MutexId].Mutex = NULL; 256 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 257 258 return_VOID; 259 } 260 261 262 /******************************************************************************* 263 * 264 * FUNCTION: AcpiUtAcquireMutex 265 * 266 * PARAMETERS: MutexID - ID of the mutex to be acquired 267 * 268 * RETURN: Status 269 * 270 * DESCRIPTION: Acquire a mutex object. 271 * 272 ******************************************************************************/ 273 274 ACPI_STATUS 275 AcpiUtAcquireMutex ( 276 ACPI_MUTEX_HANDLE MutexId) 277 { 278 ACPI_STATUS Status; 279 ACPI_THREAD_ID ThisThreadId; 280 281 282 ACPI_FUNCTION_NAME (UtAcquireMutex); 283 284 285 if (MutexId > ACPI_MAX_MUTEX) 286 { 287 return (AE_BAD_PARAMETER); 288 } 289 290 ThisThreadId = AcpiOsGetThreadId (); 291 292 #ifdef ACPI_MUTEX_DEBUG 293 { 294 UINT32 i; 295 /* 296 * Mutex debug code, for internal debugging only. 297 * 298 * Deadlock prevention. Check if this thread owns any mutexes of value 299 * greater than or equal to this one. If so, the thread has violated 300 * the mutex ordering rule. This indicates a coding error somewhere in 301 * the ACPI subsystem code. 302 */ 303 for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 304 { 305 if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) 306 { 307 if (i == MutexId) 308 { 309 ACPI_ERROR ((AE_INFO, 310 "Mutex [%s] already acquired by this thread [%u]", 311 AcpiUtGetMutexName (MutexId), 312 (UINT32) ThisThreadId)); 313 314 return (AE_ALREADY_ACQUIRED); 315 } 316 317 ACPI_ERROR ((AE_INFO, 318 "Invalid acquire order: Thread %u owns [%s], wants [%s]", 319 (UINT32) ThisThreadId, AcpiUtGetMutexName (i), 320 AcpiUtGetMutexName (MutexId))); 321 322 return (AE_ACQUIRE_DEADLOCK); 323 } 324 } 325 } 326 #endif 327 328 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 329 "Thread %u attempting to acquire Mutex [%s]\n", 330 (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 331 332 Status = AcpiOsAcquireMutex ( 333 AcpiGbl_MutexInfo[MutexId].Mutex, ACPI_WAIT_FOREVER); 334 if (ACPI_SUCCESS (Status)) 335 { 336 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 337 "Thread %u acquired Mutex [%s]\n", 338 (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 339 340 AcpiGbl_MutexInfo[MutexId].UseCount++; 341 AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId; 342 } 343 else 344 { 345 ACPI_EXCEPTION ((AE_INFO, Status, 346 "Thread %u could not acquire Mutex [0x%X]", 347 (UINT32) ThisThreadId, MutexId)); 348 } 349 350 return (Status); 351 } 352 353 354 /******************************************************************************* 355 * 356 * FUNCTION: AcpiUtReleaseMutex 357 * 358 * PARAMETERS: MutexID - ID of the mutex to be released 359 * 360 * RETURN: Status 361 * 362 * DESCRIPTION: Release a mutex object. 363 * 364 ******************************************************************************/ 365 366 ACPI_STATUS 367 AcpiUtReleaseMutex ( 368 ACPI_MUTEX_HANDLE MutexId) 369 { 370 ACPI_FUNCTION_NAME (UtReleaseMutex); 371 372 373 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", 374 (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId))); 375 376 if (MutexId > ACPI_MAX_MUTEX) 377 { 378 return (AE_BAD_PARAMETER); 379 } 380 381 /* 382 * Mutex must be acquired in order to release it! 383 */ 384 if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED) 385 { 386 ACPI_ERROR ((AE_INFO, 387 "Mutex [0x%X] is not acquired, cannot release", MutexId)); 388 389 return (AE_NOT_ACQUIRED); 390 } 391 392 #ifdef ACPI_MUTEX_DEBUG 393 { 394 UINT32 i; 395 /* 396 * Mutex debug code, for internal debugging only. 397 * 398 * Deadlock prevention. Check if this thread owns any mutexes of value 399 * greater than this one. If so, the thread has violated the mutex 400 * ordering rule. This indicates a coding error somewhere in 401 * the ACPI subsystem code. 402 */ 403 for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 404 { 405 if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ()) 406 { 407 if (i == MutexId) 408 { 409 continue; 410 } 411 412 ACPI_ERROR ((AE_INFO, 413 "Invalid release order: owns [%s], releasing [%s]", 414 AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); 415 416 return (AE_RELEASE_DEADLOCK); 417 } 418 } 419 } 420 #endif 421 422 /* Mark unlocked FIRST */ 423 424 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 425 426 AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 427 return (AE_OK); 428 } 429