Home | History | Annotate | Line # | Download | only in executer
      1 /******************************************************************************
      2  *
      3  * Module Name: exmutex - ASL Mutex Acquire/Release functions
      4  *
      5  *****************************************************************************/
      6 
      7 /******************************************************************************
      8  *
      9  * 1. Copyright Notice
     10  *
     11  * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
     12  * All rights reserved.
     13  *
     14  * 2. License
     15  *
     16  * 2.1. This is your license from Intel Corp. under its intellectual property
     17  * rights. You may have additional license terms from the party that provided
     18  * you this software, covering your right to use that party's intellectual
     19  * property rights.
     20  *
     21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     22  * copy of the source code appearing in this file ("Covered Code") an
     23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     24  * base code distributed originally by Intel ("Original Intel Code") to copy,
     25  * make derivatives, distribute, use and display any portion of the Covered
     26  * Code in any form, with the right to sublicense such rights; and
     27  *
     28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     29  * license (with the right to sublicense), under only those claims of Intel
     30  * patents that are infringed by the Original Intel Code, to make, use, sell,
     31  * offer to sell, and import the Covered Code and derivative works thereof
     32  * solely to the minimum extent necessary to exercise the above copyright
     33  * license, and in no event shall the patent license extend to any additions
     34  * to or modifications of the Original Intel Code. No other license or right
     35  * is granted directly or by implication, estoppel or otherwise;
     36  *
     37  * The above copyright and patent license is granted only if the following
     38  * conditions are met:
     39  *
     40  * 3. Conditions
     41  *
     42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     43  * Redistribution of source code of any substantial portion of the Covered
     44  * Code or modification with rights to further distribute source must include
     45  * the above Copyright Notice, the above License, this list of Conditions,
     46  * and the following Disclaimer and Export Compliance provision. In addition,
     47  * Licensee must cause all Covered Code to which Licensee contributes to
     48  * contain a file documenting the changes Licensee made to create that Covered
     49  * Code and the date of any change. Licensee must include in that file the
     50  * documentation of any changes made by any predecessor Licensee. Licensee
     51  * must include a prominent statement that the modification is derived,
     52  * directly or indirectly, from Original Intel Code.
     53  *
     54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     55  * Redistribution of source code of any substantial portion of the Covered
     56  * Code or modification without rights to further distribute source must
     57  * include the following Disclaimer and Export Compliance provision in the
     58  * documentation and/or other materials provided with distribution. In
     59  * addition, Licensee may not authorize further sublicense of source of any
     60  * portion of the Covered Code, and must include terms to the effect that the
     61  * license from Licensee to its licensee is limited to the intellectual
     62  * property embodied in the software Licensee provides to its licensee, and
     63  * not to intellectual property embodied in modifications its licensee may
     64  * make.
     65  *
     66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     67  * substantial portion of the Covered Code or modification must reproduce the
     68  * above Copyright Notice, and the following Disclaimer and Export Compliance
     69  * provision in the documentation and/or other materials provided with the
     70  * distribution.
     71  *
     72  * 3.4. Intel retains all right, title, and interest in and to the Original
     73  * Intel Code.
     74  *
     75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     76  * Intel shall be used in advertising or otherwise to promote the sale, use or
     77  * other dealings in products derived from or relating to the Covered Code
     78  * without prior written authorization from Intel.
     79  *
     80  * 4. Disclaimer and Export Compliance
     81  *
     82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
     85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
     86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
     87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     88  * PARTICULAR PURPOSE.
     89  *
     90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
     96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     97  * LIMITED REMEDY.
     98  *
     99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    100  * software or system incorporating such software without first obtaining any
    101  * required license or other approval from the U. S. Department of Commerce or
    102  * any other agency or department of the United States Government. In the
    103  * event Licensee exports any such software from the United States or
    104  * re-exports any such software from a foreign destination, Licensee shall
    105  * ensure that the distribution and export/re-export of the software is in
    106  * compliance with all laws, regulations, orders, or other restrictions of the
    107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    108  * any of its subsidiaries will export/re-export any technical data, process,
    109  * software, or service, directly or indirectly, to any country for which the
    110  * United States government or any agency thereof requires an export license,
    111  * other governmental approval, or letter of assurance, without first obtaining
    112  * such license, approval or letter.
    113  *
    114  *****************************************************************************
    115  *
    116  * Alternatively, you may choose to be licensed under the terms of the
    117  * following license:
    118  *
    119  * Redistribution and use in source and binary forms, with or without
    120  * modification, are permitted provided that the following conditions
    121  * are met:
    122  * 1. Redistributions of source code must retain the above copyright
    123  *    notice, this list of conditions, and the following disclaimer,
    124  *    without modification.
    125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
    126  *    substantially similar to the "NO WARRANTY" disclaimer below
    127  *    ("Disclaimer") and any redistribution must be conditioned upon
    128  *    including a substantially similar Disclaimer requirement for further
    129  *    binary redistribution.
    130  * 3. Neither the names of the above-listed copyright holders nor the names
    131  *    of any contributors may be used to endorse or promote products derived
    132  *    from this software without specific prior written permission.
    133  *
    134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    145  *
    146  * Alternatively, you may choose to be licensed under the terms of the
    147  * GNU General Public License ("GPL") version 2 as published by the Free
    148  * Software Foundation.
    149  *
    150  *****************************************************************************/
    151 
    152 #include "acpi.h"
    153 #include "accommon.h"
    154 #include "acinterp.h"
    155 #include "acevents.h"
    156 
    157 #define _COMPONENT          ACPI_EXECUTER
    158         ACPI_MODULE_NAME    ("exmutex")
    159 
    160 /* Local prototypes */
    161 
    162 static void
    163 AcpiExLinkMutex (
    164     ACPI_OPERAND_OBJECT     *ObjDesc,
    165     ACPI_THREAD_STATE       *Thread);
    166 
    167 
    168 /*******************************************************************************
    169  *
    170  * FUNCTION:    AcpiExUnlinkMutex
    171  *
    172  * PARAMETERS:  ObjDesc             - The mutex to be unlinked
    173  *
    174  * RETURN:      None
    175  *
    176  * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list
    177  *
    178  ******************************************************************************/
    179 
    180 void
    181 AcpiExUnlinkMutex (
    182     ACPI_OPERAND_OBJECT     *ObjDesc)
    183 {
    184     ACPI_THREAD_STATE       *Thread = ObjDesc->Mutex.OwnerThread;
    185 
    186 
    187     if (!Thread)
    188     {
    189         return;
    190     }
    191 
    192     /* Doubly linked list */
    193 
    194     if (ObjDesc->Mutex.Next)
    195     {
    196         (ObjDesc->Mutex.Next)->Mutex.Prev = ObjDesc->Mutex.Prev;
    197     }
    198 
    199     if (ObjDesc->Mutex.Prev)
    200     {
    201         (ObjDesc->Mutex.Prev)->Mutex.Next = ObjDesc->Mutex.Next;
    202 
    203         /*
    204          * Migrate the previous sync level associated with this mutex to
    205          * the previous mutex on the list so that it may be preserved.
    206          * This handles the case where several mutexes have been acquired
    207          * at the same level, but are not released in opposite order.
    208          */
    209         (ObjDesc->Mutex.Prev)->Mutex.OriginalSyncLevel =
    210             ObjDesc->Mutex.OriginalSyncLevel;
    211     }
    212     else
    213     {
    214         Thread->AcquiredMutexList = ObjDesc->Mutex.Next;
    215     }
    216 }
    217 
    218 
    219 /*******************************************************************************
    220  *
    221  * FUNCTION:    AcpiExLinkMutex
    222  *
    223  * PARAMETERS:  ObjDesc             - The mutex to be linked
    224  *              Thread              - Current executing thread object
    225  *
    226  * RETURN:      None
    227  *
    228  * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk
    229  *
    230  ******************************************************************************/
    231 
    232 static void
    233 AcpiExLinkMutex (
    234     ACPI_OPERAND_OBJECT     *ObjDesc,
    235     ACPI_THREAD_STATE       *Thread)
    236 {
    237     ACPI_OPERAND_OBJECT     *ListHead;
    238 
    239 
    240     ListHead = Thread->AcquiredMutexList;
    241 
    242     /* This object will be the first object in the list */
    243 
    244     ObjDesc->Mutex.Prev = NULL;
    245     ObjDesc->Mutex.Next = ListHead;
    246 
    247     /* Update old first object to point back to this object */
    248 
    249     if (ListHead)
    250     {
    251         ListHead->Mutex.Prev = ObjDesc;
    252     }
    253 
    254     /* Update list head */
    255 
    256     Thread->AcquiredMutexList = ObjDesc;
    257 }
    258 
    259 
    260 /*******************************************************************************
    261  *
    262  * FUNCTION:    AcpiExAcquireMutexObject
    263  *
    264  * PARAMETERS:  Timeout             - Timeout in milliseconds
    265  *              ObjDesc             - Mutex object
    266  *              ThreadId            - Current thread state
    267  *
    268  * RETURN:      Status
    269  *
    270  * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common
    271  *              path that supports multiple acquires by the same thread.
    272  *
    273  * MUTEX:       Interpreter must be locked
    274  *
    275  * NOTE: This interface is called from three places:
    276  * 1) From AcpiExAcquireMutex, via an AML Acquire() operator
    277  * 2) From AcpiExAcquireGlobalLock when an AML Field access requires the
    278  *    global lock
    279  * 3) From the external interface, AcpiAcquireGlobalLock
    280  *
    281  ******************************************************************************/
    282 
    283 ACPI_STATUS
    284 AcpiExAcquireMutexObject (
    285     UINT16                  Timeout,
    286     ACPI_OPERAND_OBJECT     *ObjDesc,
    287     ACPI_THREAD_ID          ThreadId)
    288 {
    289     ACPI_STATUS             Status;
    290 
    291 
    292     ACPI_FUNCTION_TRACE_PTR (ExAcquireMutexObject, ObjDesc);
    293 
    294 
    295     if (!ObjDesc)
    296     {
    297         return_ACPI_STATUS (AE_BAD_PARAMETER);
    298     }
    299 
    300     /* Support for multiple acquires by the owning thread */
    301 
    302     if (ObjDesc->Mutex.ThreadId == ThreadId)
    303     {
    304         /*
    305          * The mutex is already owned by this thread, just increment the
    306          * acquisition depth
    307          */
    308         ObjDesc->Mutex.AcquisitionDepth++;
    309         return_ACPI_STATUS (AE_OK);
    310     }
    311 
    312     /* Acquire the mutex, wait if necessary. Special case for Global Lock */
    313 
    314     if (ObjDesc == AcpiGbl_GlobalLockMutex)
    315     {
    316         Status = AcpiEvAcquireGlobalLock (Timeout);
    317     }
    318     else
    319     {
    320         Status = AcpiExSystemWaitMutex (ObjDesc->Mutex.OsMutex, Timeout);
    321     }
    322 
    323     if (ACPI_FAILURE (Status))
    324     {
    325         /* Includes failure from a timeout on TimeDesc */
    326 
    327         return_ACPI_STATUS (Status);
    328     }
    329 
    330     /* Acquired the mutex: update mutex object */
    331 
    332     ObjDesc->Mutex.ThreadId = ThreadId;
    333     ObjDesc->Mutex.AcquisitionDepth = 1;
    334     ObjDesc->Mutex.OriginalSyncLevel = 0;
    335     ObjDesc->Mutex.OwnerThread = NULL;      /* Used only for AML Acquire() */
    336 
    337     return_ACPI_STATUS (AE_OK);
    338 }
    339 
    340 
    341 /*******************************************************************************
    342  *
    343  * FUNCTION:    AcpiExAcquireMutex
    344  *
    345  * PARAMETERS:  TimeDesc            - Timeout integer
    346  *              ObjDesc             - Mutex object
    347  *              WalkState           - Current method execution state
    348  *
    349  * RETURN:      Status
    350  *
    351  * DESCRIPTION: Acquire an AML mutex
    352  *
    353  ******************************************************************************/
    354 
    355 ACPI_STATUS
    356 AcpiExAcquireMutex (
    357     ACPI_OPERAND_OBJECT     *TimeDesc,
    358     ACPI_OPERAND_OBJECT     *ObjDesc,
    359     ACPI_WALK_STATE         *WalkState)
    360 {
    361     ACPI_STATUS             Status;
    362 
    363 
    364     ACPI_FUNCTION_TRACE_PTR (ExAcquireMutex, ObjDesc);
    365 
    366 
    367     if (!ObjDesc)
    368     {
    369         return_ACPI_STATUS (AE_BAD_PARAMETER);
    370     }
    371 
    372     /* Must have a valid thread state struct */
    373 
    374     if (!WalkState->Thread)
    375     {
    376         ACPI_ERROR ((AE_INFO,
    377             "Cannot acquire Mutex [%4.4s], null thread info",
    378             AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
    379         return_ACPI_STATUS (AE_AML_INTERNAL);
    380     }
    381 
    382     /*
    383      * Current sync level must be less than or equal to the sync level
    384      * of the mutex. This mechanism provides some deadlock prevention.
    385      */
    386     if (WalkState->Thread->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel)
    387     {
    388         ACPI_ERROR ((AE_INFO,
    389             "Cannot acquire Mutex [%4.4s], "
    390             "current SyncLevel is too large (%u)",
    391             AcpiUtGetNodeName (ObjDesc->Mutex.Node),
    392             WalkState->Thread->CurrentSyncLevel));
    393         return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
    394     }
    395 
    396     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    397         "Acquiring: Mutex SyncLevel %u, Thread SyncLevel %u, "
    398         "Depth %u TID %p\n",
    399         ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel,
    400         ObjDesc->Mutex.AcquisitionDepth, WalkState->Thread));
    401 
    402     Status = AcpiExAcquireMutexObject ((UINT16) TimeDesc->Integer.Value,
    403         ObjDesc, WalkState->Thread->ThreadId);
    404 
    405     if (ACPI_SUCCESS (Status) && ObjDesc->Mutex.AcquisitionDepth == 1)
    406     {
    407         /* Save Thread object, original/current sync levels */
    408 
    409         ObjDesc->Mutex.OwnerThread = WalkState->Thread;
    410         ObjDesc->Mutex.OriginalSyncLevel =
    411             WalkState->Thread->CurrentSyncLevel;
    412         WalkState->Thread->CurrentSyncLevel =
    413             ObjDesc->Mutex.SyncLevel;
    414 
    415         /* Link the mutex to the current thread for force-unlock at method exit */
    416 
    417         AcpiExLinkMutex (ObjDesc, WalkState->Thread);
    418     }
    419 
    420     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    421         "Acquired: Mutex SyncLevel %u, Thread SyncLevel %u, Depth %u\n",
    422         ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel,
    423         ObjDesc->Mutex.AcquisitionDepth));
    424 
    425     return_ACPI_STATUS (Status);
    426 }
    427 
    428 
    429 /*******************************************************************************
    430  *
    431  * FUNCTION:    AcpiExReleaseMutexObject
    432  *
    433  * PARAMETERS:  ObjDesc             - The object descriptor for this op
    434  *
    435  * RETURN:      Status
    436  *
    437  * DESCRIPTION: Release a previously acquired Mutex, low level interface.
    438  *              Provides a common path that supports multiple releases (after
    439  *              previous multiple acquires) by the same thread.
    440  *
    441  * MUTEX:       Interpreter must be locked
    442  *
    443  * NOTE: This interface is called from three places:
    444  * 1) From AcpiExReleaseMutex, via an AML Acquire() operator
    445  * 2) From AcpiExReleaseGlobalLock when an AML Field access requires the
    446  *    global lock
    447  * 3) From the external interface, AcpiReleaseGlobalLock
    448  *
    449  ******************************************************************************/
    450 
    451 ACPI_STATUS
    452 AcpiExReleaseMutexObject (
    453     ACPI_OPERAND_OBJECT     *ObjDesc)
    454 {
    455     ACPI_STATUS             Status = AE_OK;
    456 
    457 
    458     ACPI_FUNCTION_TRACE (ExReleaseMutexObject);
    459 
    460 
    461     if (ObjDesc->Mutex.AcquisitionDepth == 0)
    462     {
    463         return_ACPI_STATUS (AE_NOT_ACQUIRED);
    464     }
    465 
    466     /* Match multiple Acquires with multiple Releases */
    467 
    468     ObjDesc->Mutex.AcquisitionDepth--;
    469     if (ObjDesc->Mutex.AcquisitionDepth != 0)
    470     {
    471         /* Just decrement the depth and return */
    472 
    473         return_ACPI_STATUS (AE_OK);
    474     }
    475 
    476     if (ObjDesc->Mutex.OwnerThread)
    477     {
    478         /* Unlink the mutex from the owner's list */
    479 
    480         AcpiExUnlinkMutex (ObjDesc);
    481         ObjDesc->Mutex.OwnerThread = NULL;
    482     }
    483 
    484     /* Release the mutex, special case for Global Lock */
    485 
    486     if (ObjDesc == AcpiGbl_GlobalLockMutex)
    487     {
    488         Status = AcpiEvReleaseGlobalLock ();
    489     }
    490     else
    491     {
    492         AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex);
    493     }
    494 
    495     /* Clear mutex info */
    496 
    497     ObjDesc->Mutex.ThreadId = 0;
    498     return_ACPI_STATUS (Status);
    499 }
    500 
    501 
    502 /*******************************************************************************
    503  *
    504  * FUNCTION:    AcpiExReleaseMutex
    505  *
    506  * PARAMETERS:  ObjDesc             - The object descriptor for this op
    507  *              WalkState           - Current method execution state
    508  *
    509  * RETURN:      Status
    510  *
    511  * DESCRIPTION: Release a previously acquired Mutex.
    512  *
    513  ******************************************************************************/
    514 
    515 ACPI_STATUS
    516 AcpiExReleaseMutex (
    517     ACPI_OPERAND_OBJECT     *ObjDesc,
    518     ACPI_WALK_STATE         *WalkState)
    519 {
    520     UINT8                   PreviousSyncLevel;
    521     ACPI_THREAD_STATE       *OwnerThread;
    522     ACPI_STATUS             Status = AE_OK;
    523 
    524 
    525     ACPI_FUNCTION_TRACE (ExReleaseMutex);
    526 
    527 
    528     if (!ObjDesc)
    529     {
    530         return_ACPI_STATUS (AE_BAD_PARAMETER);
    531     }
    532 
    533     OwnerThread = ObjDesc->Mutex.OwnerThread;
    534 
    535     /* The mutex must have been previously acquired in order to release it */
    536 
    537     if (!OwnerThread)
    538     {
    539         ACPI_ERROR ((AE_INFO,
    540             "Cannot release Mutex [%4.4s], not acquired",
    541             AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
    542         return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED);
    543     }
    544 
    545     /* Must have a valid thread ID */
    546 
    547     if (!WalkState->Thread)
    548     {
    549         ACPI_ERROR ((AE_INFO,
    550             "Cannot release Mutex [%4.4s], null thread info",
    551             AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
    552         return_ACPI_STATUS (AE_AML_INTERNAL);
    553     }
    554 
    555     /*
    556      * The Mutex is owned, but this thread must be the owner.
    557      * Special case for Global Lock, any thread can release
    558      */
    559     if ((OwnerThread->ThreadId != WalkState->Thread->ThreadId) &&
    560         (ObjDesc != AcpiGbl_GlobalLockMutex))
    561     {
    562         ACPI_ERROR ((AE_INFO,
    563             "Thread %u cannot release Mutex [%4.4s] acquired by thread %u",
    564             (UINT32) WalkState->Thread->ThreadId,
    565             AcpiUtGetNodeName (ObjDesc->Mutex.Node),
    566             (UINT32) OwnerThread->ThreadId));
    567         return_ACPI_STATUS (AE_AML_NOT_OWNER);
    568     }
    569 
    570     /*
    571      * The sync level of the mutex must be equal to the current sync level. In
    572      * other words, the current level means that at least one mutex at that
    573      * level is currently being held. Attempting to release a mutex of a
    574      * different level can only mean that the mutex ordering rule is being
    575      * violated. This behavior is clarified in ACPI 4.0 specification.
    576      */
    577     if (ObjDesc->Mutex.SyncLevel != OwnerThread->CurrentSyncLevel)
    578     {
    579         ACPI_ERROR ((AE_INFO,
    580             "Cannot release Mutex [%4.4s], SyncLevel mismatch: "
    581             "mutex %u current %u",
    582             AcpiUtGetNodeName (ObjDesc->Mutex.Node),
    583             ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel));
    584         return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
    585     }
    586 
    587     /*
    588      * Get the previous SyncLevel from the head of the acquired mutex list.
    589      * This handles the case where several mutexes at the same level have been
    590      * acquired, but are not released in reverse order.
    591      */
    592     PreviousSyncLevel =
    593         OwnerThread->AcquiredMutexList->Mutex.OriginalSyncLevel;
    594 
    595     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    596         "Releasing: Object SyncLevel %u, Thread SyncLevel %u, "
    597         "Prev SyncLevel %u, Depth %u TID %p\n",
    598         ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel,
    599         PreviousSyncLevel, ObjDesc->Mutex.AcquisitionDepth,
    600         WalkState->Thread));
    601 
    602     Status = AcpiExReleaseMutexObject (ObjDesc);
    603     if (ACPI_FAILURE (Status))
    604     {
    605         return_ACPI_STATUS (Status);
    606     }
    607 
    608     if (ObjDesc->Mutex.AcquisitionDepth == 0)
    609     {
    610         /* Restore the previous SyncLevel */
    611 
    612         OwnerThread->CurrentSyncLevel = PreviousSyncLevel;
    613     }
    614 
    615     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    616         "Released: Object SyncLevel %u, Thread SyncLevel, %u, "
    617         "Prev SyncLevel %u, Depth %u\n",
    618         ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel,
    619         PreviousSyncLevel, ObjDesc->Mutex.AcquisitionDepth));
    620 
    621     return_ACPI_STATUS (Status);
    622 }
    623 
    624 
    625 /*******************************************************************************
    626  *
    627  * FUNCTION:    AcpiExReleaseAllMutexes
    628  *
    629  * PARAMETERS:  Thread              - Current executing thread object
    630  *
    631  * RETURN:      Status
    632  *
    633  * DESCRIPTION: Release all mutexes held by this thread
    634  *
    635  * NOTE: This function is called as the thread is exiting the interpreter.
    636  * Mutexes are not released when an individual control method is exited, but
    637  * only when the parent thread actually exits the interpreter. This allows one
    638  * method to acquire a mutex, and a different method to release it, as long as
    639  * this is performed underneath a single parent control method.
    640  *
    641  ******************************************************************************/
    642 
    643 void
    644 AcpiExReleaseAllMutexes (
    645     ACPI_THREAD_STATE       *Thread)
    646 {
    647     ACPI_OPERAND_OBJECT     *Next = Thread->AcquiredMutexList;
    648     ACPI_OPERAND_OBJECT     *ObjDesc;
    649 
    650 
    651     ACPI_FUNCTION_TRACE (ExReleaseAllMutexes);
    652 
    653 
    654     /* Traverse the list of owned mutexes, releasing each one */
    655 
    656     while (Next)
    657     {
    658         ObjDesc = Next;
    659         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    660             "Mutex [%4.4s] force-release, SyncLevel %u Depth %u\n",
    661             ObjDesc->Mutex.Node->Name.Ascii, ObjDesc->Mutex.SyncLevel,
    662             ObjDesc->Mutex.AcquisitionDepth));
    663 
    664         /* Release the mutex, special case for Global Lock */
    665 
    666         if (ObjDesc == AcpiGbl_GlobalLockMutex)
    667         {
    668             /* Ignore errors */
    669 
    670             (void) AcpiEvReleaseGlobalLock ();
    671         }
    672         else
    673         {
    674             AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex);
    675         }
    676 
    677         /* Update Thread SyncLevel (Last mutex is the important one) */
    678 
    679         Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel;
    680 
    681         /* Mark mutex unowned */
    682 
    683         Next = ObjDesc->Mutex.Next;
    684 
    685         ObjDesc->Mutex.Prev = NULL;
    686         ObjDesc->Mutex.Next = NULL;
    687         ObjDesc->Mutex.AcquisitionDepth = 0;
    688         ObjDesc->Mutex.OwnerThread = NULL;
    689         ObjDesc->Mutex.ThreadId = 0;
    690     }
    691 
    692     return_VOID;
    693 }
    694