177422Smsmith/****************************************************************************** 277422Smsmith * 377422Smsmith * Module Name: exmutex - ASL Mutex Acquire/Release functions 477422Smsmith * 577422Smsmith *****************************************************************************/ 677422Smsmith 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 977422Smsmith * All rights reserved. 1077422Smsmith * 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. 2577422Smsmith * 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. 2977422Smsmith * 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 */ 4377422Smsmith 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 46193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 47193341Sjkim#include <contrib/dev/acpica/include/acevents.h> 4877422Smsmith 4977422Smsmith#define _COMPONENT ACPI_EXECUTER 5091116Smsmith ACPI_MODULE_NAME ("exmutex") 5177422Smsmith 52151937Sjkim/* Local prototypes */ 5377422Smsmith 54151937Sjkimstatic void 55151937SjkimAcpiExLinkMutex ( 56151937Sjkim ACPI_OPERAND_OBJECT *ObjDesc, 57151937Sjkim ACPI_THREAD_STATE *Thread); 58151937Sjkim 59151937Sjkim 6077422Smsmith/******************************************************************************* 6177422Smsmith * 6277422Smsmith * FUNCTION: AcpiExUnlinkMutex 6377422Smsmith * 64129684Snjl * PARAMETERS: ObjDesc - The mutex to be unlinked 6577422Smsmith * 66151937Sjkim * RETURN: None 6777422Smsmith * 6877422Smsmith * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list 6977422Smsmith * 7077422Smsmith ******************************************************************************/ 7177422Smsmith 7277422Smsmithvoid 7377422SmsmithAcpiExUnlinkMutex ( 7477422Smsmith ACPI_OPERAND_OBJECT *ObjDesc) 7577422Smsmith{ 7687031Smsmith ACPI_THREAD_STATE *Thread = ObjDesc->Mutex.OwnerThread; 7777422Smsmith 7887031Smsmith 7987031Smsmith if (!Thread) 8087031Smsmith { 8187031Smsmith return; 8287031Smsmith } 8387031Smsmith 84129684Snjl /* Doubly linked list */ 85129684Snjl 8677422Smsmith if (ObjDesc->Mutex.Next) 8777422Smsmith { 8877422Smsmith (ObjDesc->Mutex.Next)->Mutex.Prev = ObjDesc->Mutex.Prev; 8977422Smsmith } 9087031Smsmith 9177422Smsmith if (ObjDesc->Mutex.Prev) 9277422Smsmith { 9377422Smsmith (ObjDesc->Mutex.Prev)->Mutex.Next = ObjDesc->Mutex.Next; 94193267Sjkim 95193267Sjkim /* 96206117Sjkim * Migrate the previous sync level associated with this mutex to 97206117Sjkim * the previous mutex on the list so that it may be preserved. 98206117Sjkim * This handles the case where several mutexes have been acquired 99206117Sjkim * at the same level, but are not released in opposite order. 100193267Sjkim */ 101193267Sjkim (ObjDesc->Mutex.Prev)->Mutex.OriginalSyncLevel = 102193267Sjkim ObjDesc->Mutex.OriginalSyncLevel; 10377422Smsmith } 10487031Smsmith else 10587031Smsmith { 10687031Smsmith Thread->AcquiredMutexList = ObjDesc->Mutex.Next; 10787031Smsmith } 10877422Smsmith} 10977422Smsmith 11077422Smsmith 11177422Smsmith/******************************************************************************* 11277422Smsmith * 11377422Smsmith * FUNCTION: AcpiExLinkMutex 11477422Smsmith * 115206117Sjkim * PARAMETERS: ObjDesc - The mutex to be linked 116206117Sjkim * Thread - Current executing thread object 11777422Smsmith * 118151937Sjkim * RETURN: None 11977422Smsmith * 12077422Smsmith * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk 12177422Smsmith * 12277422Smsmith ******************************************************************************/ 12377422Smsmith 124151937Sjkimstatic void 12577422SmsmithAcpiExLinkMutex ( 12677422Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 12787031Smsmith ACPI_THREAD_STATE *Thread) 12877422Smsmith{ 12987031Smsmith ACPI_OPERAND_OBJECT *ListHead; 13077422Smsmith 13187031Smsmith 13287031Smsmith ListHead = Thread->AcquiredMutexList; 13387031Smsmith 13477422Smsmith /* This object will be the first object in the list */ 13577422Smsmith 13687031Smsmith ObjDesc->Mutex.Prev = NULL; 13787031Smsmith ObjDesc->Mutex.Next = ListHead; 13877422Smsmith 13977422Smsmith /* Update old first object to point back to this object */ 14077422Smsmith 14187031Smsmith if (ListHead) 14277422Smsmith { 14387031Smsmith ListHead->Mutex.Prev = ObjDesc; 14477422Smsmith } 14577422Smsmith 14677422Smsmith /* Update list head */ 14777422Smsmith 14887031Smsmith Thread->AcquiredMutexList = ObjDesc; 14977422Smsmith} 15077422Smsmith 15177422Smsmith 15277422Smsmith/******************************************************************************* 15377422Smsmith * 154167802Sjkim * FUNCTION: AcpiExAcquireMutexObject 155167802Sjkim * 156206117Sjkim * PARAMETERS: Timeout - Timeout in milliseconds 157167802Sjkim * ObjDesc - Mutex object 158206117Sjkim * ThreadId - Current thread state 159167802Sjkim * 160167802Sjkim * RETURN: Status 161167802Sjkim * 162167802Sjkim * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common 163167802Sjkim * path that supports multiple acquires by the same thread. 164167802Sjkim * 165167802Sjkim * MUTEX: Interpreter must be locked 166167802Sjkim * 167167802Sjkim * NOTE: This interface is called from three places: 168167802Sjkim * 1) From AcpiExAcquireMutex, via an AML Acquire() operator 169167802Sjkim * 2) From AcpiExAcquireGlobalLock when an AML Field access requires the 170167802Sjkim * global lock 171167802Sjkim * 3) From the external interface, AcpiAcquireGlobalLock 172167802Sjkim * 173167802Sjkim ******************************************************************************/ 174167802Sjkim 175167802SjkimACPI_STATUS 176167802SjkimAcpiExAcquireMutexObject ( 177167802Sjkim UINT16 Timeout, 178167802Sjkim ACPI_OPERAND_OBJECT *ObjDesc, 179167802Sjkim ACPI_THREAD_ID ThreadId) 180167802Sjkim{ 181167802Sjkim ACPI_STATUS Status; 182167802Sjkim 183167802Sjkim 184167802Sjkim ACPI_FUNCTION_TRACE_PTR (ExAcquireMutexObject, ObjDesc); 185167802Sjkim 186167802Sjkim 187167802Sjkim if (!ObjDesc) 188167802Sjkim { 189167802Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 190167802Sjkim } 191167802Sjkim 192167802Sjkim /* Support for multiple acquires by the owning thread */ 193167802Sjkim 194167802Sjkim if (ObjDesc->Mutex.ThreadId == ThreadId) 195167802Sjkim { 196167802Sjkim /* 197167802Sjkim * The mutex is already owned by this thread, just increment the 198167802Sjkim * acquisition depth 199167802Sjkim */ 200167802Sjkim ObjDesc->Mutex.AcquisitionDepth++; 201167802Sjkim return_ACPI_STATUS (AE_OK); 202167802Sjkim } 203167802Sjkim 204167802Sjkim /* Acquire the mutex, wait if necessary. Special case for Global Lock */ 205167802Sjkim 206167802Sjkim if (ObjDesc == AcpiGbl_GlobalLockMutex) 207167802Sjkim { 208167802Sjkim Status = AcpiEvAcquireGlobalLock (Timeout); 209167802Sjkim } 210167802Sjkim else 211167802Sjkim { 212306536Sjkim Status = AcpiExSystemWaitMutex (ObjDesc->Mutex.OsMutex, Timeout); 213167802Sjkim } 214167802Sjkim 215167802Sjkim if (ACPI_FAILURE (Status)) 216167802Sjkim { 217167802Sjkim /* Includes failure from a timeout on TimeDesc */ 218167802Sjkim 219167802Sjkim return_ACPI_STATUS (Status); 220167802Sjkim } 221167802Sjkim 222167802Sjkim /* Acquired the mutex: update mutex object */ 223167802Sjkim 224167802Sjkim ObjDesc->Mutex.ThreadId = ThreadId; 225167802Sjkim ObjDesc->Mutex.AcquisitionDepth = 1; 226167802Sjkim ObjDesc->Mutex.OriginalSyncLevel = 0; 227167802Sjkim ObjDesc->Mutex.OwnerThread = NULL; /* Used only for AML Acquire() */ 228167802Sjkim 229167802Sjkim return_ACPI_STATUS (AE_OK); 230167802Sjkim} 231167802Sjkim 232167802Sjkim 233167802Sjkim/******************************************************************************* 234167802Sjkim * 23577422Smsmith * FUNCTION: AcpiExAcquireMutex 23677422Smsmith * 237151937Sjkim * PARAMETERS: TimeDesc - Timeout integer 238151937Sjkim * ObjDesc - Mutex object 239151937Sjkim * WalkState - Current method execution state 24077422Smsmith * 24177422Smsmith * RETURN: Status 24277422Smsmith * 24377422Smsmith * DESCRIPTION: Acquire an AML mutex 24477422Smsmith * 24577422Smsmith ******************************************************************************/ 24677422Smsmith 24777422SmsmithACPI_STATUS 24877422SmsmithAcpiExAcquireMutex ( 24977422Smsmith ACPI_OPERAND_OBJECT *TimeDesc, 25077422Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 25177422Smsmith ACPI_WALK_STATE *WalkState) 25277422Smsmith{ 25377422Smsmith ACPI_STATUS Status; 25477422Smsmith 25577422Smsmith 256167802Sjkim ACPI_FUNCTION_TRACE_PTR (ExAcquireMutex, ObjDesc); 25777422Smsmith 258107325Siwasaki 25977422Smsmith if (!ObjDesc) 26077422Smsmith { 26177422Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 26277422Smsmith } 26377422Smsmith 264206117Sjkim /* Must have a valid thread state struct */ 265107325Siwasaki 266107325Siwasaki if (!WalkState->Thread) 267107325Siwasaki { 268206117Sjkim ACPI_ERROR ((AE_INFO, 269206117Sjkim "Cannot acquire Mutex [%4.4s], null thread info", 270151937Sjkim AcpiUtGetNodeName (ObjDesc->Mutex.Node))); 271107325Siwasaki return_ACPI_STATUS (AE_AML_INTERNAL); 272107325Siwasaki } 273107325Siwasaki 27477422Smsmith /* 275306536Sjkim * Current sync level must be less than or equal to the sync level 276306536Sjkim * of the mutex. This mechanism provides some deadlock prevention. 27777422Smsmith */ 27887031Smsmith if (WalkState->Thread->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel) 27977422Smsmith { 280167802Sjkim ACPI_ERROR ((AE_INFO, 281306536Sjkim "Cannot acquire Mutex [%4.4s], " 282306536Sjkim "current SyncLevel is too large (%u)", 283167802Sjkim AcpiUtGetNodeName (ObjDesc->Mutex.Node), 284167802Sjkim WalkState->Thread->CurrentSyncLevel)); 28577422Smsmith return_ACPI_STATUS (AE_AML_MUTEX_ORDER); 28677422Smsmith } 28777422Smsmith 288306536Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 289306536Sjkim "Acquiring: Mutex SyncLevel %u, Thread SyncLevel %u, " 290306536Sjkim "Depth %u TID %p\n", 291306536Sjkim ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel, 292306536Sjkim ObjDesc->Mutex.AcquisitionDepth, WalkState->Thread)); 293306536Sjkim 294167802Sjkim Status = AcpiExAcquireMutexObject ((UINT16) TimeDesc->Integer.Value, 295306536Sjkim ObjDesc, WalkState->Thread->ThreadId); 296306536Sjkim 297167802Sjkim if (ACPI_SUCCESS (Status) && ObjDesc->Mutex.AcquisitionDepth == 1) 298127175Snjl { 299167802Sjkim /* Save Thread object, original/current sync levels */ 300107325Siwasaki 301167802Sjkim ObjDesc->Mutex.OwnerThread = WalkState->Thread; 302306536Sjkim ObjDesc->Mutex.OriginalSyncLevel = 303306536Sjkim WalkState->Thread->CurrentSyncLevel; 304306536Sjkim WalkState->Thread->CurrentSyncLevel = 305306536Sjkim ObjDesc->Mutex.SyncLevel; 306167802Sjkim 307167802Sjkim /* Link the mutex to the current thread for force-unlock at method exit */ 308167802Sjkim 309167802Sjkim AcpiExLinkMutex (ObjDesc, WalkState->Thread); 31077422Smsmith } 31177422Smsmith 312306536Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 313306536Sjkim "Acquired: Mutex SyncLevel %u, Thread SyncLevel %u, Depth %u\n", 314306536Sjkim ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel, 315306536Sjkim ObjDesc->Mutex.AcquisitionDepth)); 316306536Sjkim 317167802Sjkim return_ACPI_STATUS (Status); 318167802Sjkim} 31977422Smsmith 320167802Sjkim 321167802Sjkim/******************************************************************************* 322167802Sjkim * 323167802Sjkim * FUNCTION: AcpiExReleaseMutexObject 324167802Sjkim * 325167802Sjkim * PARAMETERS: ObjDesc - The object descriptor for this op 326167802Sjkim * 327167802Sjkim * RETURN: Status 328167802Sjkim * 329167802Sjkim * DESCRIPTION: Release a previously acquired Mutex, low level interface. 330167802Sjkim * Provides a common path that supports multiple releases (after 331167802Sjkim * previous multiple acquires) by the same thread. 332167802Sjkim * 333167802Sjkim * MUTEX: Interpreter must be locked 334167802Sjkim * 335167802Sjkim * NOTE: This interface is called from three places: 336167802Sjkim * 1) From AcpiExReleaseMutex, via an AML Acquire() operator 337167802Sjkim * 2) From AcpiExReleaseGlobalLock when an AML Field access requires the 338167802Sjkim * global lock 339167802Sjkim * 3) From the external interface, AcpiReleaseGlobalLock 340167802Sjkim * 341167802Sjkim ******************************************************************************/ 342167802Sjkim 343167802SjkimACPI_STATUS 344167802SjkimAcpiExReleaseMutexObject ( 345167802Sjkim ACPI_OPERAND_OBJECT *ObjDesc) 346167802Sjkim{ 347167802Sjkim ACPI_STATUS Status = AE_OK; 348167802Sjkim 349167802Sjkim 350167802Sjkim ACPI_FUNCTION_TRACE (ExReleaseMutexObject); 351167802Sjkim 352167802Sjkim 353167802Sjkim if (ObjDesc->Mutex.AcquisitionDepth == 0) 35477422Smsmith { 355241973Sjkim return_ACPI_STATUS (AE_NOT_ACQUIRED); 356167802Sjkim } 35777422Smsmith 358167802Sjkim /* Match multiple Acquires with multiple Releases */ 359167802Sjkim 360167802Sjkim ObjDesc->Mutex.AcquisitionDepth--; 361167802Sjkim if (ObjDesc->Mutex.AcquisitionDepth != 0) 362167802Sjkim { 363167802Sjkim /* Just decrement the depth and return */ 364167802Sjkim 365167802Sjkim return_ACPI_STATUS (AE_OK); 36677422Smsmith } 36777422Smsmith 368167802Sjkim if (ObjDesc->Mutex.OwnerThread) 369167802Sjkim { 370167802Sjkim /* Unlink the mutex from the owner's list */ 37177422Smsmith 372167802Sjkim AcpiExUnlinkMutex (ObjDesc); 373167802Sjkim ObjDesc->Mutex.OwnerThread = NULL; 374167802Sjkim } 37577422Smsmith 376167802Sjkim /* Release the mutex, special case for Global Lock */ 37777422Smsmith 378167802Sjkim if (ObjDesc == AcpiGbl_GlobalLockMutex) 379167802Sjkim { 380167802Sjkim Status = AcpiEvReleaseGlobalLock (); 381167802Sjkim } 382167802Sjkim else 383167802Sjkim { 384167802Sjkim AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex); 385167802Sjkim } 38677422Smsmith 387167802Sjkim /* Clear mutex info */ 38887031Smsmith 389167802Sjkim ObjDesc->Mutex.ThreadId = 0; 390167802Sjkim return_ACPI_STATUS (Status); 39177422Smsmith} 39277422Smsmith 39377422Smsmith 39477422Smsmith/******************************************************************************* 39577422Smsmith * 39677422Smsmith * FUNCTION: AcpiExReleaseMutex 39777422Smsmith * 398129684Snjl * PARAMETERS: ObjDesc - The object descriptor for this op 399151937Sjkim * WalkState - Current method execution state 40077422Smsmith * 40177422Smsmith * RETURN: Status 40277422Smsmith * 40377422Smsmith * DESCRIPTION: Release a previously acquired Mutex. 40477422Smsmith * 40577422Smsmith ******************************************************************************/ 40677422Smsmith 40777422SmsmithACPI_STATUS 40877422SmsmithAcpiExReleaseMutex ( 40977422Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 41077422Smsmith ACPI_WALK_STATE *WalkState) 41177422Smsmith{ 412193267Sjkim UINT8 PreviousSyncLevel; 413204773Sjkim ACPI_THREAD_STATE *OwnerThread; 414306536Sjkim ACPI_STATUS Status = AE_OK; 41577422Smsmith 41677422Smsmith 417167802Sjkim ACPI_FUNCTION_TRACE (ExReleaseMutex); 41877422Smsmith 41977422Smsmith 42077422Smsmith if (!ObjDesc) 42177422Smsmith { 42277422Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 42377422Smsmith } 42477422Smsmith 425204773Sjkim OwnerThread = ObjDesc->Mutex.OwnerThread; 426204773Sjkim 42783174Smsmith /* The mutex must have been previously acquired in order to release it */ 42877422Smsmith 429204773Sjkim if (!OwnerThread) 43077422Smsmith { 431206117Sjkim ACPI_ERROR ((AE_INFO, 432206117Sjkim "Cannot release Mutex [%4.4s], not acquired", 433167802Sjkim AcpiUtGetNodeName (ObjDesc->Mutex.Node))); 43477422Smsmith return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED); 43577422Smsmith } 43677422Smsmith 437200553Sjkim /* Must have a valid thread ID */ 438200553Sjkim 439200553Sjkim if (!WalkState->Thread) 440200553Sjkim { 441206117Sjkim ACPI_ERROR ((AE_INFO, 442206117Sjkim "Cannot release Mutex [%4.4s], null thread info", 443200553Sjkim AcpiUtGetNodeName (ObjDesc->Mutex.Node))); 444200553Sjkim return_ACPI_STATUS (AE_AML_INTERNAL); 445200553Sjkim } 446200553Sjkim 447129684Snjl /* 448127175Snjl * The Mutex is owned, but this thread must be the owner. 449127175Snjl * Special case for Global Lock, any thread can release 450127175Snjl */ 451204773Sjkim if ((OwnerThread->ThreadId != WalkState->Thread->ThreadId) && 452167802Sjkim (ObjDesc != AcpiGbl_GlobalLockMutex)) 45377422Smsmith { 454167802Sjkim ACPI_ERROR ((AE_INFO, 455212761Sjkim "Thread %u cannot release Mutex [%4.4s] acquired by thread %u", 456212761Sjkim (UINT32) WalkState->Thread->ThreadId, 457123315Snjl AcpiUtGetNodeName (ObjDesc->Mutex.Node), 458212761Sjkim (UINT32) OwnerThread->ThreadId)); 45977422Smsmith return_ACPI_STATUS (AE_AML_NOT_OWNER); 46077422Smsmith } 46177422Smsmith 46277422Smsmith /* 463193267Sjkim * The sync level of the mutex must be equal to the current sync level. In 464193267Sjkim * other words, the current level means that at least one mutex at that 465193267Sjkim * level is currently being held. Attempting to release a mutex of a 466193267Sjkim * different level can only mean that the mutex ordering rule is being 467193267Sjkim * violated. This behavior is clarified in ACPI 4.0 specification. 46877422Smsmith */ 469204773Sjkim if (ObjDesc->Mutex.SyncLevel != OwnerThread->CurrentSyncLevel) 47077422Smsmith { 471167802Sjkim ACPI_ERROR ((AE_INFO, 472306536Sjkim "Cannot release Mutex [%4.4s], SyncLevel mismatch: " 473306536Sjkim "mutex %u current %u", 474167802Sjkim AcpiUtGetNodeName (ObjDesc->Mutex.Node), 475167802Sjkim ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel)); 47677422Smsmith return_ACPI_STATUS (AE_AML_MUTEX_ORDER); 47777422Smsmith } 47877422Smsmith 479193267Sjkim /* 480193267Sjkim * Get the previous SyncLevel from the head of the acquired mutex list. 481193267Sjkim * This handles the case where several mutexes at the same level have been 482193267Sjkim * acquired, but are not released in reverse order. 483193267Sjkim */ 484193267Sjkim PreviousSyncLevel = 485204773Sjkim OwnerThread->AcquiredMutexList->Mutex.OriginalSyncLevel; 486193267Sjkim 487306536Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 488306536Sjkim "Releasing: Object SyncLevel %u, Thread SyncLevel %u, " 489306536Sjkim "Prev SyncLevel %u, Depth %u TID %p\n", 490306536Sjkim ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel, 491306536Sjkim PreviousSyncLevel, ObjDesc->Mutex.AcquisitionDepth, 492306536Sjkim WalkState->Thread)); 493306536Sjkim 494167802Sjkim Status = AcpiExReleaseMutexObject (ObjDesc); 495193267Sjkim if (ACPI_FAILURE (Status)) 496193267Sjkim { 497193267Sjkim return_ACPI_STATUS (Status); 498193267Sjkim } 499129684Snjl 500167802Sjkim if (ObjDesc->Mutex.AcquisitionDepth == 0) 50177422Smsmith { 502193267Sjkim /* Restore the previous SyncLevel */ 50377422Smsmith 504204773Sjkim OwnerThread->CurrentSyncLevel = PreviousSyncLevel; 50577422Smsmith } 506206117Sjkim 507306536Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 508306536Sjkim "Released: Object SyncLevel %u, Thread SyncLevel, %u, " 509306536Sjkim "Prev SyncLevel %u, Depth %u\n", 510306536Sjkim ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel, 511306536Sjkim PreviousSyncLevel, ObjDesc->Mutex.AcquisitionDepth)); 512306536Sjkim 51377422Smsmith return_ACPI_STATUS (Status); 51477422Smsmith} 51577422Smsmith 51677422Smsmith 51777422Smsmith/******************************************************************************* 51877422Smsmith * 51977422Smsmith * FUNCTION: AcpiExReleaseAllMutexes 52077422Smsmith * 521206117Sjkim * PARAMETERS: Thread - Current executing thread object 52277422Smsmith * 52377422Smsmith * RETURN: Status 52477422Smsmith * 525151937Sjkim * DESCRIPTION: Release all mutexes held by this thread 52677422Smsmith * 527167802Sjkim * NOTE: This function is called as the thread is exiting the interpreter. 528167802Sjkim * Mutexes are not released when an individual control method is exited, but 529167802Sjkim * only when the parent thread actually exits the interpreter. This allows one 530167802Sjkim * method to acquire a mutex, and a different method to release it, as long as 531167802Sjkim * this is performed underneath a single parent control method. 532167802Sjkim * 53377422Smsmith ******************************************************************************/ 53477422Smsmith 53599679Siwasakivoid 53677422SmsmithAcpiExReleaseAllMutexes ( 53787031Smsmith ACPI_THREAD_STATE *Thread) 53877422Smsmith{ 53987031Smsmith ACPI_OPERAND_OBJECT *Next = Thread->AcquiredMutexList; 540167802Sjkim ACPI_OPERAND_OBJECT *ObjDesc; 54177422Smsmith 54277422Smsmith 543306536Sjkim ACPI_FUNCTION_TRACE (ExReleaseAllMutexes); 54483174Smsmith 54583174Smsmith 546129684Snjl /* Traverse the list of owned mutexes, releasing each one */ 547129684Snjl 54877422Smsmith while (Next) 54977422Smsmith { 550167802Sjkim ObjDesc = Next; 551241973Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 552306536Sjkim "Mutex [%4.4s] force-release, SyncLevel %u Depth %u\n", 553306536Sjkim ObjDesc->Mutex.Node->Name.Ascii, ObjDesc->Mutex.SyncLevel, 554306536Sjkim ObjDesc->Mutex.AcquisitionDepth)); 555241973Sjkim 556167802Sjkim /* Release the mutex, special case for Global Lock */ 55777422Smsmith 558167802Sjkim if (ObjDesc == AcpiGbl_GlobalLockMutex) 55999679Siwasaki { 560167802Sjkim /* Ignore errors */ 561167802Sjkim 562167802Sjkim (void) AcpiEvReleaseGlobalLock (); 56399679Siwasaki } 564167802Sjkim else 565167802Sjkim { 566167802Sjkim AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex); 567167802Sjkim } 56887031Smsmith 569306536Sjkim /* Update Thread SyncLevel (Last mutex is the important one) */ 570306536Sjkim 571306536Sjkim Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel; 572306536Sjkim 57387031Smsmith /* Mark mutex unowned */ 57487031Smsmith 575306536Sjkim Next = ObjDesc->Mutex.Next; 576306536Sjkim 577306536Sjkim ObjDesc->Mutex.Prev = NULL; 578306536Sjkim ObjDesc->Mutex.Next = NULL; 579306536Sjkim ObjDesc->Mutex.AcquisitionDepth = 0; 580167802Sjkim ObjDesc->Mutex.OwnerThread = NULL; 581167802Sjkim ObjDesc->Mutex.ThreadId = 0; 582306536Sjkim } 583129684Snjl 584306536Sjkim return_VOID; 58577422Smsmith} 586