utmutex.c revision 249112
1151937Sjkim/******************************************************************************* 2151937Sjkim * 3151937Sjkim * Module Name: utmutex - local mutex support 4151937Sjkim * 5151937Sjkim ******************************************************************************/ 6151937Sjkim 7217365Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp. 9151937Sjkim * All rights reserved. 10151937Sjkim * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 25151937Sjkim * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 29151937Sjkim * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 43151937Sjkim 44151937Sjkim 45151937Sjkim#define __UTMUTEX_C__ 46151937Sjkim 47193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 48193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 49151937Sjkim 50151937Sjkim#define _COMPONENT ACPI_UTILITIES 51151937Sjkim ACPI_MODULE_NAME ("utmutex") 52151937Sjkim 53151937Sjkim/* Local prototypes */ 54151937Sjkim 55151937Sjkimstatic ACPI_STATUS 56151937SjkimAcpiUtCreateMutex ( 57151937Sjkim ACPI_MUTEX_HANDLE MutexId); 58151937Sjkim 59202771Sjkimstatic void 60151937SjkimAcpiUtDeleteMutex ( 61151937Sjkim ACPI_MUTEX_HANDLE MutexId); 62151937Sjkim 63151937Sjkim 64151937Sjkim/******************************************************************************* 65151937Sjkim * 66151937Sjkim * FUNCTION: AcpiUtMutexInitialize 67151937Sjkim * 68151937Sjkim * PARAMETERS: None. 69151937Sjkim * 70151937Sjkim * RETURN: Status 71151937Sjkim * 72193267Sjkim * DESCRIPTION: Create the system mutex objects. This includes mutexes, 73193267Sjkim * spin locks, and reader/writer locks. 74151937Sjkim * 75151937Sjkim ******************************************************************************/ 76151937Sjkim 77151937SjkimACPI_STATUS 78151937SjkimAcpiUtMutexInitialize ( 79151937Sjkim void) 80151937Sjkim{ 81151937Sjkim UINT32 i; 82151937Sjkim ACPI_STATUS Status; 83151937Sjkim 84151937Sjkim 85167802Sjkim ACPI_FUNCTION_TRACE (UtMutexInitialize); 86151937Sjkim 87151937Sjkim 88193267Sjkim /* Create each of the predefined mutex objects */ 89193267Sjkim 90167802Sjkim for (i = 0; i < ACPI_NUM_MUTEX; i++) 91151937Sjkim { 92151937Sjkim Status = AcpiUtCreateMutex (i); 93151937Sjkim if (ACPI_FAILURE (Status)) 94151937Sjkim { 95151937Sjkim return_ACPI_STATUS (Status); 96151937Sjkim } 97151937Sjkim } 98151937Sjkim 99249112Sjkim /* Create the spinlocks for use at interrupt level or for speed */ 100167802Sjkim 101151937Sjkim Status = AcpiOsCreateLock (&AcpiGbl_GpeLock); 102167802Sjkim if (ACPI_FAILURE (Status)) 103167802Sjkim { 104167802Sjkim return_ACPI_STATUS (Status); 105167802Sjkim } 106167802Sjkim 107167802Sjkim Status = AcpiOsCreateLock (&AcpiGbl_HardwareLock); 108193267Sjkim if (ACPI_FAILURE (Status)) 109193267Sjkim { 110193267Sjkim return_ACPI_STATUS (Status); 111193267Sjkim } 112193267Sjkim 113249112Sjkim Status = AcpiOsCreateLock (&AcpiGbl_ReferenceCountLock); 114249112Sjkim if (ACPI_FAILURE (Status)) 115249112Sjkim { 116249112Sjkim return_ACPI_STATUS (Status); 117249112Sjkim } 118249112Sjkim 119210976Sjkim /* Mutex for _OSI support */ 120249112Sjkim 121210976Sjkim Status = AcpiOsCreateMutex (&AcpiGbl_OsiMutex); 122210976Sjkim if (ACPI_FAILURE (Status)) 123210976Sjkim { 124210976Sjkim return_ACPI_STATUS (Status); 125210976Sjkim } 126210976Sjkim 127193267Sjkim /* Create the reader/writer lock for namespace access */ 128193267Sjkim 129193267Sjkim Status = AcpiUtCreateRwLock (&AcpiGbl_NamespaceRwLock); 130151937Sjkim return_ACPI_STATUS (Status); 131151937Sjkim} 132151937Sjkim 133151937Sjkim 134151937Sjkim/******************************************************************************* 135151937Sjkim * 136151937Sjkim * FUNCTION: AcpiUtMutexTerminate 137151937Sjkim * 138151937Sjkim * PARAMETERS: None. 139151937Sjkim * 140151937Sjkim * RETURN: None. 141151937Sjkim * 142193267Sjkim * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, 143193267Sjkim * spin locks, and reader/writer locks. 144151937Sjkim * 145151937Sjkim ******************************************************************************/ 146151937Sjkim 147151937Sjkimvoid 148151937SjkimAcpiUtMutexTerminate ( 149151937Sjkim void) 150151937Sjkim{ 151151937Sjkim UINT32 i; 152151937Sjkim 153151937Sjkim 154167802Sjkim ACPI_FUNCTION_TRACE (UtMutexTerminate); 155151937Sjkim 156151937Sjkim 157193267Sjkim /* Delete each predefined mutex object */ 158193267Sjkim 159167802Sjkim for (i = 0; i < ACPI_NUM_MUTEX; i++) 160151937Sjkim { 161202771Sjkim AcpiUtDeleteMutex (i); 162151937Sjkim } 163151937Sjkim 164210976Sjkim AcpiOsDeleteMutex (AcpiGbl_OsiMutex); 165210976Sjkim 166167802Sjkim /* Delete the spinlocks */ 167167802Sjkim 168151937Sjkim AcpiOsDeleteLock (AcpiGbl_GpeLock); 169167802Sjkim AcpiOsDeleteLock (AcpiGbl_HardwareLock); 170249112Sjkim AcpiOsDeleteLock (AcpiGbl_ReferenceCountLock); 171193267Sjkim 172193267Sjkim /* Delete the reader/writer lock */ 173193267Sjkim 174193267Sjkim AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock); 175151937Sjkim return_VOID; 176151937Sjkim} 177151937Sjkim 178151937Sjkim 179151937Sjkim/******************************************************************************* 180151937Sjkim * 181151937Sjkim * FUNCTION: AcpiUtCreateMutex 182151937Sjkim * 183151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be created 184151937Sjkim * 185151937Sjkim * RETURN: Status 186151937Sjkim * 187151937Sjkim * DESCRIPTION: Create a mutex object. 188151937Sjkim * 189151937Sjkim ******************************************************************************/ 190151937Sjkim 191151937Sjkimstatic ACPI_STATUS 192151937SjkimAcpiUtCreateMutex ( 193151937Sjkim ACPI_MUTEX_HANDLE MutexId) 194151937Sjkim{ 195151937Sjkim ACPI_STATUS Status = AE_OK; 196151937Sjkim 197151937Sjkim 198167802Sjkim ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId); 199151937Sjkim 200151937Sjkim 201151937Sjkim if (!AcpiGbl_MutexInfo[MutexId].Mutex) 202151937Sjkim { 203167802Sjkim Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex); 204151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 205151937Sjkim AcpiGbl_MutexInfo[MutexId].UseCount = 0; 206151937Sjkim } 207151937Sjkim 208151937Sjkim return_ACPI_STATUS (Status); 209151937Sjkim} 210151937Sjkim 211151937Sjkim 212151937Sjkim/******************************************************************************* 213151937Sjkim * 214151937Sjkim * FUNCTION: AcpiUtDeleteMutex 215151937Sjkim * 216151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be deleted 217151937Sjkim * 218151937Sjkim * RETURN: Status 219151937Sjkim * 220151937Sjkim * DESCRIPTION: Delete a mutex object. 221151937Sjkim * 222151937Sjkim ******************************************************************************/ 223151937Sjkim 224202771Sjkimstatic void 225151937SjkimAcpiUtDeleteMutex ( 226151937Sjkim ACPI_MUTEX_HANDLE MutexId) 227151937Sjkim{ 228151937Sjkim 229167802Sjkim ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId); 230151937Sjkim 231151937Sjkim 232167802Sjkim AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 233151937Sjkim 234151937Sjkim AcpiGbl_MutexInfo[MutexId].Mutex = NULL; 235151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 236241973Sjkim 237241973Sjkim return_VOID; 238151937Sjkim} 239151937Sjkim 240151937Sjkim 241151937Sjkim/******************************************************************************* 242151937Sjkim * 243151937Sjkim * FUNCTION: AcpiUtAcquireMutex 244151937Sjkim * 245151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be acquired 246151937Sjkim * 247151937Sjkim * RETURN: Status 248151937Sjkim * 249151937Sjkim * DESCRIPTION: Acquire a mutex object. 250151937Sjkim * 251151937Sjkim ******************************************************************************/ 252151937Sjkim 253151937SjkimACPI_STATUS 254151937SjkimAcpiUtAcquireMutex ( 255151937Sjkim ACPI_MUTEX_HANDLE MutexId) 256151937Sjkim{ 257151937Sjkim ACPI_STATUS Status; 258167802Sjkim ACPI_THREAD_ID ThisThreadId; 259151937Sjkim 260151937Sjkim 261167802Sjkim ACPI_FUNCTION_NAME (UtAcquireMutex); 262151937Sjkim 263151937Sjkim 264167802Sjkim if (MutexId > ACPI_MAX_MUTEX) 265151937Sjkim { 266151937Sjkim return (AE_BAD_PARAMETER); 267151937Sjkim } 268151937Sjkim 269151937Sjkim ThisThreadId = AcpiOsGetThreadId (); 270151937Sjkim 271151937Sjkim#ifdef ACPI_MUTEX_DEBUG 272151937Sjkim { 273151937Sjkim UINT32 i; 274151937Sjkim /* 275151937Sjkim * Mutex debug code, for internal debugging only. 276151937Sjkim * 277241973Sjkim * Deadlock prevention. Check if this thread owns any mutexes of value 278241973Sjkim * greater than or equal to this one. If so, the thread has violated 279241973Sjkim * the mutex ordering rule. This indicates a coding error somewhere in 280151937Sjkim * the ACPI subsystem code. 281151937Sjkim */ 282193267Sjkim for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 283151937Sjkim { 284151937Sjkim if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) 285151937Sjkim { 286151937Sjkim if (i == MutexId) 287151937Sjkim { 288167802Sjkim ACPI_ERROR ((AE_INFO, 289212761Sjkim "Mutex [%s] already acquired by this thread [%u]", 290193267Sjkim AcpiUtGetMutexName (MutexId), 291212761Sjkim (UINT32) ThisThreadId)); 292151937Sjkim 293151937Sjkim return (AE_ALREADY_ACQUIRED); 294151937Sjkim } 295151937Sjkim 296167802Sjkim ACPI_ERROR ((AE_INFO, 297212761Sjkim "Invalid acquire order: Thread %u owns [%s], wants [%s]", 298212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (i), 299151937Sjkim AcpiUtGetMutexName (MutexId))); 300151937Sjkim 301151937Sjkim return (AE_ACQUIRE_DEADLOCK); 302151937Sjkim } 303151937Sjkim } 304151937Sjkim } 305151937Sjkim#endif 306151937Sjkim 307151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 308212761Sjkim "Thread %u attempting to acquire Mutex [%s]\n", 309212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 310151937Sjkim 311167802Sjkim Status = AcpiOsAcquireMutex (AcpiGbl_MutexInfo[MutexId].Mutex, 312167802Sjkim ACPI_WAIT_FOREVER); 313151937Sjkim if (ACPI_SUCCESS (Status)) 314151937Sjkim { 315212761Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u acquired Mutex [%s]\n", 316212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 317151937Sjkim 318151937Sjkim AcpiGbl_MutexInfo[MutexId].UseCount++; 319151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId; 320151937Sjkim } 321151937Sjkim else 322151937Sjkim { 323167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 324212761Sjkim "Thread %u could not acquire Mutex [0x%X]", 325212761Sjkim (UINT32) ThisThreadId, MutexId)); 326151937Sjkim } 327151937Sjkim 328151937Sjkim return (Status); 329151937Sjkim} 330151937Sjkim 331151937Sjkim 332151937Sjkim/******************************************************************************* 333151937Sjkim * 334151937Sjkim * FUNCTION: AcpiUtReleaseMutex 335151937Sjkim * 336151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be released 337151937Sjkim * 338151937Sjkim * RETURN: Status 339151937Sjkim * 340151937Sjkim * DESCRIPTION: Release a mutex object. 341151937Sjkim * 342151937Sjkim ******************************************************************************/ 343151937Sjkim 344151937SjkimACPI_STATUS 345151937SjkimAcpiUtReleaseMutex ( 346151937Sjkim ACPI_MUTEX_HANDLE MutexId) 347151937Sjkim{ 348167802Sjkim ACPI_FUNCTION_NAME (UtReleaseMutex); 349151937Sjkim 350241973Sjkim 351212761Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", 352228110Sjkim (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId))); 353151937Sjkim 354167802Sjkim if (MutexId > ACPI_MAX_MUTEX) 355151937Sjkim { 356151937Sjkim return (AE_BAD_PARAMETER); 357151937Sjkim } 358151937Sjkim 359151937Sjkim /* 360151937Sjkim * Mutex must be acquired in order to release it! 361151937Sjkim */ 362151937Sjkim if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED) 363151937Sjkim { 364167802Sjkim ACPI_ERROR ((AE_INFO, 365204773Sjkim "Mutex [0x%X] is not acquired, cannot release", MutexId)); 366151937Sjkim 367151937Sjkim return (AE_NOT_ACQUIRED); 368151937Sjkim } 369151937Sjkim 370151937Sjkim#ifdef ACPI_MUTEX_DEBUG 371151937Sjkim { 372151937Sjkim UINT32 i; 373151937Sjkim /* 374151937Sjkim * Mutex debug code, for internal debugging only. 375151937Sjkim * 376241973Sjkim * Deadlock prevention. Check if this thread owns any mutexes of value 377241973Sjkim * greater than this one. If so, the thread has violated the mutex 378241973Sjkim * ordering rule. This indicates a coding error somewhere in 379151937Sjkim * the ACPI subsystem code. 380151937Sjkim */ 381193267Sjkim for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 382151937Sjkim { 383228110Sjkim if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ()) 384151937Sjkim { 385151937Sjkim if (i == MutexId) 386151937Sjkim { 387151937Sjkim continue; 388151937Sjkim } 389151937Sjkim 390167802Sjkim ACPI_ERROR ((AE_INFO, 391167802Sjkim "Invalid release order: owns [%s], releasing [%s]", 392151937Sjkim AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); 393151937Sjkim 394151937Sjkim return (AE_RELEASE_DEADLOCK); 395151937Sjkim } 396151937Sjkim } 397151937Sjkim } 398151937Sjkim#endif 399151937Sjkim 400151937Sjkim /* Mark unlocked FIRST */ 401151937Sjkim 402151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 403151937Sjkim 404167802Sjkim AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 405167802Sjkim return (AE_OK); 406151937Sjkim} 407