1151937Sjkim/******************************************************************************* 2151937Sjkim * 3151937Sjkim * Module Name: utmutex - local mutex support 4151937Sjkim * 5151937Sjkim ******************************************************************************/ 6151937Sjkim 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, 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); 127306536Sjkim if (ACPI_FAILURE (Status)) 128306536Sjkim { 129306536Sjkim return_ACPI_STATUS (Status); 130306536Sjkim } 131306536Sjkim 132306536Sjkim#ifdef ACPI_DEBUGGER 133306536Sjkim 134306536Sjkim /* Debugger Support */ 135306536Sjkim 136306536Sjkim Status = AcpiOsCreateMutex (&AcpiGbl_DbCommandReady); 137306536Sjkim if (ACPI_FAILURE (Status)) 138306536Sjkim { 139306536Sjkim return_ACPI_STATUS (Status); 140306536Sjkim } 141306536Sjkim 142306536Sjkim Status = AcpiOsCreateMutex (&AcpiGbl_DbCommandComplete); 143306536Sjkim#endif 144306536Sjkim 145151937Sjkim return_ACPI_STATUS (Status); 146151937Sjkim} 147151937Sjkim 148151937Sjkim 149151937Sjkim/******************************************************************************* 150151937Sjkim * 151151937Sjkim * FUNCTION: AcpiUtMutexTerminate 152151937Sjkim * 153151937Sjkim * PARAMETERS: None. 154151937Sjkim * 155151937Sjkim * RETURN: None. 156151937Sjkim * 157193267Sjkim * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, 158193267Sjkim * spin locks, and reader/writer locks. 159151937Sjkim * 160151937Sjkim ******************************************************************************/ 161151937Sjkim 162151937Sjkimvoid 163151937SjkimAcpiUtMutexTerminate ( 164151937Sjkim void) 165151937Sjkim{ 166151937Sjkim UINT32 i; 167151937Sjkim 168151937Sjkim 169167802Sjkim ACPI_FUNCTION_TRACE (UtMutexTerminate); 170151937Sjkim 171151937Sjkim 172193267Sjkim /* Delete each predefined mutex object */ 173193267Sjkim 174167802Sjkim for (i = 0; i < ACPI_NUM_MUTEX; i++) 175151937Sjkim { 176202771Sjkim AcpiUtDeleteMutex (i); 177151937Sjkim } 178151937Sjkim 179210976Sjkim AcpiOsDeleteMutex (AcpiGbl_OsiMutex); 180210976Sjkim 181167802Sjkim /* Delete the spinlocks */ 182167802Sjkim 183151937Sjkim AcpiOsDeleteLock (AcpiGbl_GpeLock); 184167802Sjkim AcpiOsDeleteLock (AcpiGbl_HardwareLock); 185249112Sjkim AcpiOsDeleteLock (AcpiGbl_ReferenceCountLock); 186193267Sjkim 187193267Sjkim /* Delete the reader/writer lock */ 188193267Sjkim 189193267Sjkim AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock); 190306536Sjkim 191306536Sjkim#ifdef ACPI_DEBUGGER 192306536Sjkim AcpiOsDeleteMutex (AcpiGbl_DbCommandReady); 193306536Sjkim AcpiOsDeleteMutex (AcpiGbl_DbCommandComplete); 194306536Sjkim#endif 195306536Sjkim 196151937Sjkim return_VOID; 197151937Sjkim} 198151937Sjkim 199151937Sjkim 200151937Sjkim/******************************************************************************* 201151937Sjkim * 202151937Sjkim * FUNCTION: AcpiUtCreateMutex 203151937Sjkim * 204151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be created 205151937Sjkim * 206151937Sjkim * RETURN: Status 207151937Sjkim * 208151937Sjkim * DESCRIPTION: Create a mutex object. 209151937Sjkim * 210151937Sjkim ******************************************************************************/ 211151937Sjkim 212151937Sjkimstatic ACPI_STATUS 213151937SjkimAcpiUtCreateMutex ( 214151937Sjkim ACPI_MUTEX_HANDLE MutexId) 215151937Sjkim{ 216151937Sjkim ACPI_STATUS Status = AE_OK; 217151937Sjkim 218151937Sjkim 219167802Sjkim ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId); 220151937Sjkim 221151937Sjkim 222151937Sjkim if (!AcpiGbl_MutexInfo[MutexId].Mutex) 223151937Sjkim { 224167802Sjkim Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex); 225151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 226151937Sjkim AcpiGbl_MutexInfo[MutexId].UseCount = 0; 227151937Sjkim } 228151937Sjkim 229151937Sjkim return_ACPI_STATUS (Status); 230151937Sjkim} 231151937Sjkim 232151937Sjkim 233151937Sjkim/******************************************************************************* 234151937Sjkim * 235151937Sjkim * FUNCTION: AcpiUtDeleteMutex 236151937Sjkim * 237151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be deleted 238151937Sjkim * 239151937Sjkim * RETURN: Status 240151937Sjkim * 241151937Sjkim * DESCRIPTION: Delete a mutex object. 242151937Sjkim * 243151937Sjkim ******************************************************************************/ 244151937Sjkim 245202771Sjkimstatic void 246151937SjkimAcpiUtDeleteMutex ( 247151937Sjkim ACPI_MUTEX_HANDLE MutexId) 248151937Sjkim{ 249151937Sjkim 250167802Sjkim ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId); 251151937Sjkim 252151937Sjkim 253167802Sjkim AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 254151937Sjkim 255151937Sjkim AcpiGbl_MutexInfo[MutexId].Mutex = NULL; 256151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 257241973Sjkim 258241973Sjkim return_VOID; 259151937Sjkim} 260151937Sjkim 261151937Sjkim 262151937Sjkim/******************************************************************************* 263151937Sjkim * 264151937Sjkim * FUNCTION: AcpiUtAcquireMutex 265151937Sjkim * 266151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be acquired 267151937Sjkim * 268151937Sjkim * RETURN: Status 269151937Sjkim * 270151937Sjkim * DESCRIPTION: Acquire a mutex object. 271151937Sjkim * 272151937Sjkim ******************************************************************************/ 273151937Sjkim 274151937SjkimACPI_STATUS 275151937SjkimAcpiUtAcquireMutex ( 276151937Sjkim ACPI_MUTEX_HANDLE MutexId) 277151937Sjkim{ 278151937Sjkim ACPI_STATUS Status; 279167802Sjkim ACPI_THREAD_ID ThisThreadId; 280151937Sjkim 281151937Sjkim 282167802Sjkim ACPI_FUNCTION_NAME (UtAcquireMutex); 283151937Sjkim 284151937Sjkim 285167802Sjkim if (MutexId > ACPI_MAX_MUTEX) 286151937Sjkim { 287151937Sjkim return (AE_BAD_PARAMETER); 288151937Sjkim } 289151937Sjkim 290151937Sjkim ThisThreadId = AcpiOsGetThreadId (); 291151937Sjkim 292151937Sjkim#ifdef ACPI_MUTEX_DEBUG 293151937Sjkim { 294151937Sjkim UINT32 i; 295151937Sjkim /* 296151937Sjkim * Mutex debug code, for internal debugging only. 297151937Sjkim * 298241973Sjkim * Deadlock prevention. Check if this thread owns any mutexes of value 299241973Sjkim * greater than or equal to this one. If so, the thread has violated 300241973Sjkim * the mutex ordering rule. This indicates a coding error somewhere in 301151937Sjkim * the ACPI subsystem code. 302151937Sjkim */ 303193267Sjkim for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 304151937Sjkim { 305151937Sjkim if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) 306151937Sjkim { 307151937Sjkim if (i == MutexId) 308151937Sjkim { 309167802Sjkim ACPI_ERROR ((AE_INFO, 310212761Sjkim "Mutex [%s] already acquired by this thread [%u]", 311193267Sjkim AcpiUtGetMutexName (MutexId), 312212761Sjkim (UINT32) ThisThreadId)); 313151937Sjkim 314151937Sjkim return (AE_ALREADY_ACQUIRED); 315151937Sjkim } 316151937Sjkim 317167802Sjkim ACPI_ERROR ((AE_INFO, 318212761Sjkim "Invalid acquire order: Thread %u owns [%s], wants [%s]", 319212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (i), 320151937Sjkim AcpiUtGetMutexName (MutexId))); 321151937Sjkim 322151937Sjkim return (AE_ACQUIRE_DEADLOCK); 323151937Sjkim } 324151937Sjkim } 325151937Sjkim } 326151937Sjkim#endif 327151937Sjkim 328151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 329212761Sjkim "Thread %u attempting to acquire Mutex [%s]\n", 330212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 331151937Sjkim 332306536Sjkim Status = AcpiOsAcquireMutex ( 333306536Sjkim AcpiGbl_MutexInfo[MutexId].Mutex, ACPI_WAIT_FOREVER); 334151937Sjkim if (ACPI_SUCCESS (Status)) 335151937Sjkim { 336306536Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 337306536Sjkim "Thread %u acquired Mutex [%s]\n", 338212761Sjkim (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 339151937Sjkim 340151937Sjkim AcpiGbl_MutexInfo[MutexId].UseCount++; 341151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId; 342151937Sjkim } 343151937Sjkim else 344151937Sjkim { 345167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 346212761Sjkim "Thread %u could not acquire Mutex [0x%X]", 347212761Sjkim (UINT32) ThisThreadId, MutexId)); 348151937Sjkim } 349151937Sjkim 350151937Sjkim return (Status); 351151937Sjkim} 352151937Sjkim 353151937Sjkim 354151937Sjkim/******************************************************************************* 355151937Sjkim * 356151937Sjkim * FUNCTION: AcpiUtReleaseMutex 357151937Sjkim * 358151937Sjkim * PARAMETERS: MutexID - ID of the mutex to be released 359151937Sjkim * 360151937Sjkim * RETURN: Status 361151937Sjkim * 362151937Sjkim * DESCRIPTION: Release a mutex object. 363151937Sjkim * 364151937Sjkim ******************************************************************************/ 365151937Sjkim 366151937SjkimACPI_STATUS 367151937SjkimAcpiUtReleaseMutex ( 368151937Sjkim ACPI_MUTEX_HANDLE MutexId) 369151937Sjkim{ 370167802Sjkim ACPI_FUNCTION_NAME (UtReleaseMutex); 371151937Sjkim 372241973Sjkim 373212761Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", 374228110Sjkim (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId))); 375151937Sjkim 376167802Sjkim if (MutexId > ACPI_MAX_MUTEX) 377151937Sjkim { 378151937Sjkim return (AE_BAD_PARAMETER); 379151937Sjkim } 380151937Sjkim 381151937Sjkim /* 382151937Sjkim * Mutex must be acquired in order to release it! 383151937Sjkim */ 384151937Sjkim if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED) 385151937Sjkim { 386167802Sjkim ACPI_ERROR ((AE_INFO, 387204773Sjkim "Mutex [0x%X] is not acquired, cannot release", MutexId)); 388151937Sjkim 389151937Sjkim return (AE_NOT_ACQUIRED); 390151937Sjkim } 391151937Sjkim 392151937Sjkim#ifdef ACPI_MUTEX_DEBUG 393151937Sjkim { 394151937Sjkim UINT32 i; 395151937Sjkim /* 396151937Sjkim * Mutex debug code, for internal debugging only. 397151937Sjkim * 398241973Sjkim * Deadlock prevention. Check if this thread owns any mutexes of value 399241973Sjkim * greater than this one. If so, the thread has violated the mutex 400241973Sjkim * ordering rule. This indicates a coding error somewhere in 401151937Sjkim * the ACPI subsystem code. 402151937Sjkim */ 403193267Sjkim for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 404151937Sjkim { 405228110Sjkim if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ()) 406151937Sjkim { 407151937Sjkim if (i == MutexId) 408151937Sjkim { 409151937Sjkim continue; 410151937Sjkim } 411151937Sjkim 412167802Sjkim ACPI_ERROR ((AE_INFO, 413167802Sjkim "Invalid release order: owns [%s], releasing [%s]", 414151937Sjkim AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); 415151937Sjkim 416151937Sjkim return (AE_RELEASE_DEADLOCK); 417151937Sjkim } 418151937Sjkim } 419151937Sjkim } 420151937Sjkim#endif 421151937Sjkim 422151937Sjkim /* Mark unlocked FIRST */ 423151937Sjkim 424151937Sjkim AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 425151937Sjkim 426167802Sjkim AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 427167802Sjkim return (AE_OK); 428151937Sjkim} 429