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