1151937Sjkim/******************************************************************************* 2151937Sjkim * 3151937Sjkim * Module Name: utmutex - local mutex support 4151937Sjkim * 5151937Sjkim ******************************************************************************/ 6151937Sjkim 7217365Sjkim/* 8281075Sdim * Copyright (C) 2000 - 2015, 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 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 46151937Sjkim 47151937Sjkim#define _COMPONENT ACPI_UTILITIES 48151937Sjkim ACPI_MODULE_NAME ("utmutex") 49151937Sjkim 50151937Sjkim/* Local prototypes */ 51151937Sjkim 52151937Sjkimstatic ACPI_STATUS 53151937SjkimAcpiUtCreateMutex ( 54151937Sjkim ACPI_MUTEX_HANDLE MutexId); 55151937Sjkim 56202771Sjkimstatic void 57151937SjkimAcpiUtDeleteMutex ( 58151937Sjkim ACPI_MUTEX_HANDLE MutexId); 59151937Sjkim 60151937Sjkim 61151937Sjkim/******************************************************************************* 62151937Sjkim * 63151937Sjkim * FUNCTION: AcpiUtMutexInitialize 64151937Sjkim * 65151937Sjkim * PARAMETERS: None. 66151937Sjkim * 67151937Sjkim * RETURN: Status 68151937Sjkim * 69193267Sjkim * DESCRIPTION: Create the system mutex objects. This includes mutexes, 70193267Sjkim * spin locks, and reader/writer locks. 71151937Sjkim * 72151937Sjkim ******************************************************************************/ 73151937Sjkim 74151937SjkimACPI_STATUS 75151937SjkimAcpiUtMutexInitialize ( 76151937Sjkim void) 77151937Sjkim{ 78151937Sjkim UINT32 i; 79151937Sjkim ACPI_STATUS Status; 80151937Sjkim 81151937Sjkim 82167802Sjkim ACPI_FUNCTION_TRACE (UtMutexInitialize); 83151937Sjkim 84151937Sjkim 85193267Sjkim /* Create each of the predefined mutex objects */ 86193267Sjkim 87167802Sjkim for (i = 0; i < ACPI_NUM_MUTEX; i++) 88151937Sjkim { 89151937Sjkim Status = AcpiUtCreateMutex (i); 90151937Sjkim if (ACPI_FAILURE (Status)) 91151937Sjkim { 92151937Sjkim return_ACPI_STATUS (Status); 93151937Sjkim } 94151937Sjkim } 95151937Sjkim 96249112Sjkim /* Create the spinlocks for use at interrupt level or for speed */ 97167802Sjkim 98151937Sjkim Status = AcpiOsCreateLock (&AcpiGbl_GpeLock); 99167802Sjkim if (ACPI_FAILURE (Status)) 100167802Sjkim { 101167802Sjkim return_ACPI_STATUS (Status); 102167802Sjkim } 103167802Sjkim 104167802Sjkim Status = AcpiOsCreateLock (&AcpiGbl_HardwareLock); 105193267Sjkim if (ACPI_FAILURE (Status)) 106193267Sjkim { 107193267Sjkim return_ACPI_STATUS (Status); 108193267Sjkim } 109193267Sjkim 110249112Sjkim Status = AcpiOsCreateLock (&AcpiGbl_ReferenceCountLock); 111249112Sjkim if (ACPI_FAILURE (Status)) 112249112Sjkim { 113249112Sjkim return_ACPI_STATUS (Status); 114249112Sjkim } 115249112Sjkim 116210976Sjkim /* Mutex for _OSI support */ 117249112Sjkim 118210976Sjkim Status = AcpiOsCreateMutex (&AcpiGbl_OsiMutex); 119210976Sjkim if (ACPI_FAILURE (Status)) 120210976Sjkim { 121210976Sjkim return_ACPI_STATUS (Status); 122210976Sjkim } 123210976Sjkim 124193267Sjkim /* Create the reader/writer lock for namespace access */ 125193267Sjkim 126193267Sjkim Status = AcpiUtCreateRwLock (&AcpiGbl_NamespaceRwLock); 127151937Sjkim return_ACPI_STATUS (Status); 128151937Sjkim} 129151937Sjkim 130151937Sjkim 131151937Sjkim/******************************************************************************* 132151937Sjkim * 133151937Sjkim * FUNCTION: AcpiUtMutexTerminate 134151937Sjkim * 135151937Sjkim * PARAMETERS: None. 136151937Sjkim * 137151937Sjkim * RETURN: None. 138151937Sjkim * 139193267Sjkim * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, 140193267Sjkim * spin locks, and reader/writer locks. 141151937Sjkim * 142151937Sjkim ******************************************************************************/ 143151937Sjkim 144151937Sjkimvoid 145151937SjkimAcpiUtMutexTerminate ( 146151937Sjkim void) 147151937Sjkim{ 148151937Sjkim UINT32 i; 149151937Sjkim 150151937Sjkim 151167802Sjkim ACPI_FUNCTION_TRACE (UtMutexTerminate); 152151937Sjkim 153151937Sjkim 154193267Sjkim /* Delete each predefined mutex object */ 155193267Sjkim 156167802Sjkim for (i = 0; i < ACPI_NUM_MUTEX; i++) 157151937Sjkim { 158202771Sjkim AcpiUtDeleteMutex (i); 159151937Sjkim } 160151937Sjkim 161210976Sjkim AcpiOsDeleteMutex (AcpiGbl_OsiMutex); 162210976Sjkim 163167802Sjkim /* Delete the spinlocks */ 164167802Sjkim 165151937Sjkim AcpiOsDeleteLock (AcpiGbl_GpeLock); 166167802Sjkim AcpiOsDeleteLock (AcpiGbl_HardwareLock); 167249112Sjkim AcpiOsDeleteLock (AcpiGbl_ReferenceCountLock); 168193267Sjkim 169193267Sjkim /* Delete the reader/writer lock */ 170193267Sjkim 171193267Sjkim AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock); 172151937Sjkim return_VOID; 173151937Sjkim} 174151937Sjkim 175151937Sjkim 176151937Sjkim/******************************************************************************* 177151937Sjkim * 178151937Sjkim * FUNCTION: AcpiUtCreateMutex 179151937Sjkim * 180151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be created 181151937Sjkim * 182151937Sjkim * RETURN: Status 183151937Sjkim * 184151937Sjkim * DESCRIPTION: Create a mutex object. 185151937Sjkim * 186151937Sjkim ******************************************************************************/ 187151937Sjkim 188151937Sjkimstatic ACPI_STATUS 189151937SjkimAcpiUtCreateMutex ( 190151937Sjkim ACPI_MUTEX_HANDLE MutexId) 191151937Sjkim{ 192151937Sjkim ACPI_STATUS Status = AE_OK; 193151937Sjkim 194151937Sjkim 195167802Sjkim ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId); 196151937Sjkim 197151937Sjkim 198151937Sjkim if (!AcpiGbl_MutexInfo[MutexId].Mutex) 199151937Sjkim { 200167802Sjkim Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex); 201151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 202151937Sjkim AcpiGbl_MutexInfo[MutexId].UseCount = 0; 203151937Sjkim } 204151937Sjkim 205151937Sjkim return_ACPI_STATUS (Status); 206151937Sjkim} 207151937Sjkim 208151937Sjkim 209151937Sjkim/******************************************************************************* 210151937Sjkim * 211151937Sjkim * FUNCTION: AcpiUtDeleteMutex 212151937Sjkim * 213151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be deleted 214151937Sjkim * 215151937Sjkim * RETURN: Status 216151937Sjkim * 217151937Sjkim * DESCRIPTION: Delete a mutex object. 218151937Sjkim * 219151937Sjkim ******************************************************************************/ 220151937Sjkim 221202771Sjkimstatic void 222151937SjkimAcpiUtDeleteMutex ( 223151937Sjkim ACPI_MUTEX_HANDLE MutexId) 224151937Sjkim{ 225151937Sjkim 226167802Sjkim ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId); 227151937Sjkim 228151937Sjkim 229167802Sjkim AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 230151937Sjkim 231151937Sjkim AcpiGbl_MutexInfo[MutexId].Mutex = NULL; 232151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 233241973Sjkim 234241973Sjkim return_VOID; 235151937Sjkim} 236151937Sjkim 237151937Sjkim 238151937Sjkim/******************************************************************************* 239151937Sjkim * 240151937Sjkim * FUNCTION: AcpiUtAcquireMutex 241151937Sjkim * 242151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be acquired 243151937Sjkim * 244151937Sjkim * RETURN: Status 245151937Sjkim * 246151937Sjkim * DESCRIPTION: Acquire a mutex object. 247151937Sjkim * 248151937Sjkim ******************************************************************************/ 249151937Sjkim 250151937SjkimACPI_STATUS 251151937SjkimAcpiUtAcquireMutex ( 252151937Sjkim ACPI_MUTEX_HANDLE MutexId) 253151937Sjkim{ 254151937Sjkim ACPI_STATUS Status; 255167802Sjkim ACPI_THREAD_ID ThisThreadId; 256151937Sjkim 257151937Sjkim 258167802Sjkim ACPI_FUNCTION_NAME (UtAcquireMutex); 259151937Sjkim 260151937Sjkim 261167802Sjkim if (MutexId > ACPI_MAX_MUTEX) 262151937Sjkim { 263151937Sjkim return (AE_BAD_PARAMETER); 264151937Sjkim } 265151937Sjkim 266151937Sjkim ThisThreadId = AcpiOsGetThreadId (); 267151937Sjkim 268151937Sjkim#ifdef ACPI_MUTEX_DEBUG 269151937Sjkim { 270151937Sjkim UINT32 i; 271151937Sjkim /* 272151937Sjkim * Mutex debug code, for internal debugging only. 273151937Sjkim * 274241973Sjkim * Deadlock prevention. Check if this thread owns any mutexes of value 275241973Sjkim * greater than or equal to this one. If so, the thread has violated 276241973Sjkim * the mutex ordering rule. This indicates a coding error somewhere in 277151937Sjkim * the ACPI subsystem code. 278151937Sjkim */ 279193267Sjkim for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 280151937Sjkim { 281151937Sjkim if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) 282151937Sjkim { 283151937Sjkim if (i == MutexId) 284151937Sjkim { 285167802Sjkim ACPI_ERROR ((AE_INFO, 286212761Sjkim "Mutex [%s] already acquired by this thread [%u]", 287193267Sjkim AcpiUtGetMutexName (MutexId), 288212761Sjkim (UINT32) ThisThreadId)); 289151937Sjkim 290151937Sjkim return (AE_ALREADY_ACQUIRED); 291151937Sjkim } 292151937Sjkim 293167802Sjkim ACPI_ERROR ((AE_INFO, 294212761Sjkim "Invalid acquire order: Thread %u owns [%s], wants [%s]", 295212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (i), 296151937Sjkim AcpiUtGetMutexName (MutexId))); 297151937Sjkim 298151937Sjkim return (AE_ACQUIRE_DEADLOCK); 299151937Sjkim } 300151937Sjkim } 301151937Sjkim } 302151937Sjkim#endif 303151937Sjkim 304151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 305212761Sjkim "Thread %u attempting to acquire Mutex [%s]\n", 306212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 307151937Sjkim 308167802Sjkim Status = AcpiOsAcquireMutex (AcpiGbl_MutexInfo[MutexId].Mutex, 309167802Sjkim ACPI_WAIT_FOREVER); 310151937Sjkim if (ACPI_SUCCESS (Status)) 311151937Sjkim { 312212761Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u acquired Mutex [%s]\n", 313212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 314151937Sjkim 315151937Sjkim AcpiGbl_MutexInfo[MutexId].UseCount++; 316151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId; 317151937Sjkim } 318151937Sjkim else 319151937Sjkim { 320167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 321212761Sjkim "Thread %u could not acquire Mutex [0x%X]", 322212761Sjkim (UINT32) ThisThreadId, MutexId)); 323151937Sjkim } 324151937Sjkim 325151937Sjkim return (Status); 326151937Sjkim} 327151937Sjkim 328151937Sjkim 329151937Sjkim/******************************************************************************* 330151937Sjkim * 331151937Sjkim * FUNCTION: AcpiUtReleaseMutex 332151937Sjkim * 333151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be released 334151937Sjkim * 335151937Sjkim * RETURN: Status 336151937Sjkim * 337151937Sjkim * DESCRIPTION: Release a mutex object. 338151937Sjkim * 339151937Sjkim ******************************************************************************/ 340151937Sjkim 341151937SjkimACPI_STATUS 342151937SjkimAcpiUtReleaseMutex ( 343151937Sjkim ACPI_MUTEX_HANDLE MutexId) 344151937Sjkim{ 345167802Sjkim ACPI_FUNCTION_NAME (UtReleaseMutex); 346151937Sjkim 347241973Sjkim 348212761Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", 349228110Sjkim (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId))); 350151937Sjkim 351167802Sjkim if (MutexId > ACPI_MAX_MUTEX) 352151937Sjkim { 353151937Sjkim return (AE_BAD_PARAMETER); 354151937Sjkim } 355151937Sjkim 356151937Sjkim /* 357151937Sjkim * Mutex must be acquired in order to release it! 358151937Sjkim */ 359151937Sjkim if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED) 360151937Sjkim { 361167802Sjkim ACPI_ERROR ((AE_INFO, 362204773Sjkim "Mutex [0x%X] is not acquired, cannot release", MutexId)); 363151937Sjkim 364151937Sjkim return (AE_NOT_ACQUIRED); 365151937Sjkim } 366151937Sjkim 367151937Sjkim#ifdef ACPI_MUTEX_DEBUG 368151937Sjkim { 369151937Sjkim UINT32 i; 370151937Sjkim /* 371151937Sjkim * Mutex debug code, for internal debugging only. 372151937Sjkim * 373241973Sjkim * Deadlock prevention. Check if this thread owns any mutexes of value 374241973Sjkim * greater than this one. If so, the thread has violated the mutex 375241973Sjkim * ordering rule. This indicates a coding error somewhere in 376151937Sjkim * the ACPI subsystem code. 377151937Sjkim */ 378193267Sjkim for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 379151937Sjkim { 380228110Sjkim if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ()) 381151937Sjkim { 382151937Sjkim if (i == MutexId) 383151937Sjkim { 384151937Sjkim continue; 385151937Sjkim } 386151937Sjkim 387167802Sjkim ACPI_ERROR ((AE_INFO, 388167802Sjkim "Invalid release order: owns [%s], releasing [%s]", 389151937Sjkim AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); 390151937Sjkim 391151937Sjkim return (AE_RELEASE_DEADLOCK); 392151937Sjkim } 393151937Sjkim } 394151937Sjkim } 395151937Sjkim#endif 396151937Sjkim 397151937Sjkim /* Mark unlocked FIRST */ 398151937Sjkim 399151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 400151937Sjkim 401167802Sjkim AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 402167802Sjkim return (AE_OK); 403151937Sjkim} 404