utmutex.c revision 217365
1151937Sjkim/******************************************************************************* 2151937Sjkim * 3151937Sjkim * Module Name: utmutex - local mutex support 4151937Sjkim * 5151937Sjkim ******************************************************************************/ 6151937Sjkim 7217365Sjkim/* 8217365Sjkim * Copyright (C) 2000 - 2011, 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 99167802Sjkim /* Create the spinlocks for use at interrupt level */ 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 113210976Sjkim /* Mutex for _OSI support */ 114210976Sjkim Status = AcpiOsCreateMutex (&AcpiGbl_OsiMutex); 115210976Sjkim if (ACPI_FAILURE (Status)) 116210976Sjkim { 117210976Sjkim return_ACPI_STATUS (Status); 118210976Sjkim } 119210976Sjkim 120193267Sjkim /* Create the reader/writer lock for namespace access */ 121193267Sjkim 122193267Sjkim Status = AcpiUtCreateRwLock (&AcpiGbl_NamespaceRwLock); 123151937Sjkim return_ACPI_STATUS (Status); 124151937Sjkim} 125151937Sjkim 126151937Sjkim 127151937Sjkim/******************************************************************************* 128151937Sjkim * 129151937Sjkim * FUNCTION: AcpiUtMutexTerminate 130151937Sjkim * 131151937Sjkim * PARAMETERS: None. 132151937Sjkim * 133151937Sjkim * RETURN: None. 134151937Sjkim * 135193267Sjkim * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, 136193267Sjkim * spin locks, and reader/writer locks. 137151937Sjkim * 138151937Sjkim ******************************************************************************/ 139151937Sjkim 140151937Sjkimvoid 141151937SjkimAcpiUtMutexTerminate ( 142151937Sjkim void) 143151937Sjkim{ 144151937Sjkim UINT32 i; 145151937Sjkim 146151937Sjkim 147167802Sjkim ACPI_FUNCTION_TRACE (UtMutexTerminate); 148151937Sjkim 149151937Sjkim 150193267Sjkim /* Delete each predefined mutex object */ 151193267Sjkim 152167802Sjkim for (i = 0; i < ACPI_NUM_MUTEX; i++) 153151937Sjkim { 154202771Sjkim AcpiUtDeleteMutex (i); 155151937Sjkim } 156151937Sjkim 157210976Sjkim AcpiOsDeleteMutex (AcpiGbl_OsiMutex); 158210976Sjkim 159167802Sjkim /* Delete the spinlocks */ 160167802Sjkim 161151937Sjkim AcpiOsDeleteLock (AcpiGbl_GpeLock); 162167802Sjkim AcpiOsDeleteLock (AcpiGbl_HardwareLock); 163193267Sjkim 164193267Sjkim /* Delete the reader/writer lock */ 165193267Sjkim 166193267Sjkim AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock); 167151937Sjkim return_VOID; 168151937Sjkim} 169151937Sjkim 170151937Sjkim 171151937Sjkim/******************************************************************************* 172151937Sjkim * 173151937Sjkim * FUNCTION: AcpiUtCreateMutex 174151937Sjkim * 175151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be created 176151937Sjkim * 177151937Sjkim * RETURN: Status 178151937Sjkim * 179151937Sjkim * DESCRIPTION: Create a mutex object. 180151937Sjkim * 181151937Sjkim ******************************************************************************/ 182151937Sjkim 183151937Sjkimstatic ACPI_STATUS 184151937SjkimAcpiUtCreateMutex ( 185151937Sjkim ACPI_MUTEX_HANDLE MutexId) 186151937Sjkim{ 187151937Sjkim ACPI_STATUS Status = AE_OK; 188151937Sjkim 189151937Sjkim 190167802Sjkim ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId); 191151937Sjkim 192151937Sjkim 193151937Sjkim if (!AcpiGbl_MutexInfo[MutexId].Mutex) 194151937Sjkim { 195167802Sjkim Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex); 196151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 197151937Sjkim AcpiGbl_MutexInfo[MutexId].UseCount = 0; 198151937Sjkim } 199151937Sjkim 200151937Sjkim return_ACPI_STATUS (Status); 201151937Sjkim} 202151937Sjkim 203151937Sjkim 204151937Sjkim/******************************************************************************* 205151937Sjkim * 206151937Sjkim * FUNCTION: AcpiUtDeleteMutex 207151937Sjkim * 208151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be deleted 209151937Sjkim * 210151937Sjkim * RETURN: Status 211151937Sjkim * 212151937Sjkim * DESCRIPTION: Delete a mutex object. 213151937Sjkim * 214151937Sjkim ******************************************************************************/ 215151937Sjkim 216202771Sjkimstatic void 217151937SjkimAcpiUtDeleteMutex ( 218151937Sjkim ACPI_MUTEX_HANDLE MutexId) 219151937Sjkim{ 220151937Sjkim 221167802Sjkim ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId); 222151937Sjkim 223151937Sjkim 224167802Sjkim AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 225151937Sjkim 226151937Sjkim AcpiGbl_MutexInfo[MutexId].Mutex = NULL; 227151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 228151937Sjkim} 229151937Sjkim 230151937Sjkim 231151937Sjkim/******************************************************************************* 232151937Sjkim * 233151937Sjkim * FUNCTION: AcpiUtAcquireMutex 234151937Sjkim * 235151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be acquired 236151937Sjkim * 237151937Sjkim * RETURN: Status 238151937Sjkim * 239151937Sjkim * DESCRIPTION: Acquire a mutex object. 240151937Sjkim * 241151937Sjkim ******************************************************************************/ 242151937Sjkim 243151937SjkimACPI_STATUS 244151937SjkimAcpiUtAcquireMutex ( 245151937Sjkim ACPI_MUTEX_HANDLE MutexId) 246151937Sjkim{ 247151937Sjkim ACPI_STATUS Status; 248167802Sjkim ACPI_THREAD_ID ThisThreadId; 249151937Sjkim 250151937Sjkim 251167802Sjkim ACPI_FUNCTION_NAME (UtAcquireMutex); 252151937Sjkim 253151937Sjkim 254167802Sjkim if (MutexId > ACPI_MAX_MUTEX) 255151937Sjkim { 256151937Sjkim return (AE_BAD_PARAMETER); 257151937Sjkim } 258151937Sjkim 259151937Sjkim ThisThreadId = AcpiOsGetThreadId (); 260151937Sjkim 261151937Sjkim#ifdef ACPI_MUTEX_DEBUG 262151937Sjkim { 263151937Sjkim UINT32 i; 264151937Sjkim /* 265151937Sjkim * Mutex debug code, for internal debugging only. 266151937Sjkim * 267151937Sjkim * Deadlock prevention. Check if this thread owns any mutexes of value 268151937Sjkim * greater than or equal to this one. If so, the thread has violated 269151937Sjkim * the mutex ordering rule. This indicates a coding error somewhere in 270151937Sjkim * the ACPI subsystem code. 271151937Sjkim */ 272193267Sjkim for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 273151937Sjkim { 274151937Sjkim if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) 275151937Sjkim { 276151937Sjkim if (i == MutexId) 277151937Sjkim { 278167802Sjkim ACPI_ERROR ((AE_INFO, 279212761Sjkim "Mutex [%s] already acquired by this thread [%u]", 280193267Sjkim AcpiUtGetMutexName (MutexId), 281212761Sjkim (UINT32) ThisThreadId)); 282151937Sjkim 283151937Sjkim return (AE_ALREADY_ACQUIRED); 284151937Sjkim } 285151937Sjkim 286167802Sjkim ACPI_ERROR ((AE_INFO, 287212761Sjkim "Invalid acquire order: Thread %u owns [%s], wants [%s]", 288212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (i), 289151937Sjkim AcpiUtGetMutexName (MutexId))); 290151937Sjkim 291151937Sjkim return (AE_ACQUIRE_DEADLOCK); 292151937Sjkim } 293151937Sjkim } 294151937Sjkim } 295151937Sjkim#endif 296151937Sjkim 297151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 298212761Sjkim "Thread %u attempting to acquire Mutex [%s]\n", 299212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 300151937Sjkim 301167802Sjkim Status = AcpiOsAcquireMutex (AcpiGbl_MutexInfo[MutexId].Mutex, 302167802Sjkim ACPI_WAIT_FOREVER); 303151937Sjkim if (ACPI_SUCCESS (Status)) 304151937Sjkim { 305212761Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u acquired Mutex [%s]\n", 306212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 307151937Sjkim 308151937Sjkim AcpiGbl_MutexInfo[MutexId].UseCount++; 309151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId; 310151937Sjkim } 311151937Sjkim else 312151937Sjkim { 313167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 314212761Sjkim "Thread %u could not acquire Mutex [0x%X]", 315212761Sjkim (UINT32) ThisThreadId, MutexId)); 316151937Sjkim } 317151937Sjkim 318151937Sjkim return (Status); 319151937Sjkim} 320151937Sjkim 321151937Sjkim 322151937Sjkim/******************************************************************************* 323151937Sjkim * 324151937Sjkim * FUNCTION: AcpiUtReleaseMutex 325151937Sjkim * 326151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be released 327151937Sjkim * 328151937Sjkim * RETURN: Status 329151937Sjkim * 330151937Sjkim * DESCRIPTION: Release a mutex object. 331151937Sjkim * 332151937Sjkim ******************************************************************************/ 333151937Sjkim 334151937SjkimACPI_STATUS 335151937SjkimAcpiUtReleaseMutex ( 336151937Sjkim ACPI_MUTEX_HANDLE MutexId) 337151937Sjkim{ 338167802Sjkim ACPI_THREAD_ID ThisThreadId; 339151937Sjkim 340151937Sjkim 341167802Sjkim ACPI_FUNCTION_NAME (UtReleaseMutex); 342151937Sjkim 343151937Sjkim 344151937Sjkim ThisThreadId = AcpiOsGetThreadId (); 345212761Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", 346212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 347151937Sjkim 348167802Sjkim if (MutexId > ACPI_MAX_MUTEX) 349151937Sjkim { 350151937Sjkim return (AE_BAD_PARAMETER); 351151937Sjkim } 352151937Sjkim 353151937Sjkim /* 354151937Sjkim * Mutex must be acquired in order to release it! 355151937Sjkim */ 356151937Sjkim if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED) 357151937Sjkim { 358167802Sjkim ACPI_ERROR ((AE_INFO, 359204773Sjkim "Mutex [0x%X] is not acquired, cannot release", MutexId)); 360151937Sjkim 361151937Sjkim return (AE_NOT_ACQUIRED); 362151937Sjkim } 363151937Sjkim 364151937Sjkim#ifdef ACPI_MUTEX_DEBUG 365151937Sjkim { 366151937Sjkim UINT32 i; 367151937Sjkim /* 368151937Sjkim * Mutex debug code, for internal debugging only. 369151937Sjkim * 370151937Sjkim * Deadlock prevention. Check if this thread owns any mutexes of value 371151937Sjkim * greater than this one. If so, the thread has violated the mutex 372151937Sjkim * ordering rule. This indicates a coding error somewhere in 373151937Sjkim * the ACPI subsystem code. 374151937Sjkim */ 375193267Sjkim for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 376151937Sjkim { 377151937Sjkim if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) 378151937Sjkim { 379151937Sjkim if (i == MutexId) 380151937Sjkim { 381151937Sjkim continue; 382151937Sjkim } 383151937Sjkim 384167802Sjkim ACPI_ERROR ((AE_INFO, 385167802Sjkim "Invalid release order: owns [%s], releasing [%s]", 386151937Sjkim AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); 387151937Sjkim 388151937Sjkim return (AE_RELEASE_DEADLOCK); 389151937Sjkim } 390151937Sjkim } 391151937Sjkim } 392151937Sjkim#endif 393151937Sjkim 394151937Sjkim /* Mark unlocked FIRST */ 395151937Sjkim 396151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 397151937Sjkim 398167802Sjkim AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 399167802Sjkim return (AE_OK); 400151937Sjkim} 401151937Sjkim 402151937Sjkim 403