Subversion Repositories Kolibri OS

Rev

Rev 1498 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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