utmutex.c revision 245582
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 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; 228241973Sjkim 229241973Sjkim return_VOID; 230151937Sjkim} 231151937Sjkim 232151937Sjkim 233151937Sjkim/******************************************************************************* 234151937Sjkim * 235151937Sjkim * FUNCTION: AcpiUtAcquireMutex 236151937Sjkim * 237151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be acquired 238151937Sjkim * 239151937Sjkim * RETURN: Status 240151937Sjkim * 241151937Sjkim * DESCRIPTION: Acquire a mutex object. 242151937Sjkim * 243151937Sjkim ******************************************************************************/ 244151937Sjkim 245151937SjkimACPI_STATUS 246151937SjkimAcpiUtAcquireMutex ( 247151937Sjkim ACPI_MUTEX_HANDLE MutexId) 248151937Sjkim{ 249151937Sjkim ACPI_STATUS Status; 250167802Sjkim ACPI_THREAD_ID ThisThreadId; 251151937Sjkim 252151937Sjkim 253167802Sjkim ACPI_FUNCTION_NAME (UtAcquireMutex); 254151937Sjkim 255151937Sjkim 256167802Sjkim if (MutexId > ACPI_MAX_MUTEX) 257151937Sjkim { 258151937Sjkim return (AE_BAD_PARAMETER); 259151937Sjkim } 260151937Sjkim 261151937Sjkim ThisThreadId = AcpiOsGetThreadId (); 262151937Sjkim 263151937Sjkim#ifdef ACPI_MUTEX_DEBUG 264151937Sjkim { 265151937Sjkim UINT32 i; 266151937Sjkim /* 267151937Sjkim * Mutex debug code, for internal debugging only. 268151937Sjkim * 269241973Sjkim * Deadlock prevention. Check if this thread owns any mutexes of value 270241973Sjkim * greater than or equal to this one. If so, the thread has violated 271241973Sjkim * the mutex ordering rule. This indicates a coding error somewhere in 272151937Sjkim * the ACPI subsystem code. 273151937Sjkim */ 274193267Sjkim for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 275151937Sjkim { 276151937Sjkim if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) 277151937Sjkim { 278151937Sjkim if (i == MutexId) 279151937Sjkim { 280167802Sjkim ACPI_ERROR ((AE_INFO, 281212761Sjkim "Mutex [%s] already acquired by this thread [%u]", 282193267Sjkim AcpiUtGetMutexName (MutexId), 283212761Sjkim (UINT32) ThisThreadId)); 284151937Sjkim 285151937Sjkim return (AE_ALREADY_ACQUIRED); 286151937Sjkim } 287151937Sjkim 288167802Sjkim ACPI_ERROR ((AE_INFO, 289212761Sjkim "Invalid acquire order: Thread %u owns [%s], wants [%s]", 290212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (i), 291151937Sjkim AcpiUtGetMutexName (MutexId))); 292151937Sjkim 293151937Sjkim return (AE_ACQUIRE_DEADLOCK); 294151937Sjkim } 295151937Sjkim } 296151937Sjkim } 297151937Sjkim#endif 298151937Sjkim 299151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 300212761Sjkim "Thread %u attempting to acquire Mutex [%s]\n", 301212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 302151937Sjkim 303167802Sjkim Status = AcpiOsAcquireMutex (AcpiGbl_MutexInfo[MutexId].Mutex, 304167802Sjkim ACPI_WAIT_FOREVER); 305151937Sjkim if (ACPI_SUCCESS (Status)) 306151937Sjkim { 307212761Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u acquired Mutex [%s]\n", 308212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 309151937Sjkim 310151937Sjkim AcpiGbl_MutexInfo[MutexId].UseCount++; 311151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId; 312151937Sjkim } 313151937Sjkim else 314151937Sjkim { 315167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 316212761Sjkim "Thread %u could not acquire Mutex [0x%X]", 317212761Sjkim (UINT32) ThisThreadId, MutexId)); 318151937Sjkim } 319151937Sjkim 320151937Sjkim return (Status); 321151937Sjkim} 322151937Sjkim 323151937Sjkim 324151937Sjkim/******************************************************************************* 325151937Sjkim * 326151937Sjkim * FUNCTION: AcpiUtReleaseMutex 327151937Sjkim * 328151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be released 329151937Sjkim * 330151937Sjkim * RETURN: Status 331151937Sjkim * 332151937Sjkim * DESCRIPTION: Release a mutex object. 333151937Sjkim * 334151937Sjkim ******************************************************************************/ 335151937Sjkim 336151937SjkimACPI_STATUS 337151937SjkimAcpiUtReleaseMutex ( 338151937Sjkim ACPI_MUTEX_HANDLE MutexId) 339151937Sjkim{ 340167802Sjkim ACPI_FUNCTION_NAME (UtReleaseMutex); 341151937Sjkim 342241973Sjkim 343212761Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", 344228110Sjkim (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId))); 345151937Sjkim 346167802Sjkim if (MutexId > ACPI_MAX_MUTEX) 347151937Sjkim { 348151937Sjkim return (AE_BAD_PARAMETER); 349151937Sjkim } 350151937Sjkim 351151937Sjkim /* 352151937Sjkim * Mutex must be acquired in order to release it! 353151937Sjkim */ 354151937Sjkim if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED) 355151937Sjkim { 356167802Sjkim ACPI_ERROR ((AE_INFO, 357204773Sjkim "Mutex [0x%X] is not acquired, cannot release", MutexId)); 358151937Sjkim 359151937Sjkim return (AE_NOT_ACQUIRED); 360151937Sjkim } 361151937Sjkim 362151937Sjkim#ifdef ACPI_MUTEX_DEBUG 363151937Sjkim { 364151937Sjkim UINT32 i; 365151937Sjkim /* 366151937Sjkim * Mutex debug code, for internal debugging only. 367151937Sjkim * 368241973Sjkim * Deadlock prevention. Check if this thread owns any mutexes of value 369241973Sjkim * greater than this one. If so, the thread has violated the mutex 370241973Sjkim * ordering rule. This indicates a coding error somewhere in 371151937Sjkim * the ACPI subsystem code. 372151937Sjkim */ 373193267Sjkim for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 374151937Sjkim { 375228110Sjkim if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ()) 376151937Sjkim { 377151937Sjkim if (i == MutexId) 378151937Sjkim { 379151937Sjkim continue; 380151937Sjkim } 381151937Sjkim 382167802Sjkim ACPI_ERROR ((AE_INFO, 383167802Sjkim "Invalid release order: owns [%s], releasing [%s]", 384151937Sjkim AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); 385151937Sjkim 386151937Sjkim return (AE_RELEASE_DEADLOCK); 387151937Sjkim } 388151937Sjkim } 389151937Sjkim } 390151937Sjkim#endif 391151937Sjkim 392151937Sjkim /* Mark unlocked FIRST */ 393151937Sjkim 394151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 395151937Sjkim 396167802Sjkim AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 397167802Sjkim return (AE_OK); 398151937Sjkim} 399