1*a159c266SJung-uk Kim 2*a159c266SJung-uk Kim /****************************************************************************** 3*a159c266SJung-uk Kim * 4*a159c266SJung-uk Kim * Module Name: exmutex - ASL Mutex Acquire/Release functions 5*a159c266SJung-uk Kim * 6*a159c266SJung-uk Kim *****************************************************************************/ 7*a159c266SJung-uk Kim 8*a159c266SJung-uk Kim /* 9*a159c266SJung-uk Kim * Copyright (C) 2000 - 2012, Intel Corp. 10*a159c266SJung-uk Kim * All rights reserved. 11*a159c266SJung-uk Kim * 12*a159c266SJung-uk Kim * Redistribution and use in source and binary forms, with or without 13*a159c266SJung-uk Kim * modification, are permitted provided that the following conditions 14*a159c266SJung-uk Kim * are met: 15*a159c266SJung-uk Kim * 1. Redistributions of source code must retain the above copyright 16*a159c266SJung-uk Kim * notice, this list of conditions, and the following disclaimer, 17*a159c266SJung-uk Kim * without modification. 18*a159c266SJung-uk Kim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19*a159c266SJung-uk Kim * substantially similar to the "NO WARRANTY" disclaimer below 20*a159c266SJung-uk Kim * ("Disclaimer") and any redistribution must be conditioned upon 21*a159c266SJung-uk Kim * including a substantially similar Disclaimer requirement for further 22*a159c266SJung-uk Kim * binary redistribution. 23*a159c266SJung-uk Kim * 3. Neither the names of the above-listed copyright holders nor the names 24*a159c266SJung-uk Kim * of any contributors may be used to endorse or promote products derived 25*a159c266SJung-uk Kim * from this software without specific prior written permission. 26*a159c266SJung-uk Kim * 27*a159c266SJung-uk Kim * Alternatively, this software may be distributed under the terms of the 28*a159c266SJung-uk Kim * GNU General Public License ("GPL") version 2 as published by the Free 29*a159c266SJung-uk Kim * Software Foundation. 30*a159c266SJung-uk Kim * 31*a159c266SJung-uk Kim * NO WARRANTY 32*a159c266SJung-uk Kim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33*a159c266SJung-uk Kim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34*a159c266SJung-uk Kim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35*a159c266SJung-uk Kim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36*a159c266SJung-uk Kim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37*a159c266SJung-uk Kim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38*a159c266SJung-uk Kim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39*a159c266SJung-uk Kim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40*a159c266SJung-uk Kim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41*a159c266SJung-uk Kim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42*a159c266SJung-uk Kim * POSSIBILITY OF SUCH DAMAGES. 43*a159c266SJung-uk Kim */ 44*a159c266SJung-uk Kim 45*a159c266SJung-uk Kim #define __EXMUTEX_C__ 46*a159c266SJung-uk Kim 47*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h> 48*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h> 49*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acinterp.h> 50*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acevents.h> 51*a159c266SJung-uk Kim 52*a159c266SJung-uk Kim #define _COMPONENT ACPI_EXECUTER 53*a159c266SJung-uk Kim ACPI_MODULE_NAME ("exmutex") 54*a159c266SJung-uk Kim 55*a159c266SJung-uk Kim /* Local prototypes */ 56*a159c266SJung-uk Kim 57*a159c266SJung-uk Kim static void 58*a159c266SJung-uk Kim AcpiExLinkMutex ( 59*a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc, 60*a159c266SJung-uk Kim ACPI_THREAD_STATE *Thread); 61*a159c266SJung-uk Kim 62*a159c266SJung-uk Kim 63*a159c266SJung-uk Kim /******************************************************************************* 64*a159c266SJung-uk Kim * 65*a159c266SJung-uk Kim * FUNCTION: AcpiExUnlinkMutex 66*a159c266SJung-uk Kim * 67*a159c266SJung-uk Kim * PARAMETERS: ObjDesc - The mutex to be unlinked 68*a159c266SJung-uk Kim * 69*a159c266SJung-uk Kim * RETURN: None 70*a159c266SJung-uk Kim * 71*a159c266SJung-uk Kim * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list 72*a159c266SJung-uk Kim * 73*a159c266SJung-uk Kim ******************************************************************************/ 74*a159c266SJung-uk Kim 75*a159c266SJung-uk Kim void 76*a159c266SJung-uk Kim AcpiExUnlinkMutex ( 77*a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc) 78*a159c266SJung-uk Kim { 79*a159c266SJung-uk Kim ACPI_THREAD_STATE *Thread = ObjDesc->Mutex.OwnerThread; 80*a159c266SJung-uk Kim 81*a159c266SJung-uk Kim 82*a159c266SJung-uk Kim if (!Thread) 83*a159c266SJung-uk Kim { 84*a159c266SJung-uk Kim return; 85*a159c266SJung-uk Kim } 86*a159c266SJung-uk Kim 87*a159c266SJung-uk Kim /* Doubly linked list */ 88*a159c266SJung-uk Kim 89*a159c266SJung-uk Kim if (ObjDesc->Mutex.Next) 90*a159c266SJung-uk Kim { 91*a159c266SJung-uk Kim (ObjDesc->Mutex.Next)->Mutex.Prev = ObjDesc->Mutex.Prev; 92*a159c266SJung-uk Kim } 93*a159c266SJung-uk Kim 94*a159c266SJung-uk Kim if (ObjDesc->Mutex.Prev) 95*a159c266SJung-uk Kim { 96*a159c266SJung-uk Kim (ObjDesc->Mutex.Prev)->Mutex.Next = ObjDesc->Mutex.Next; 97*a159c266SJung-uk Kim 98*a159c266SJung-uk Kim /* 99*a159c266SJung-uk Kim * Migrate the previous sync level associated with this mutex to 100*a159c266SJung-uk Kim * the previous mutex on the list so that it may be preserved. 101*a159c266SJung-uk Kim * This handles the case where several mutexes have been acquired 102*a159c266SJung-uk Kim * at the same level, but are not released in opposite order. 103*a159c266SJung-uk Kim */ 104*a159c266SJung-uk Kim (ObjDesc->Mutex.Prev)->Mutex.OriginalSyncLevel = 105*a159c266SJung-uk Kim ObjDesc->Mutex.OriginalSyncLevel; 106*a159c266SJung-uk Kim } 107*a159c266SJung-uk Kim else 108*a159c266SJung-uk Kim { 109*a159c266SJung-uk Kim Thread->AcquiredMutexList = ObjDesc->Mutex.Next; 110*a159c266SJung-uk Kim } 111*a159c266SJung-uk Kim } 112*a159c266SJung-uk Kim 113*a159c266SJung-uk Kim 114*a159c266SJung-uk Kim /******************************************************************************* 115*a159c266SJung-uk Kim * 116*a159c266SJung-uk Kim * FUNCTION: AcpiExLinkMutex 117*a159c266SJung-uk Kim * 118*a159c266SJung-uk Kim * PARAMETERS: ObjDesc - The mutex to be linked 119*a159c266SJung-uk Kim * Thread - Current executing thread object 120*a159c266SJung-uk Kim * 121*a159c266SJung-uk Kim * RETURN: None 122*a159c266SJung-uk Kim * 123*a159c266SJung-uk Kim * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk 124*a159c266SJung-uk Kim * 125*a159c266SJung-uk Kim ******************************************************************************/ 126*a159c266SJung-uk Kim 127*a159c266SJung-uk Kim static void 128*a159c266SJung-uk Kim AcpiExLinkMutex ( 129*a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc, 130*a159c266SJung-uk Kim ACPI_THREAD_STATE *Thread) 131*a159c266SJung-uk Kim { 132*a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ListHead; 133*a159c266SJung-uk Kim 134*a159c266SJung-uk Kim 135*a159c266SJung-uk Kim ListHead = Thread->AcquiredMutexList; 136*a159c266SJung-uk Kim 137*a159c266SJung-uk Kim /* This object will be the first object in the list */ 138*a159c266SJung-uk Kim 139*a159c266SJung-uk Kim ObjDesc->Mutex.Prev = NULL; 140*a159c266SJung-uk Kim ObjDesc->Mutex.Next = ListHead; 141*a159c266SJung-uk Kim 142*a159c266SJung-uk Kim /* Update old first object to point back to this object */ 143*a159c266SJung-uk Kim 144*a159c266SJung-uk Kim if (ListHead) 145*a159c266SJung-uk Kim { 146*a159c266SJung-uk Kim ListHead->Mutex.Prev = ObjDesc; 147*a159c266SJung-uk Kim } 148*a159c266SJung-uk Kim 149*a159c266SJung-uk Kim /* Update list head */ 150*a159c266SJung-uk Kim 151*a159c266SJung-uk Kim Thread->AcquiredMutexList = ObjDesc; 152*a159c266SJung-uk Kim } 153*a159c266SJung-uk Kim 154*a159c266SJung-uk Kim 155*a159c266SJung-uk Kim /******************************************************************************* 156*a159c266SJung-uk Kim * 157*a159c266SJung-uk Kim * FUNCTION: AcpiExAcquireMutexObject 158*a159c266SJung-uk Kim * 159*a159c266SJung-uk Kim * PARAMETERS: Timeout - Timeout in milliseconds 160*a159c266SJung-uk Kim * ObjDesc - Mutex object 161*a159c266SJung-uk Kim * ThreadId - Current thread state 162*a159c266SJung-uk Kim * 163*a159c266SJung-uk Kim * RETURN: Status 164*a159c266SJung-uk Kim * 165*a159c266SJung-uk Kim * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common 166*a159c266SJung-uk Kim * path that supports multiple acquires by the same thread. 167*a159c266SJung-uk Kim * 168*a159c266SJung-uk Kim * MUTEX: Interpreter must be locked 169*a159c266SJung-uk Kim * 170*a159c266SJung-uk Kim * NOTE: This interface is called from three places: 171*a159c266SJung-uk Kim * 1) From AcpiExAcquireMutex, via an AML Acquire() operator 172*a159c266SJung-uk Kim * 2) From AcpiExAcquireGlobalLock when an AML Field access requires the 173*a159c266SJung-uk Kim * global lock 174*a159c266SJung-uk Kim * 3) From the external interface, AcpiAcquireGlobalLock 175*a159c266SJung-uk Kim * 176*a159c266SJung-uk Kim ******************************************************************************/ 177*a159c266SJung-uk Kim 178*a159c266SJung-uk Kim ACPI_STATUS 179*a159c266SJung-uk Kim AcpiExAcquireMutexObject ( 180*a159c266SJung-uk Kim UINT16 Timeout, 181*a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc, 182*a159c266SJung-uk Kim ACPI_THREAD_ID ThreadId) 183*a159c266SJung-uk Kim { 184*a159c266SJung-uk Kim ACPI_STATUS Status; 185*a159c266SJung-uk Kim 186*a159c266SJung-uk Kim 187*a159c266SJung-uk Kim ACPI_FUNCTION_TRACE_PTR (ExAcquireMutexObject, ObjDesc); 188*a159c266SJung-uk Kim 189*a159c266SJung-uk Kim 190*a159c266SJung-uk Kim if (!ObjDesc) 191*a159c266SJung-uk Kim { 192*a159c266SJung-uk Kim return_ACPI_STATUS (AE_BAD_PARAMETER); 193*a159c266SJung-uk Kim } 194*a159c266SJung-uk Kim 195*a159c266SJung-uk Kim /* Support for multiple acquires by the owning thread */ 196*a159c266SJung-uk Kim 197*a159c266SJung-uk Kim if (ObjDesc->Mutex.ThreadId == ThreadId) 198*a159c266SJung-uk Kim { 199*a159c266SJung-uk Kim /* 200*a159c266SJung-uk Kim * The mutex is already owned by this thread, just increment the 201*a159c266SJung-uk Kim * acquisition depth 202*a159c266SJung-uk Kim */ 203*a159c266SJung-uk Kim ObjDesc->Mutex.AcquisitionDepth++; 204*a159c266SJung-uk Kim return_ACPI_STATUS (AE_OK); 205*a159c266SJung-uk Kim } 206*a159c266SJung-uk Kim 207*a159c266SJung-uk Kim /* Acquire the mutex, wait if necessary. Special case for Global Lock */ 208*a159c266SJung-uk Kim 209*a159c266SJung-uk Kim if (ObjDesc == AcpiGbl_GlobalLockMutex) 210*a159c266SJung-uk Kim { 211*a159c266SJung-uk Kim Status = AcpiEvAcquireGlobalLock (Timeout); 212*a159c266SJung-uk Kim } 213*a159c266SJung-uk Kim else 214*a159c266SJung-uk Kim { 215*a159c266SJung-uk Kim Status = AcpiExSystemWaitMutex (ObjDesc->Mutex.OsMutex, 216*a159c266SJung-uk Kim Timeout); 217*a159c266SJung-uk Kim } 218*a159c266SJung-uk Kim 219*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 220*a159c266SJung-uk Kim { 221*a159c266SJung-uk Kim /* Includes failure from a timeout on TimeDesc */ 222*a159c266SJung-uk Kim 223*a159c266SJung-uk Kim return_ACPI_STATUS (Status); 224*a159c266SJung-uk Kim } 225*a159c266SJung-uk Kim 226*a159c266SJung-uk Kim /* Acquired the mutex: update mutex object */ 227*a159c266SJung-uk Kim 228*a159c266SJung-uk Kim ObjDesc->Mutex.ThreadId = ThreadId; 229*a159c266SJung-uk Kim ObjDesc->Mutex.AcquisitionDepth = 1; 230*a159c266SJung-uk Kim ObjDesc->Mutex.OriginalSyncLevel = 0; 231*a159c266SJung-uk Kim ObjDesc->Mutex.OwnerThread = NULL; /* Used only for AML Acquire() */ 232*a159c266SJung-uk Kim 233*a159c266SJung-uk Kim return_ACPI_STATUS (AE_OK); 234*a159c266SJung-uk Kim } 235*a159c266SJung-uk Kim 236*a159c266SJung-uk Kim 237*a159c266SJung-uk Kim /******************************************************************************* 238*a159c266SJung-uk Kim * 239*a159c266SJung-uk Kim * FUNCTION: AcpiExAcquireMutex 240*a159c266SJung-uk Kim * 241*a159c266SJung-uk Kim * PARAMETERS: TimeDesc - Timeout integer 242*a159c266SJung-uk Kim * ObjDesc - Mutex object 243*a159c266SJung-uk Kim * WalkState - Current method execution state 244*a159c266SJung-uk Kim * 245*a159c266SJung-uk Kim * RETURN: Status 246*a159c266SJung-uk Kim * 247*a159c266SJung-uk Kim * DESCRIPTION: Acquire an AML mutex 248*a159c266SJung-uk Kim * 249*a159c266SJung-uk Kim ******************************************************************************/ 250*a159c266SJung-uk Kim 251*a159c266SJung-uk Kim ACPI_STATUS 252*a159c266SJung-uk Kim AcpiExAcquireMutex ( 253*a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *TimeDesc, 254*a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc, 255*a159c266SJung-uk Kim ACPI_WALK_STATE *WalkState) 256*a159c266SJung-uk Kim { 257*a159c266SJung-uk Kim ACPI_STATUS Status; 258*a159c266SJung-uk Kim 259*a159c266SJung-uk Kim 260*a159c266SJung-uk Kim ACPI_FUNCTION_TRACE_PTR (ExAcquireMutex, ObjDesc); 261*a159c266SJung-uk Kim 262*a159c266SJung-uk Kim 263*a159c266SJung-uk Kim if (!ObjDesc) 264*a159c266SJung-uk Kim { 265*a159c266SJung-uk Kim return_ACPI_STATUS (AE_BAD_PARAMETER); 266*a159c266SJung-uk Kim } 267*a159c266SJung-uk Kim 268*a159c266SJung-uk Kim /* Must have a valid thread state struct */ 269*a159c266SJung-uk Kim 270*a159c266SJung-uk Kim if (!WalkState->Thread) 271*a159c266SJung-uk Kim { 272*a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 273*a159c266SJung-uk Kim "Cannot acquire Mutex [%4.4s], null thread info", 274*a159c266SJung-uk Kim AcpiUtGetNodeName (ObjDesc->Mutex.Node))); 275*a159c266SJung-uk Kim return_ACPI_STATUS (AE_AML_INTERNAL); 276*a159c266SJung-uk Kim } 277*a159c266SJung-uk Kim 278*a159c266SJung-uk Kim /* 279*a159c266SJung-uk Kim * Current sync level must be less than or equal to the sync level of the 280*a159c266SJung-uk Kim * mutex. This mechanism provides some deadlock prevention 281*a159c266SJung-uk Kim */ 282*a159c266SJung-uk Kim if (WalkState->Thread->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel) 283*a159c266SJung-uk Kim { 284*a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 285*a159c266SJung-uk Kim "Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%u)", 286*a159c266SJung-uk Kim AcpiUtGetNodeName (ObjDesc->Mutex.Node), 287*a159c266SJung-uk Kim WalkState->Thread->CurrentSyncLevel)); 288*a159c266SJung-uk Kim return_ACPI_STATUS (AE_AML_MUTEX_ORDER); 289*a159c266SJung-uk Kim } 290*a159c266SJung-uk Kim 291*a159c266SJung-uk Kim Status = AcpiExAcquireMutexObject ((UINT16) TimeDesc->Integer.Value, 292*a159c266SJung-uk Kim ObjDesc, WalkState->Thread->ThreadId); 293*a159c266SJung-uk Kim if (ACPI_SUCCESS (Status) && ObjDesc->Mutex.AcquisitionDepth == 1) 294*a159c266SJung-uk Kim { 295*a159c266SJung-uk Kim /* Save Thread object, original/current sync levels */ 296*a159c266SJung-uk Kim 297*a159c266SJung-uk Kim ObjDesc->Mutex.OwnerThread = WalkState->Thread; 298*a159c266SJung-uk Kim ObjDesc->Mutex.OriginalSyncLevel = WalkState->Thread->CurrentSyncLevel; 299*a159c266SJung-uk Kim WalkState->Thread->CurrentSyncLevel = ObjDesc->Mutex.SyncLevel; 300*a159c266SJung-uk Kim 301*a159c266SJung-uk Kim /* Link the mutex to the current thread for force-unlock at method exit */ 302*a159c266SJung-uk Kim 303*a159c266SJung-uk Kim AcpiExLinkMutex (ObjDesc, WalkState->Thread); 304*a159c266SJung-uk Kim } 305*a159c266SJung-uk Kim 306*a159c266SJung-uk Kim return_ACPI_STATUS (Status); 307*a159c266SJung-uk Kim } 308*a159c266SJung-uk Kim 309*a159c266SJung-uk Kim 310*a159c266SJung-uk Kim /******************************************************************************* 311*a159c266SJung-uk Kim * 312*a159c266SJung-uk Kim * FUNCTION: AcpiExReleaseMutexObject 313*a159c266SJung-uk Kim * 314*a159c266SJung-uk Kim * PARAMETERS: ObjDesc - The object descriptor for this op 315*a159c266SJung-uk Kim * 316*a159c266SJung-uk Kim * RETURN: Status 317*a159c266SJung-uk Kim * 318*a159c266SJung-uk Kim * DESCRIPTION: Release a previously acquired Mutex, low level interface. 319*a159c266SJung-uk Kim * Provides a common path that supports multiple releases (after 320*a159c266SJung-uk Kim * previous multiple acquires) by the same thread. 321*a159c266SJung-uk Kim * 322*a159c266SJung-uk Kim * MUTEX: Interpreter must be locked 323*a159c266SJung-uk Kim * 324*a159c266SJung-uk Kim * NOTE: This interface is called from three places: 325*a159c266SJung-uk Kim * 1) From AcpiExReleaseMutex, via an AML Acquire() operator 326*a159c266SJung-uk Kim * 2) From AcpiExReleaseGlobalLock when an AML Field access requires the 327*a159c266SJung-uk Kim * global lock 328*a159c266SJung-uk Kim * 3) From the external interface, AcpiReleaseGlobalLock 329*a159c266SJung-uk Kim * 330*a159c266SJung-uk Kim ******************************************************************************/ 331*a159c266SJung-uk Kim 332*a159c266SJung-uk Kim ACPI_STATUS 333*a159c266SJung-uk Kim AcpiExReleaseMutexObject ( 334*a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc) 335*a159c266SJung-uk Kim { 336*a159c266SJung-uk Kim ACPI_STATUS Status = AE_OK; 337*a159c266SJung-uk Kim 338*a159c266SJung-uk Kim 339*a159c266SJung-uk Kim ACPI_FUNCTION_TRACE (ExReleaseMutexObject); 340*a159c266SJung-uk Kim 341*a159c266SJung-uk Kim 342*a159c266SJung-uk Kim if (ObjDesc->Mutex.AcquisitionDepth == 0) 343*a159c266SJung-uk Kim { 344*a159c266SJung-uk Kim return (AE_NOT_ACQUIRED); 345*a159c266SJung-uk Kim } 346*a159c266SJung-uk Kim 347*a159c266SJung-uk Kim /* Match multiple Acquires with multiple Releases */ 348*a159c266SJung-uk Kim 349*a159c266SJung-uk Kim ObjDesc->Mutex.AcquisitionDepth--; 350*a159c266SJung-uk Kim if (ObjDesc->Mutex.AcquisitionDepth != 0) 351*a159c266SJung-uk Kim { 352*a159c266SJung-uk Kim /* Just decrement the depth and return */ 353*a159c266SJung-uk Kim 354*a159c266SJung-uk Kim return_ACPI_STATUS (AE_OK); 355*a159c266SJung-uk Kim } 356*a159c266SJung-uk Kim 357*a159c266SJung-uk Kim if (ObjDesc->Mutex.OwnerThread) 358*a159c266SJung-uk Kim { 359*a159c266SJung-uk Kim /* Unlink the mutex from the owner's list */ 360*a159c266SJung-uk Kim 361*a159c266SJung-uk Kim AcpiExUnlinkMutex (ObjDesc); 362*a159c266SJung-uk Kim ObjDesc->Mutex.OwnerThread = NULL; 363*a159c266SJung-uk Kim } 364*a159c266SJung-uk Kim 365*a159c266SJung-uk Kim /* Release the mutex, special case for Global Lock */ 366*a159c266SJung-uk Kim 367*a159c266SJung-uk Kim if (ObjDesc == AcpiGbl_GlobalLockMutex) 368*a159c266SJung-uk Kim { 369*a159c266SJung-uk Kim Status = AcpiEvReleaseGlobalLock (); 370*a159c266SJung-uk Kim } 371*a159c266SJung-uk Kim else 372*a159c266SJung-uk Kim { 373*a159c266SJung-uk Kim AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex); 374*a159c266SJung-uk Kim } 375*a159c266SJung-uk Kim 376*a159c266SJung-uk Kim /* Clear mutex info */ 377*a159c266SJung-uk Kim 378*a159c266SJung-uk Kim ObjDesc->Mutex.ThreadId = 0; 379*a159c266SJung-uk Kim return_ACPI_STATUS (Status); 380*a159c266SJung-uk Kim } 381*a159c266SJung-uk Kim 382*a159c266SJung-uk Kim 383*a159c266SJung-uk Kim /******************************************************************************* 384*a159c266SJung-uk Kim * 385*a159c266SJung-uk Kim * FUNCTION: AcpiExReleaseMutex 386*a159c266SJung-uk Kim * 387*a159c266SJung-uk Kim * PARAMETERS: ObjDesc - The object descriptor for this op 388*a159c266SJung-uk Kim * WalkState - Current method execution state 389*a159c266SJung-uk Kim * 390*a159c266SJung-uk Kim * RETURN: Status 391*a159c266SJung-uk Kim * 392*a159c266SJung-uk Kim * DESCRIPTION: Release a previously acquired Mutex. 393*a159c266SJung-uk Kim * 394*a159c266SJung-uk Kim ******************************************************************************/ 395*a159c266SJung-uk Kim 396*a159c266SJung-uk Kim ACPI_STATUS 397*a159c266SJung-uk Kim AcpiExReleaseMutex ( 398*a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc, 399*a159c266SJung-uk Kim ACPI_WALK_STATE *WalkState) 400*a159c266SJung-uk Kim { 401*a159c266SJung-uk Kim ACPI_STATUS Status = AE_OK; 402*a159c266SJung-uk Kim UINT8 PreviousSyncLevel; 403*a159c266SJung-uk Kim ACPI_THREAD_STATE *OwnerThread; 404*a159c266SJung-uk Kim 405*a159c266SJung-uk Kim 406*a159c266SJung-uk Kim ACPI_FUNCTION_TRACE (ExReleaseMutex); 407*a159c266SJung-uk Kim 408*a159c266SJung-uk Kim 409*a159c266SJung-uk Kim if (!ObjDesc) 410*a159c266SJung-uk Kim { 411*a159c266SJung-uk Kim return_ACPI_STATUS (AE_BAD_PARAMETER); 412*a159c266SJung-uk Kim } 413*a159c266SJung-uk Kim 414*a159c266SJung-uk Kim OwnerThread = ObjDesc->Mutex.OwnerThread; 415*a159c266SJung-uk Kim 416*a159c266SJung-uk Kim /* The mutex must have been previously acquired in order to release it */ 417*a159c266SJung-uk Kim 418*a159c266SJung-uk Kim if (!OwnerThread) 419*a159c266SJung-uk Kim { 420*a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 421*a159c266SJung-uk Kim "Cannot release Mutex [%4.4s], not acquired", 422*a159c266SJung-uk Kim AcpiUtGetNodeName (ObjDesc->Mutex.Node))); 423*a159c266SJung-uk Kim return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED); 424*a159c266SJung-uk Kim } 425*a159c266SJung-uk Kim 426*a159c266SJung-uk Kim /* Must have a valid thread ID */ 427*a159c266SJung-uk Kim 428*a159c266SJung-uk Kim if (!WalkState->Thread) 429*a159c266SJung-uk Kim { 430*a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 431*a159c266SJung-uk Kim "Cannot release Mutex [%4.4s], null thread info", 432*a159c266SJung-uk Kim AcpiUtGetNodeName (ObjDesc->Mutex.Node))); 433*a159c266SJung-uk Kim return_ACPI_STATUS (AE_AML_INTERNAL); 434*a159c266SJung-uk Kim } 435*a159c266SJung-uk Kim 436*a159c266SJung-uk Kim /* 437*a159c266SJung-uk Kim * The Mutex is owned, but this thread must be the owner. 438*a159c266SJung-uk Kim * Special case for Global Lock, any thread can release 439*a159c266SJung-uk Kim */ 440*a159c266SJung-uk Kim if ((OwnerThread->ThreadId != WalkState->Thread->ThreadId) && 441*a159c266SJung-uk Kim (ObjDesc != AcpiGbl_GlobalLockMutex)) 442*a159c266SJung-uk Kim { 443*a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 444*a159c266SJung-uk Kim "Thread %u cannot release Mutex [%4.4s] acquired by thread %u", 445*a159c266SJung-uk Kim (UINT32) WalkState->Thread->ThreadId, 446*a159c266SJung-uk Kim AcpiUtGetNodeName (ObjDesc->Mutex.Node), 447*a159c266SJung-uk Kim (UINT32) OwnerThread->ThreadId)); 448*a159c266SJung-uk Kim return_ACPI_STATUS (AE_AML_NOT_OWNER); 449*a159c266SJung-uk Kim } 450*a159c266SJung-uk Kim 451*a159c266SJung-uk Kim /* 452*a159c266SJung-uk Kim * The sync level of the mutex must be equal to the current sync level. In 453*a159c266SJung-uk Kim * other words, the current level means that at least one mutex at that 454*a159c266SJung-uk Kim * level is currently being held. Attempting to release a mutex of a 455*a159c266SJung-uk Kim * different level can only mean that the mutex ordering rule is being 456*a159c266SJung-uk Kim * violated. This behavior is clarified in ACPI 4.0 specification. 457*a159c266SJung-uk Kim */ 458*a159c266SJung-uk Kim if (ObjDesc->Mutex.SyncLevel != OwnerThread->CurrentSyncLevel) 459*a159c266SJung-uk Kim { 460*a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 461*a159c266SJung-uk Kim "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u", 462*a159c266SJung-uk Kim AcpiUtGetNodeName (ObjDesc->Mutex.Node), 463*a159c266SJung-uk Kim ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel)); 464*a159c266SJung-uk Kim return_ACPI_STATUS (AE_AML_MUTEX_ORDER); 465*a159c266SJung-uk Kim } 466*a159c266SJung-uk Kim 467*a159c266SJung-uk Kim /* 468*a159c266SJung-uk Kim * Get the previous SyncLevel from the head of the acquired mutex list. 469*a159c266SJung-uk Kim * This handles the case where several mutexes at the same level have been 470*a159c266SJung-uk Kim * acquired, but are not released in reverse order. 471*a159c266SJung-uk Kim */ 472*a159c266SJung-uk Kim PreviousSyncLevel = 473*a159c266SJung-uk Kim OwnerThread->AcquiredMutexList->Mutex.OriginalSyncLevel; 474*a159c266SJung-uk Kim 475*a159c266SJung-uk Kim Status = AcpiExReleaseMutexObject (ObjDesc); 476*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 477*a159c266SJung-uk Kim { 478*a159c266SJung-uk Kim return_ACPI_STATUS (Status); 479*a159c266SJung-uk Kim } 480*a159c266SJung-uk Kim 481*a159c266SJung-uk Kim if (ObjDesc->Mutex.AcquisitionDepth == 0) 482*a159c266SJung-uk Kim { 483*a159c266SJung-uk Kim /* Restore the previous SyncLevel */ 484*a159c266SJung-uk Kim 485*a159c266SJung-uk Kim OwnerThread->CurrentSyncLevel = PreviousSyncLevel; 486*a159c266SJung-uk Kim } 487*a159c266SJung-uk Kim 488*a159c266SJung-uk Kim return_ACPI_STATUS (Status); 489*a159c266SJung-uk Kim } 490*a159c266SJung-uk Kim 491*a159c266SJung-uk Kim 492*a159c266SJung-uk Kim /******************************************************************************* 493*a159c266SJung-uk Kim * 494*a159c266SJung-uk Kim * FUNCTION: AcpiExReleaseAllMutexes 495*a159c266SJung-uk Kim * 496*a159c266SJung-uk Kim * PARAMETERS: Thread - Current executing thread object 497*a159c266SJung-uk Kim * 498*a159c266SJung-uk Kim * RETURN: Status 499*a159c266SJung-uk Kim * 500*a159c266SJung-uk Kim * DESCRIPTION: Release all mutexes held by this thread 501*a159c266SJung-uk Kim * 502*a159c266SJung-uk Kim * NOTE: This function is called as the thread is exiting the interpreter. 503*a159c266SJung-uk Kim * Mutexes are not released when an individual control method is exited, but 504*a159c266SJung-uk Kim * only when the parent thread actually exits the interpreter. This allows one 505*a159c266SJung-uk Kim * method to acquire a mutex, and a different method to release it, as long as 506*a159c266SJung-uk Kim * this is performed underneath a single parent control method. 507*a159c266SJung-uk Kim * 508*a159c266SJung-uk Kim ******************************************************************************/ 509*a159c266SJung-uk Kim 510*a159c266SJung-uk Kim void 511*a159c266SJung-uk Kim AcpiExReleaseAllMutexes ( 512*a159c266SJung-uk Kim ACPI_THREAD_STATE *Thread) 513*a159c266SJung-uk Kim { 514*a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *Next = Thread->AcquiredMutexList; 515*a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc; 516*a159c266SJung-uk Kim 517*a159c266SJung-uk Kim 518*a159c266SJung-uk Kim ACPI_FUNCTION_ENTRY (); 519*a159c266SJung-uk Kim 520*a159c266SJung-uk Kim 521*a159c266SJung-uk Kim /* Traverse the list of owned mutexes, releasing each one */ 522*a159c266SJung-uk Kim 523*a159c266SJung-uk Kim while (Next) 524*a159c266SJung-uk Kim { 525*a159c266SJung-uk Kim ObjDesc = Next; 526*a159c266SJung-uk Kim Next = ObjDesc->Mutex.Next; 527*a159c266SJung-uk Kim 528*a159c266SJung-uk Kim ObjDesc->Mutex.Prev = NULL; 529*a159c266SJung-uk Kim ObjDesc->Mutex.Next = NULL; 530*a159c266SJung-uk Kim ObjDesc->Mutex.AcquisitionDepth = 0; 531*a159c266SJung-uk Kim 532*a159c266SJung-uk Kim /* Release the mutex, special case for Global Lock */ 533*a159c266SJung-uk Kim 534*a159c266SJung-uk Kim if (ObjDesc == AcpiGbl_GlobalLockMutex) 535*a159c266SJung-uk Kim { 536*a159c266SJung-uk Kim /* Ignore errors */ 537*a159c266SJung-uk Kim 538*a159c266SJung-uk Kim (void) AcpiEvReleaseGlobalLock (); 539*a159c266SJung-uk Kim } 540*a159c266SJung-uk Kim else 541*a159c266SJung-uk Kim { 542*a159c266SJung-uk Kim AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex); 543*a159c266SJung-uk Kim } 544*a159c266SJung-uk Kim 545*a159c266SJung-uk Kim /* Mark mutex unowned */ 546*a159c266SJung-uk Kim 547*a159c266SJung-uk Kim ObjDesc->Mutex.OwnerThread = NULL; 548*a159c266SJung-uk Kim ObjDesc->Mutex.ThreadId = 0; 549*a159c266SJung-uk Kim 550*a159c266SJung-uk Kim /* Update Thread SyncLevel (Last mutex is the important one) */ 551*a159c266SJung-uk Kim 552*a159c266SJung-uk Kim Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel; 553*a159c266SJung-uk Kim } 554*a159c266SJung-uk Kim } 555