utmutex.c revision 306536
1178170Simp/******************************************************************************* 2178170Simp * 3178170Simp * Module Name: utmutex - local mutex support 4178170Simp * 5178170Simp ******************************************************************************/ 6178170Simp 7241933Simp/* 8241933Simp * Copyright (C) 2000 - 2016, Intel Corp. 9241933Simp * All rights reserved. 10241933Simp * 11241933Simp * Redistribution and use in source and binary forms, with or without 12241933Simp * modification, are permitted provided that the following conditions 13241933Simp * are met: 14241933Simp * 1. Redistributions of source code must retain the above copyright 15241933Simp * notice, this list of conditions, and the following disclaimer, 16241933Simp * without modification. 17241933Simp * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18241933Simp * substantially similar to the "NO WARRANTY" disclaimer below 19241933Simp * ("Disclaimer") and any redistribution must be conditioned upon 20241933Simp * including a substantially similar Disclaimer requirement for further 21242066Simp * binary redistribution. 22241933Simp * 3. Neither the names of the above-listed copyright holders nor the names 23241933Simp * of any contributors may be used to endorse or promote products derived 24241933Simp * from this software without specific prior written permission. 25241933Simp * 26241933Simp * Alternatively, this software may be distributed under the terms of the 27241933Simp * GNU General Public License ("GPL") version 2 as published by the Free 28241933Simp * Software Foundation. 29241933Simp * 30241933Simp * NO WARRANTY 31241933Simp * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32292556Sian * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33241933Simp * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34241933Simp * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35241933Simp * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36241933Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37242162Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38251524Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39251524Sed * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40241933Simp * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41255367Sjchandra * POSSIBILITY OF SUCH DAMAGES. 42241933Simp */ 43241933Simp 44241933Simp#include <contrib/dev/acpica/include/acpi.h> 45241933Simp#include <contrib/dev/acpica/include/accommon.h> 46241933Simp 47241933Simp#define _COMPONENT ACPI_UTILITIES 48241933Simp ACPI_MODULE_NAME ("utmutex") 49178170Simp 50241933Simp/* Local prototypes */ 51241933Simp 52241933Simpstatic ACPI_STATUS 53289701SianAcpiUtCreateMutex ( 54241933Simp ACPI_MUTEX_HANDLE MutexId); 55269577Sglebius 56178170Simpstatic void 57241933SimpAcpiUtDeleteMutex ( 58241933Simp ACPI_MUTEX_HANDLE MutexId); 59289765Scem 60241933Simp 61241933Simp/******************************************************************************* 62261891Savg * 63241933Simp * FUNCTION: AcpiUtMutexInitialize 64255290Sglebius * 65242064Simp * PARAMETERS: None. 66284587Sadrian * 67284587Sadrian * RETURN: Status 68241933Simp * 69241936Simp * DESCRIPTION: Create the system mutex objects. This includes mutexes, 70241933Simp * spin locks, and reader/writer locks. 71241933Simp * 72241933Simp ******************************************************************************/ 73241936Simp 74241936SimpACPI_STATUS 75241936SimpAcpiUtMutexInitialize ( 76241936Simp void) 77241936Simp{ 78241936Simp UINT32 i; 79241936Simp ACPI_STATUS Status; 80241953Simp 81241953Simp 82250840Smarcel ACPI_FUNCTION_TRACE (UtMutexInitialize); 83241954Simp 84241954Simp 85315514Sae /* Create each of the predefined mutex objects */ 86315514Sae 87315514Sae for (i = 0; i < ACPI_NUM_MUTEX; i++) 88315514Sae { 89241964Simp Status = AcpiUtCreateMutex (i); 90242204Simp if (ACPI_FAILURE (Status)) 91241964Simp { 92241986Simp return_ACPI_STATUS (Status); 93242204Simp } 94242004Simp } 95243178Sadrian 96281098Sadrian /* Create the spinlocks for use at interrupt level or for speed */ 97297392Szbb 98297392Szbb Status = AcpiOsCreateLock (&AcpiGbl_GpeLock); 99297392Szbb if (ACPI_FAILURE (Status)) 100299118Sbr { 101299118Sbr return_ACPI_STATUS (Status); 102299118Sbr } 103299118Sbr 104299118Sbr Status = AcpiOsCreateLock (&AcpiGbl_HardwareLock); 105299118Sbr 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 162void 163AcpiUtMutexTerminate ( 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 212static ACPI_STATUS 213AcpiUtCreateMutex ( 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 245static void 246AcpiUtDeleteMutex ( 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 274ACPI_STATUS 275AcpiUtAcquireMutex ( 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 366ACPI_STATUS 367AcpiUtReleaseMutex ( 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