1 /******************************************************************************* 2 * 3 * Module Name: utmutex - local mutex support 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 45 #define __UTMUTEX_C__ 46 47 #include "acpi.h" 48 #include "accommon.h" 49 50 #define _COMPONENT ACPI_UTILITIES 51 ACPI_MODULE_NAME ("utmutex") 52 53 /* Local prototypes */ 54 55 static ACPI_STATUS 56 AcpiUtCreateMutex ( 57 ACPI_MUTEX_HANDLE MutexId); 58 59 static void 60 AcpiUtDeleteMutex ( 61 ACPI_MUTEX_HANDLE MutexId); 62 63 64 /******************************************************************************* 65 * 66 * FUNCTION: AcpiUtMutexInitialize 67 * 68 * PARAMETERS: None. 69 * 70 * RETURN: Status 71 * 72 * DESCRIPTION: Create the system mutex objects. This includes mutexes, 73 * spin locks, and reader/writer locks. 74 * 75 ******************************************************************************/ 76 77 ACPI_STATUS 78 AcpiUtMutexInitialize ( 79 void) 80 { 81 UINT32 i; 82 ACPI_STATUS Status; 83 84 85 ACPI_FUNCTION_TRACE (UtMutexInitialize); 86 87 88 /* Create each of the predefined mutex objects */ 89 90 for (i = 0; i < ACPI_NUM_MUTEX; i++) 91 { 92 Status = AcpiUtCreateMutex (i); 93 if (ACPI_FAILURE (Status)) 94 { 95 return_ACPI_STATUS (Status); 96 } 97 } 98 99 /* Create the spinlocks for use at interrupt level or for speed */ 100 101 Status = AcpiOsCreateLock (&AcpiGbl_GpeLock); 102 if (ACPI_FAILURE (Status)) 103 { 104 return_ACPI_STATUS (Status); 105 } 106 107 Status = AcpiOsCreateLock (&AcpiGbl_HardwareLock); 108 if (ACPI_FAILURE (Status)) 109 { 110 return_ACPI_STATUS (Status); 111 } 112 113 Status = AcpiOsCreateLock (&AcpiGbl_ReferenceCountLock); 114 if (ACPI_FAILURE (Status)) 115 { 116 return_ACPI_STATUS (Status); 117 } 118 119 /* Mutex for _OSI support */ 120 121 Status = AcpiOsCreateMutex (&AcpiGbl_OsiMutex); 122 if (ACPI_FAILURE (Status)) 123 { 124 return_ACPI_STATUS (Status); 125 } 126 127 /* Create the reader/writer lock for namespace access */ 128 129 Status = AcpiUtCreateRwLock (&AcpiGbl_NamespaceRwLock); 130 return_ACPI_STATUS (Status); 131 } 132 133 134 /******************************************************************************* 135 * 136 * FUNCTION: AcpiUtMutexTerminate 137 * 138 * PARAMETERS: None. 139 * 140 * RETURN: None. 141 * 142 * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, 143 * spin locks, and reader/writer locks. 144 * 145 ******************************************************************************/ 146 147 void 148 AcpiUtMutexTerminate ( 149 void) 150 { 151 UINT32 i; 152 153 154 ACPI_FUNCTION_TRACE (UtMutexTerminate); 155 156 157 /* Delete each predefined mutex object */ 158 159 for (i = 0; i < ACPI_NUM_MUTEX; i++) 160 { 161 AcpiUtDeleteMutex (i); 162 } 163 164 AcpiOsDeleteMutex (AcpiGbl_OsiMutex); 165 166 /* Delete the spinlocks */ 167 168 AcpiOsDeleteLock (AcpiGbl_GpeLock); 169 AcpiOsDeleteLock (AcpiGbl_HardwareLock); 170 AcpiOsDeleteLock (AcpiGbl_ReferenceCountLock); 171 172 /* Delete the reader/writer lock */ 173 174 AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock); 175 return_VOID; 176 } 177 178 179 /******************************************************************************* 180 * 181 * FUNCTION: AcpiUtCreateMutex 182 * 183 * PARAMETERS: MutexID - ID of the mutex to be created 184 * 185 * RETURN: Status 186 * 187 * DESCRIPTION: Create a mutex object. 188 * 189 ******************************************************************************/ 190 191 static ACPI_STATUS 192 AcpiUtCreateMutex ( 193 ACPI_MUTEX_HANDLE MutexId) 194 { 195 ACPI_STATUS Status = AE_OK; 196 197 198 ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId); 199 200 201 if (!AcpiGbl_MutexInfo[MutexId].Mutex) 202 { 203 Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex); 204 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 205 AcpiGbl_MutexInfo[MutexId].UseCount = 0; 206 } 207 208 return_ACPI_STATUS (Status); 209 } 210 211 212 /******************************************************************************* 213 * 214 * FUNCTION: AcpiUtDeleteMutex 215 * 216 * PARAMETERS: MutexID - ID of the mutex to be deleted 217 * 218 * RETURN: Status 219 * 220 * DESCRIPTION: Delete a mutex object. 221 * 222 ******************************************************************************/ 223 224 static void 225 AcpiUtDeleteMutex ( 226 ACPI_MUTEX_HANDLE MutexId) 227 { 228 229 ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId); 230 231 232 AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 233 234 AcpiGbl_MutexInfo[MutexId].Mutex = NULL; 235 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 236 237 return_VOID; 238 } 239 240 241 /******************************************************************************* 242 * 243 * FUNCTION: AcpiUtAcquireMutex 244 * 245 * PARAMETERS: MutexID - ID of the mutex to be acquired 246 * 247 * RETURN: Status 248 * 249 * DESCRIPTION: Acquire a mutex object. 250 * 251 ******************************************************************************/ 252 253 ACPI_STATUS 254 AcpiUtAcquireMutex ( 255 ACPI_MUTEX_HANDLE MutexId) 256 { 257 ACPI_STATUS Status; 258 ACPI_THREAD_ID ThisThreadId; 259 260 261 ACPI_FUNCTION_NAME (UtAcquireMutex); 262 263 264 if (MutexId > ACPI_MAX_MUTEX) 265 { 266 return (AE_BAD_PARAMETER); 267 } 268 269 ThisThreadId = AcpiOsGetThreadId (); 270 271 #ifdef ACPI_MUTEX_DEBUG 272 { 273 UINT32 i; 274 /* 275 * Mutex debug code, for internal debugging only. 276 * 277 * Deadlock prevention. Check if this thread owns any mutexes of value 278 * greater than or equal to this one. If so, the thread has violated 279 * the mutex ordering rule. This indicates a coding error somewhere in 280 * the ACPI subsystem code. 281 */ 282 for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 283 { 284 if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) 285 { 286 if (i == MutexId) 287 { 288 ACPI_ERROR ((AE_INFO, 289 "Mutex [%s] already acquired by this thread [%u]", 290 AcpiUtGetMutexName (MutexId), 291 (UINT32) ThisThreadId)); 292 293 return (AE_ALREADY_ACQUIRED); 294 } 295 296 ACPI_ERROR ((AE_INFO, 297 "Invalid acquire order: Thread %u owns [%s], wants [%s]", 298 (UINT32) ThisThreadId, AcpiUtGetMutexName (i), 299 AcpiUtGetMutexName (MutexId))); 300 301 return (AE_ACQUIRE_DEADLOCK); 302 } 303 } 304 } 305 #endif 306 307 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 308 "Thread %u attempting to acquire Mutex [%s]\n", 309 (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 310 311 Status = AcpiOsAcquireMutex (AcpiGbl_MutexInfo[MutexId].Mutex, 312 ACPI_WAIT_FOREVER); 313 if (ACPI_SUCCESS (Status)) 314 { 315 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u acquired Mutex [%s]\n", 316 (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 317 318 AcpiGbl_MutexInfo[MutexId].UseCount++; 319 AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId; 320 } 321 else 322 { 323 ACPI_EXCEPTION ((AE_INFO, Status, 324 "Thread %u could not acquire Mutex [0x%X]", 325 (UINT32) ThisThreadId, MutexId)); 326 } 327 328 return (Status); 329 } 330 331 332 /******************************************************************************* 333 * 334 * FUNCTION: AcpiUtReleaseMutex 335 * 336 * PARAMETERS: MutexID - ID of the mutex to be released 337 * 338 * RETURN: Status 339 * 340 * DESCRIPTION: Release a mutex object. 341 * 342 ******************************************************************************/ 343 344 ACPI_STATUS 345 AcpiUtReleaseMutex ( 346 ACPI_MUTEX_HANDLE MutexId) 347 { 348 ACPI_FUNCTION_NAME (UtReleaseMutex); 349 350 351 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", 352 (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId))); 353 354 if (MutexId > ACPI_MAX_MUTEX) 355 { 356 return (AE_BAD_PARAMETER); 357 } 358 359 /* 360 * Mutex must be acquired in order to release it! 361 */ 362 if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED) 363 { 364 ACPI_ERROR ((AE_INFO, 365 "Mutex [0x%X] is not acquired, cannot release", MutexId)); 366 367 return (AE_NOT_ACQUIRED); 368 } 369 370 #ifdef ACPI_MUTEX_DEBUG 371 { 372 UINT32 i; 373 /* 374 * Mutex debug code, for internal debugging only. 375 * 376 * Deadlock prevention. Check if this thread owns any mutexes of value 377 * greater than this one. If so, the thread has violated the mutex 378 * ordering rule. This indicates a coding error somewhere in 379 * the ACPI subsystem code. 380 */ 381 for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 382 { 383 if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ()) 384 { 385 if (i == MutexId) 386 { 387 continue; 388 } 389 390 ACPI_ERROR ((AE_INFO, 391 "Invalid release order: owns [%s], releasing [%s]", 392 AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); 393 394 return (AE_RELEASE_DEADLOCK); 395 } 396 } 397 } 398 #endif 399 400 /* Mark unlocked FIRST */ 401 402 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 403 404 AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 405 return (AE_OK); 406 }