xref: /onnv-gate/usr/src/uts/intel/io/acpica/dispatcher/dsmethod.c (revision 11225:eb6056029d84)
17851SDana.Myers@Sun.COM /******************************************************************************
27851SDana.Myers@Sun.COM  *
37851SDana.Myers@Sun.COM  * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
47851SDana.Myers@Sun.COM  *
57851SDana.Myers@Sun.COM  *****************************************************************************/
67851SDana.Myers@Sun.COM 
77851SDana.Myers@Sun.COM /******************************************************************************
87851SDana.Myers@Sun.COM  *
97851SDana.Myers@Sun.COM  * 1. Copyright Notice
107851SDana.Myers@Sun.COM  *
119980SDana.Myers@Sun.COM  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
127851SDana.Myers@Sun.COM  * All rights reserved.
137851SDana.Myers@Sun.COM  *
147851SDana.Myers@Sun.COM  * 2. License
157851SDana.Myers@Sun.COM  *
167851SDana.Myers@Sun.COM  * 2.1. This is your license from Intel Corp. under its intellectual property
177851SDana.Myers@Sun.COM  * rights.  You may have additional license terms from the party that provided
187851SDana.Myers@Sun.COM  * you this software, covering your right to use that party's intellectual
197851SDana.Myers@Sun.COM  * property rights.
207851SDana.Myers@Sun.COM  *
217851SDana.Myers@Sun.COM  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
227851SDana.Myers@Sun.COM  * copy of the source code appearing in this file ("Covered Code") an
237851SDana.Myers@Sun.COM  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
247851SDana.Myers@Sun.COM  * base code distributed originally by Intel ("Original Intel Code") to copy,
257851SDana.Myers@Sun.COM  * make derivatives, distribute, use and display any portion of the Covered
267851SDana.Myers@Sun.COM  * Code in any form, with the right to sublicense such rights; and
277851SDana.Myers@Sun.COM  *
287851SDana.Myers@Sun.COM  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
297851SDana.Myers@Sun.COM  * license (with the right to sublicense), under only those claims of Intel
307851SDana.Myers@Sun.COM  * patents that are infringed by the Original Intel Code, to make, use, sell,
317851SDana.Myers@Sun.COM  * offer to sell, and import the Covered Code and derivative works thereof
327851SDana.Myers@Sun.COM  * solely to the minimum extent necessary to exercise the above copyright
337851SDana.Myers@Sun.COM  * license, and in no event shall the patent license extend to any additions
347851SDana.Myers@Sun.COM  * to or modifications of the Original Intel Code.  No other license or right
357851SDana.Myers@Sun.COM  * is granted directly or by implication, estoppel or otherwise;
367851SDana.Myers@Sun.COM  *
377851SDana.Myers@Sun.COM  * The above copyright and patent license is granted only if the following
387851SDana.Myers@Sun.COM  * conditions are met:
397851SDana.Myers@Sun.COM  *
407851SDana.Myers@Sun.COM  * 3. Conditions
417851SDana.Myers@Sun.COM  *
427851SDana.Myers@Sun.COM  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
437851SDana.Myers@Sun.COM  * Redistribution of source code of any substantial portion of the Covered
447851SDana.Myers@Sun.COM  * Code or modification with rights to further distribute source must include
457851SDana.Myers@Sun.COM  * the above Copyright Notice, the above License, this list of Conditions,
467851SDana.Myers@Sun.COM  * and the following Disclaimer and Export Compliance provision.  In addition,
477851SDana.Myers@Sun.COM  * Licensee must cause all Covered Code to which Licensee contributes to
487851SDana.Myers@Sun.COM  * contain a file documenting the changes Licensee made to create that Covered
497851SDana.Myers@Sun.COM  * Code and the date of any change.  Licensee must include in that file the
507851SDana.Myers@Sun.COM  * documentation of any changes made by any predecessor Licensee.  Licensee
517851SDana.Myers@Sun.COM  * must include a prominent statement that the modification is derived,
527851SDana.Myers@Sun.COM  * directly or indirectly, from Original Intel Code.
537851SDana.Myers@Sun.COM  *
547851SDana.Myers@Sun.COM  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
557851SDana.Myers@Sun.COM  * Redistribution of source code of any substantial portion of the Covered
567851SDana.Myers@Sun.COM  * Code or modification without rights to further distribute source must
577851SDana.Myers@Sun.COM  * include the following Disclaimer and Export Compliance provision in the
587851SDana.Myers@Sun.COM  * documentation and/or other materials provided with distribution.  In
597851SDana.Myers@Sun.COM  * addition, Licensee may not authorize further sublicense of source of any
607851SDana.Myers@Sun.COM  * portion of the Covered Code, and must include terms to the effect that the
617851SDana.Myers@Sun.COM  * license from Licensee to its licensee is limited to the intellectual
627851SDana.Myers@Sun.COM  * property embodied in the software Licensee provides to its licensee, and
637851SDana.Myers@Sun.COM  * not to intellectual property embodied in modifications its licensee may
647851SDana.Myers@Sun.COM  * make.
657851SDana.Myers@Sun.COM  *
667851SDana.Myers@Sun.COM  * 3.3. Redistribution of Executable. Redistribution in executable form of any
677851SDana.Myers@Sun.COM  * substantial portion of the Covered Code or modification must reproduce the
687851SDana.Myers@Sun.COM  * above Copyright Notice, and the following Disclaimer and Export Compliance
697851SDana.Myers@Sun.COM  * provision in the documentation and/or other materials provided with the
707851SDana.Myers@Sun.COM  * distribution.
717851SDana.Myers@Sun.COM  *
727851SDana.Myers@Sun.COM  * 3.4. Intel retains all right, title, and interest in and to the Original
737851SDana.Myers@Sun.COM  * Intel Code.
747851SDana.Myers@Sun.COM  *
757851SDana.Myers@Sun.COM  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
767851SDana.Myers@Sun.COM  * Intel shall be used in advertising or otherwise to promote the sale, use or
777851SDana.Myers@Sun.COM  * other dealings in products derived from or relating to the Covered Code
787851SDana.Myers@Sun.COM  * without prior written authorization from Intel.
797851SDana.Myers@Sun.COM  *
807851SDana.Myers@Sun.COM  * 4. Disclaimer and Export Compliance
817851SDana.Myers@Sun.COM  *
827851SDana.Myers@Sun.COM  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
837851SDana.Myers@Sun.COM  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
847851SDana.Myers@Sun.COM  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
857851SDana.Myers@Sun.COM  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
867851SDana.Myers@Sun.COM  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
877851SDana.Myers@Sun.COM  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
887851SDana.Myers@Sun.COM  * PARTICULAR PURPOSE.
897851SDana.Myers@Sun.COM  *
907851SDana.Myers@Sun.COM  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
917851SDana.Myers@Sun.COM  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
927851SDana.Myers@Sun.COM  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
937851SDana.Myers@Sun.COM  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
947851SDana.Myers@Sun.COM  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
957851SDana.Myers@Sun.COM  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
967851SDana.Myers@Sun.COM  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
977851SDana.Myers@Sun.COM  * LIMITED REMEDY.
987851SDana.Myers@Sun.COM  *
997851SDana.Myers@Sun.COM  * 4.3. Licensee shall not export, either directly or indirectly, any of this
1007851SDana.Myers@Sun.COM  * software or system incorporating such software without first obtaining any
1017851SDana.Myers@Sun.COM  * required license or other approval from the U. S. Department of Commerce or
1027851SDana.Myers@Sun.COM  * any other agency or department of the United States Government.  In the
1037851SDana.Myers@Sun.COM  * event Licensee exports any such software from the United States or
1047851SDana.Myers@Sun.COM  * re-exports any such software from a foreign destination, Licensee shall
1057851SDana.Myers@Sun.COM  * ensure that the distribution and export/re-export of the software is in
1067851SDana.Myers@Sun.COM  * compliance with all laws, regulations, orders, or other restrictions of the
1077851SDana.Myers@Sun.COM  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
1087851SDana.Myers@Sun.COM  * any of its subsidiaries will export/re-export any technical data, process,
1097851SDana.Myers@Sun.COM  * software, or service, directly or indirectly, to any country for which the
1107851SDana.Myers@Sun.COM  * United States government or any agency thereof requires an export license,
1117851SDana.Myers@Sun.COM  * other governmental approval, or letter of assurance, without first obtaining
1127851SDana.Myers@Sun.COM  * such license, approval or letter.
1137851SDana.Myers@Sun.COM  *
1147851SDana.Myers@Sun.COM  *****************************************************************************/
1157851SDana.Myers@Sun.COM 
1167851SDana.Myers@Sun.COM #define __DSMETHOD_C__
1177851SDana.Myers@Sun.COM 
1187851SDana.Myers@Sun.COM #include "acpi.h"
1199980SDana.Myers@Sun.COM #include "accommon.h"
1207851SDana.Myers@Sun.COM #include "amlcode.h"
1217851SDana.Myers@Sun.COM #include "acdispat.h"
1227851SDana.Myers@Sun.COM #include "acinterp.h"
1237851SDana.Myers@Sun.COM #include "acnamesp.h"
1247851SDana.Myers@Sun.COM #include "acdisasm.h"
1257851SDana.Myers@Sun.COM 
1267851SDana.Myers@Sun.COM 
1277851SDana.Myers@Sun.COM #define _COMPONENT          ACPI_DISPATCHER
1287851SDana.Myers@Sun.COM         ACPI_MODULE_NAME    ("dsmethod")
1297851SDana.Myers@Sun.COM 
1307851SDana.Myers@Sun.COM /* Local prototypes */
1317851SDana.Myers@Sun.COM 
1327851SDana.Myers@Sun.COM static ACPI_STATUS
1337851SDana.Myers@Sun.COM AcpiDsCreateMethodMutex (
1347851SDana.Myers@Sun.COM     ACPI_OPERAND_OBJECT     *MethodDesc);
1357851SDana.Myers@Sun.COM 
1367851SDana.Myers@Sun.COM 
1377851SDana.Myers@Sun.COM /*******************************************************************************
1387851SDana.Myers@Sun.COM  *
1397851SDana.Myers@Sun.COM  * FUNCTION:    AcpiDsMethodError
1407851SDana.Myers@Sun.COM  *
1417851SDana.Myers@Sun.COM  * PARAMETERS:  Status          - Execution status
1427851SDana.Myers@Sun.COM  *              WalkState       - Current state
1437851SDana.Myers@Sun.COM  *
1447851SDana.Myers@Sun.COM  * RETURN:      Status
1457851SDana.Myers@Sun.COM  *
1467851SDana.Myers@Sun.COM  * DESCRIPTION: Called on method error. Invoke the global exception handler if
1477851SDana.Myers@Sun.COM  *              present, dump the method data if the disassembler is configured
1487851SDana.Myers@Sun.COM  *
1497851SDana.Myers@Sun.COM  *              Note: Allows the exception handler to change the status code
1507851SDana.Myers@Sun.COM  *
1517851SDana.Myers@Sun.COM  ******************************************************************************/
1527851SDana.Myers@Sun.COM 
1537851SDana.Myers@Sun.COM ACPI_STATUS
AcpiDsMethodError(ACPI_STATUS Status,ACPI_WALK_STATE * WalkState)1547851SDana.Myers@Sun.COM AcpiDsMethodError (
1557851SDana.Myers@Sun.COM     ACPI_STATUS             Status,
1567851SDana.Myers@Sun.COM     ACPI_WALK_STATE         *WalkState)
1577851SDana.Myers@Sun.COM {
1587851SDana.Myers@Sun.COM     ACPI_FUNCTION_ENTRY ();
1597851SDana.Myers@Sun.COM 
1607851SDana.Myers@Sun.COM 
1617851SDana.Myers@Sun.COM     /* Ignore AE_OK and control exception codes */
1627851SDana.Myers@Sun.COM 
1637851SDana.Myers@Sun.COM     if (ACPI_SUCCESS (Status) ||
1647851SDana.Myers@Sun.COM         (Status & AE_CODE_CONTROL))
1657851SDana.Myers@Sun.COM     {
1667851SDana.Myers@Sun.COM         return (Status);
1677851SDana.Myers@Sun.COM     }
1687851SDana.Myers@Sun.COM 
1697851SDana.Myers@Sun.COM     /* Invoke the global exception handler */
1707851SDana.Myers@Sun.COM 
1717851SDana.Myers@Sun.COM     if (AcpiGbl_ExceptionHandler)
1727851SDana.Myers@Sun.COM     {
1737851SDana.Myers@Sun.COM         /* Exit the interpreter, allow handler to execute methods */
1747851SDana.Myers@Sun.COM 
1757851SDana.Myers@Sun.COM         AcpiExExitInterpreter ();
1767851SDana.Myers@Sun.COM 
1777851SDana.Myers@Sun.COM         /*
1787851SDana.Myers@Sun.COM          * Handler can map the exception code to anything it wants, including
1797851SDana.Myers@Sun.COM          * AE_OK, in which case the executing method will not be aborted.
1807851SDana.Myers@Sun.COM          */
1817851SDana.Myers@Sun.COM         Status = AcpiGbl_ExceptionHandler (Status,
1827851SDana.Myers@Sun.COM                     WalkState->MethodNode ?
1837851SDana.Myers@Sun.COM                         WalkState->MethodNode->Name.Integer : 0,
1847851SDana.Myers@Sun.COM                     WalkState->Opcode, WalkState->AmlOffset, NULL);
1857851SDana.Myers@Sun.COM         AcpiExEnterInterpreter ();
1867851SDana.Myers@Sun.COM     }
1877851SDana.Myers@Sun.COM 
1887851SDana.Myers@Sun.COM     AcpiDsClearImplicitReturn (WalkState);
1897851SDana.Myers@Sun.COM 
1907851SDana.Myers@Sun.COM #ifdef ACPI_DISASSEMBLER
1917851SDana.Myers@Sun.COM     if (ACPI_FAILURE (Status))
1927851SDana.Myers@Sun.COM     {
1937851SDana.Myers@Sun.COM         /* Display method locals/args if disassembler is present */
1947851SDana.Myers@Sun.COM 
1957851SDana.Myers@Sun.COM         AcpiDmDumpMethodInfo (Status, WalkState, WalkState->Op);
1967851SDana.Myers@Sun.COM     }
1977851SDana.Myers@Sun.COM #endif
1987851SDana.Myers@Sun.COM 
1997851SDana.Myers@Sun.COM     return (Status);
2007851SDana.Myers@Sun.COM }
2017851SDana.Myers@Sun.COM 
2027851SDana.Myers@Sun.COM 
2037851SDana.Myers@Sun.COM /*******************************************************************************
2047851SDana.Myers@Sun.COM  *
2057851SDana.Myers@Sun.COM  * FUNCTION:    AcpiDsCreateMethodMutex
2067851SDana.Myers@Sun.COM  *
2077851SDana.Myers@Sun.COM  * PARAMETERS:  ObjDesc             - The method object
2087851SDana.Myers@Sun.COM  *
2097851SDana.Myers@Sun.COM  * RETURN:      Status
2107851SDana.Myers@Sun.COM  *
2117851SDana.Myers@Sun.COM  * DESCRIPTION: Create a mutex object for a serialized control method
2127851SDana.Myers@Sun.COM  *
2137851SDana.Myers@Sun.COM  ******************************************************************************/
2147851SDana.Myers@Sun.COM 
2157851SDana.Myers@Sun.COM static ACPI_STATUS
AcpiDsCreateMethodMutex(ACPI_OPERAND_OBJECT * MethodDesc)2167851SDana.Myers@Sun.COM AcpiDsCreateMethodMutex (
2177851SDana.Myers@Sun.COM     ACPI_OPERAND_OBJECT     *MethodDesc)
2187851SDana.Myers@Sun.COM {
2197851SDana.Myers@Sun.COM     ACPI_OPERAND_OBJECT     *MutexDesc;
2207851SDana.Myers@Sun.COM     ACPI_STATUS             Status;
2217851SDana.Myers@Sun.COM 
2227851SDana.Myers@Sun.COM 
2237851SDana.Myers@Sun.COM     ACPI_FUNCTION_TRACE (DsCreateMethodMutex);
2247851SDana.Myers@Sun.COM 
2257851SDana.Myers@Sun.COM 
2267851SDana.Myers@Sun.COM     /* Create the new mutex object */
2277851SDana.Myers@Sun.COM 
2287851SDana.Myers@Sun.COM     MutexDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX);
2297851SDana.Myers@Sun.COM     if (!MutexDesc)
2307851SDana.Myers@Sun.COM     {
2317851SDana.Myers@Sun.COM         return_ACPI_STATUS (AE_NO_MEMORY);
2327851SDana.Myers@Sun.COM     }
2337851SDana.Myers@Sun.COM 
2347851SDana.Myers@Sun.COM     /* Create the actual OS Mutex */
2357851SDana.Myers@Sun.COM 
2367851SDana.Myers@Sun.COM     Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex);
2377851SDana.Myers@Sun.COM     if (ACPI_FAILURE (Status))
2387851SDana.Myers@Sun.COM     {
2397851SDana.Myers@Sun.COM         return_ACPI_STATUS (Status);
2407851SDana.Myers@Sun.COM     }
2417851SDana.Myers@Sun.COM 
2427851SDana.Myers@Sun.COM     MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel;
2437851SDana.Myers@Sun.COM     MethodDesc->Method.Mutex = MutexDesc;
2447851SDana.Myers@Sun.COM     return_ACPI_STATUS (AE_OK);
2457851SDana.Myers@Sun.COM }
2467851SDana.Myers@Sun.COM 
2477851SDana.Myers@Sun.COM 
2487851SDana.Myers@Sun.COM /*******************************************************************************
2497851SDana.Myers@Sun.COM  *
2507851SDana.Myers@Sun.COM  * FUNCTION:    AcpiDsBeginMethodExecution
2517851SDana.Myers@Sun.COM  *
2527851SDana.Myers@Sun.COM  * PARAMETERS:  MethodNode          - Node of the method
2537851SDana.Myers@Sun.COM  *              ObjDesc             - The method object
2547851SDana.Myers@Sun.COM  *              WalkState           - current state, NULL if not yet executing
2557851SDana.Myers@Sun.COM  *                                    a method.
2567851SDana.Myers@Sun.COM  *
2577851SDana.Myers@Sun.COM  * RETURN:      Status
2587851SDana.Myers@Sun.COM  *
2597851SDana.Myers@Sun.COM  * DESCRIPTION: Prepare a method for execution.  Parses the method if necessary,
2607851SDana.Myers@Sun.COM  *              increments the thread count, and waits at the method semaphore
2617851SDana.Myers@Sun.COM  *              for clearance to execute.
2627851SDana.Myers@Sun.COM  *
2637851SDana.Myers@Sun.COM  ******************************************************************************/
2647851SDana.Myers@Sun.COM 
2657851SDana.Myers@Sun.COM ACPI_STATUS
AcpiDsBeginMethodExecution(ACPI_NAMESPACE_NODE * MethodNode,ACPI_OPERAND_OBJECT * ObjDesc,ACPI_WALK_STATE * WalkState)2667851SDana.Myers@Sun.COM AcpiDsBeginMethodExecution (
2677851SDana.Myers@Sun.COM     ACPI_NAMESPACE_NODE     *MethodNode,
2687851SDana.Myers@Sun.COM     ACPI_OPERAND_OBJECT     *ObjDesc,
2697851SDana.Myers@Sun.COM     ACPI_WALK_STATE         *WalkState)
2707851SDana.Myers@Sun.COM {
2717851SDana.Myers@Sun.COM     ACPI_STATUS             Status = AE_OK;
2727851SDana.Myers@Sun.COM 
2737851SDana.Myers@Sun.COM 
2747851SDana.Myers@Sun.COM     ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode);
2757851SDana.Myers@Sun.COM 
2767851SDana.Myers@Sun.COM 
2777851SDana.Myers@Sun.COM     if (!MethodNode)
2787851SDana.Myers@Sun.COM     {
2797851SDana.Myers@Sun.COM         return_ACPI_STATUS (AE_NULL_ENTRY);
2807851SDana.Myers@Sun.COM     }
2817851SDana.Myers@Sun.COM 
2827851SDana.Myers@Sun.COM     /* Prevent wraparound of thread count */
2837851SDana.Myers@Sun.COM 
2847851SDana.Myers@Sun.COM     if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX)
2857851SDana.Myers@Sun.COM     {
2867851SDana.Myers@Sun.COM         ACPI_ERROR ((AE_INFO,
2877851SDana.Myers@Sun.COM             "Method reached maximum reentrancy limit (255)"));
2887851SDana.Myers@Sun.COM         return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
2897851SDana.Myers@Sun.COM     }
2907851SDana.Myers@Sun.COM 
2917851SDana.Myers@Sun.COM     /*
2927851SDana.Myers@Sun.COM      * If this method is serialized, we need to acquire the method mutex.
2937851SDana.Myers@Sun.COM      */
2947851SDana.Myers@Sun.COM     if (ObjDesc->Method.MethodFlags & AML_METHOD_SERIALIZED)
2957851SDana.Myers@Sun.COM     {
2967851SDana.Myers@Sun.COM         /*
2977851SDana.Myers@Sun.COM          * Create a mutex for the method if it is defined to be Serialized
2987851SDana.Myers@Sun.COM          * and a mutex has not already been created. We defer the mutex creation
2997851SDana.Myers@Sun.COM          * until a method is actually executed, to minimize the object count
3007851SDana.Myers@Sun.COM          */
3017851SDana.Myers@Sun.COM         if (!ObjDesc->Method.Mutex)
3027851SDana.Myers@Sun.COM         {
3037851SDana.Myers@Sun.COM             Status = AcpiDsCreateMethodMutex (ObjDesc);
3047851SDana.Myers@Sun.COM             if (ACPI_FAILURE (Status))
3057851SDana.Myers@Sun.COM             {
3067851SDana.Myers@Sun.COM                 return_ACPI_STATUS (Status);
3077851SDana.Myers@Sun.COM             }
3087851SDana.Myers@Sun.COM         }
3097851SDana.Myers@Sun.COM 
3107851SDana.Myers@Sun.COM         /*
3117851SDana.Myers@Sun.COM          * The CurrentSyncLevel (per-thread) must be less than or equal to
3127851SDana.Myers@Sun.COM          * the sync level of the method. This mechanism provides some
3137851SDana.Myers@Sun.COM          * deadlock prevention
3147851SDana.Myers@Sun.COM          *
3157851SDana.Myers@Sun.COM          * Top-level method invocation has no walk state at this point
3167851SDana.Myers@Sun.COM          */
3177851SDana.Myers@Sun.COM         if (WalkState &&
3187851SDana.Myers@Sun.COM             (WalkState->Thread->CurrentSyncLevel > ObjDesc->Method.Mutex->Mutex.SyncLevel))
3197851SDana.Myers@Sun.COM         {
3207851SDana.Myers@Sun.COM             ACPI_ERROR ((AE_INFO,
3217851SDana.Myers@Sun.COM                 "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%d)",
3227851SDana.Myers@Sun.COM                 AcpiUtGetNodeName (MethodNode),
3237851SDana.Myers@Sun.COM                 WalkState->Thread->CurrentSyncLevel));
3247851SDana.Myers@Sun.COM 
3257851SDana.Myers@Sun.COM             return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
3267851SDana.Myers@Sun.COM         }
3277851SDana.Myers@Sun.COM 
3287851SDana.Myers@Sun.COM         /*
3297851SDana.Myers@Sun.COM          * Obtain the method mutex if necessary. Do not acquire mutex for a
3307851SDana.Myers@Sun.COM          * recursive call.
3317851SDana.Myers@Sun.COM          */
3327851SDana.Myers@Sun.COM         if (!WalkState ||
3337851SDana.Myers@Sun.COM             !ObjDesc->Method.Mutex->Mutex.ThreadId ||
3347851SDana.Myers@Sun.COM             (WalkState->Thread->ThreadId != ObjDesc->Method.Mutex->Mutex.ThreadId))
3357851SDana.Myers@Sun.COM         {
3367851SDana.Myers@Sun.COM             /*
3377851SDana.Myers@Sun.COM              * Acquire the method mutex. This releases the interpreter if we
3387851SDana.Myers@Sun.COM              * block (and reacquires it before it returns)
3397851SDana.Myers@Sun.COM              */
3407851SDana.Myers@Sun.COM             Status = AcpiExSystemWaitMutex (ObjDesc->Method.Mutex->Mutex.OsMutex,
3417851SDana.Myers@Sun.COM                         ACPI_WAIT_FOREVER);
3427851SDana.Myers@Sun.COM             if (ACPI_FAILURE (Status))
3437851SDana.Myers@Sun.COM             {
3447851SDana.Myers@Sun.COM                 return_ACPI_STATUS (Status);
3457851SDana.Myers@Sun.COM             }
3467851SDana.Myers@Sun.COM 
3477851SDana.Myers@Sun.COM             /* Update the mutex and walk info and save the original SyncLevel */
3487851SDana.Myers@Sun.COM 
3497851SDana.Myers@Sun.COM             if (WalkState)
3507851SDana.Myers@Sun.COM             {
3517851SDana.Myers@Sun.COM                 ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
3527851SDana.Myers@Sun.COM                     WalkState->Thread->CurrentSyncLevel;
3537851SDana.Myers@Sun.COM 
3547851SDana.Myers@Sun.COM                 ObjDesc->Method.Mutex->Mutex.ThreadId = WalkState->Thread->ThreadId;
3557851SDana.Myers@Sun.COM                 WalkState->Thread->CurrentSyncLevel = ObjDesc->Method.SyncLevel;
3567851SDana.Myers@Sun.COM             }
3577851SDana.Myers@Sun.COM             else
3587851SDana.Myers@Sun.COM             {
3597851SDana.Myers@Sun.COM                 ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
3607851SDana.Myers@Sun.COM                     ObjDesc->Method.Mutex->Mutex.SyncLevel;
3617851SDana.Myers@Sun.COM             }
3627851SDana.Myers@Sun.COM         }
3637851SDana.Myers@Sun.COM 
3647851SDana.Myers@Sun.COM         /* Always increase acquisition depth */
3657851SDana.Myers@Sun.COM 
3667851SDana.Myers@Sun.COM         ObjDesc->Method.Mutex->Mutex.AcquisitionDepth++;
3677851SDana.Myers@Sun.COM     }
3687851SDana.Myers@Sun.COM 
3697851SDana.Myers@Sun.COM     /*
3707851SDana.Myers@Sun.COM      * Allocate an Owner ID for this method, only if this is the first thread
3717851SDana.Myers@Sun.COM      * to begin concurrent execution. We only need one OwnerId, even if the
3727851SDana.Myers@Sun.COM      * method is invoked recursively.
3737851SDana.Myers@Sun.COM      */
3747851SDana.Myers@Sun.COM     if (!ObjDesc->Method.OwnerId)
3757851SDana.Myers@Sun.COM     {
3767851SDana.Myers@Sun.COM         Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
3777851SDana.Myers@Sun.COM         if (ACPI_FAILURE (Status))
3787851SDana.Myers@Sun.COM         {
3797851SDana.Myers@Sun.COM             goto Cleanup;
3807851SDana.Myers@Sun.COM         }
3817851SDana.Myers@Sun.COM     }
3827851SDana.Myers@Sun.COM 
3837851SDana.Myers@Sun.COM     /*
3847851SDana.Myers@Sun.COM      * Increment the method parse tree thread count since it has been
3857851SDana.Myers@Sun.COM      * reentered one more time (even if it is the same thread)
3867851SDana.Myers@Sun.COM      */
3877851SDana.Myers@Sun.COM     ObjDesc->Method.ThreadCount++;
3887851SDana.Myers@Sun.COM     AcpiMethodCount++;
3897851SDana.Myers@Sun.COM     return_ACPI_STATUS (Status);
3907851SDana.Myers@Sun.COM 
3917851SDana.Myers@Sun.COM 
3927851SDana.Myers@Sun.COM Cleanup:
3937851SDana.Myers@Sun.COM     /* On error, must release the method mutex (if present) */
3947851SDana.Myers@Sun.COM 
3957851SDana.Myers@Sun.COM     if (ObjDesc->Method.Mutex)
3967851SDana.Myers@Sun.COM     {
3977851SDana.Myers@Sun.COM         AcpiOsReleaseMutex (ObjDesc->Method.Mutex->Mutex.OsMutex);
3987851SDana.Myers@Sun.COM     }
3997851SDana.Myers@Sun.COM     return_ACPI_STATUS (Status);
4007851SDana.Myers@Sun.COM }
4017851SDana.Myers@Sun.COM 
4027851SDana.Myers@Sun.COM 
4037851SDana.Myers@Sun.COM /*******************************************************************************
4047851SDana.Myers@Sun.COM  *
4057851SDana.Myers@Sun.COM  * FUNCTION:    AcpiDsCallControlMethod
4067851SDana.Myers@Sun.COM  *
4077851SDana.Myers@Sun.COM  * PARAMETERS:  Thread              - Info for this thread
4087851SDana.Myers@Sun.COM  *              ThisWalkState       - Current walk state
4097851SDana.Myers@Sun.COM  *              Op                  - Current Op to be walked
4107851SDana.Myers@Sun.COM  *
4117851SDana.Myers@Sun.COM  * RETURN:      Status
4127851SDana.Myers@Sun.COM  *
4137851SDana.Myers@Sun.COM  * DESCRIPTION: Transfer execution to a called control method
4147851SDana.Myers@Sun.COM  *
4157851SDana.Myers@Sun.COM  ******************************************************************************/
4167851SDana.Myers@Sun.COM 
4177851SDana.Myers@Sun.COM ACPI_STATUS
AcpiDsCallControlMethod(ACPI_THREAD_STATE * Thread,ACPI_WALK_STATE * ThisWalkState,ACPI_PARSE_OBJECT * Op)4187851SDana.Myers@Sun.COM AcpiDsCallControlMethod (
4197851SDana.Myers@Sun.COM     ACPI_THREAD_STATE       *Thread,
4207851SDana.Myers@Sun.COM     ACPI_WALK_STATE         *ThisWalkState,
4217851SDana.Myers@Sun.COM     ACPI_PARSE_OBJECT       *Op)
4227851SDana.Myers@Sun.COM {
4237851SDana.Myers@Sun.COM     ACPI_STATUS             Status;
4247851SDana.Myers@Sun.COM     ACPI_NAMESPACE_NODE     *MethodNode;
4257851SDana.Myers@Sun.COM     ACPI_WALK_STATE         *NextWalkState = NULL;
4267851SDana.Myers@Sun.COM     ACPI_OPERAND_OBJECT     *ObjDesc;
4277851SDana.Myers@Sun.COM     ACPI_EVALUATE_INFO      *Info;
4287851SDana.Myers@Sun.COM     UINT32                  i;
4297851SDana.Myers@Sun.COM 
4307851SDana.Myers@Sun.COM 
4317851SDana.Myers@Sun.COM     ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState);
4327851SDana.Myers@Sun.COM 
4337851SDana.Myers@Sun.COM     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Calling method %p, currentstate=%p\n",
4347851SDana.Myers@Sun.COM         ThisWalkState->PrevOp, ThisWalkState));
4357851SDana.Myers@Sun.COM 
4367851SDana.Myers@Sun.COM     /*
4377851SDana.Myers@Sun.COM      * Get the namespace entry for the control method we are about to call
4387851SDana.Myers@Sun.COM      */
4397851SDana.Myers@Sun.COM     MethodNode = ThisWalkState->MethodCallNode;
4407851SDana.Myers@Sun.COM     if (!MethodNode)
4417851SDana.Myers@Sun.COM     {
4427851SDana.Myers@Sun.COM         return_ACPI_STATUS (AE_NULL_ENTRY);
4437851SDana.Myers@Sun.COM     }
4447851SDana.Myers@Sun.COM 
4457851SDana.Myers@Sun.COM     ObjDesc = AcpiNsGetAttachedObject (MethodNode);
4467851SDana.Myers@Sun.COM     if (!ObjDesc)
4477851SDana.Myers@Sun.COM     {
4487851SDana.Myers@Sun.COM         return_ACPI_STATUS (AE_NULL_OBJECT);
4497851SDana.Myers@Sun.COM     }
4507851SDana.Myers@Sun.COM 
4517851SDana.Myers@Sun.COM     /* Init for new method, possibly wait on method mutex */
4527851SDana.Myers@Sun.COM 
4537851SDana.Myers@Sun.COM     Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc,
4547851SDana.Myers@Sun.COM                 ThisWalkState);
4557851SDana.Myers@Sun.COM     if (ACPI_FAILURE (Status))
4567851SDana.Myers@Sun.COM     {
4577851SDana.Myers@Sun.COM         return_ACPI_STATUS (Status);
4587851SDana.Myers@Sun.COM     }
4597851SDana.Myers@Sun.COM 
4607851SDana.Myers@Sun.COM     /* Begin method parse/execution. Create a new walk state */
4617851SDana.Myers@Sun.COM 
4627851SDana.Myers@Sun.COM     NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwnerId,
4637851SDana.Myers@Sun.COM                         NULL, ObjDesc, Thread);
4647851SDana.Myers@Sun.COM     if (!NextWalkState)
4657851SDana.Myers@Sun.COM     {
4667851SDana.Myers@Sun.COM         Status = AE_NO_MEMORY;
4677851SDana.Myers@Sun.COM         goto Cleanup;
4687851SDana.Myers@Sun.COM     }
4697851SDana.Myers@Sun.COM 
4707851SDana.Myers@Sun.COM     /*
4717851SDana.Myers@Sun.COM      * The resolved arguments were put on the previous walk state's operand
4727851SDana.Myers@Sun.COM      * stack. Operands on the previous walk state stack always
4737851SDana.Myers@Sun.COM      * start at index 0. Also, null terminate the list of arguments
4747851SDana.Myers@Sun.COM      */
4757851SDana.Myers@Sun.COM     ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL;
4767851SDana.Myers@Sun.COM 
4777851SDana.Myers@Sun.COM     /*
4787851SDana.Myers@Sun.COM      * Allocate and initialize the evaluation information block
4797851SDana.Myers@Sun.COM      * TBD: this is somewhat inefficient, should change interface to
4807851SDana.Myers@Sun.COM      * DsInitAmlWalk. For now, keeps this struct off the CPU stack
4817851SDana.Myers@Sun.COM      */
4827851SDana.Myers@Sun.COM     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
4837851SDana.Myers@Sun.COM     if (!Info)
4847851SDana.Myers@Sun.COM     {
4857851SDana.Myers@Sun.COM         return_ACPI_STATUS (AE_NO_MEMORY);
4867851SDana.Myers@Sun.COM     }
4877851SDana.Myers@Sun.COM 
4887851SDana.Myers@Sun.COM     Info->Parameters = &ThisWalkState->Operands[0];
4897851SDana.Myers@Sun.COM 
4907851SDana.Myers@Sun.COM     Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode,
4917851SDana.Myers@Sun.COM                 ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength,
4927851SDana.Myers@Sun.COM                 Info, ACPI_IMODE_EXECUTE);
4937851SDana.Myers@Sun.COM 
4947851SDana.Myers@Sun.COM     ACPI_FREE (Info);
4957851SDana.Myers@Sun.COM     if (ACPI_FAILURE (Status))
4967851SDana.Myers@Sun.COM     {
4977851SDana.Myers@Sun.COM         goto Cleanup;
4987851SDana.Myers@Sun.COM     }
4997851SDana.Myers@Sun.COM 
5007851SDana.Myers@Sun.COM     /*
5017851SDana.Myers@Sun.COM      * Delete the operands on the previous walkstate operand stack
5027851SDana.Myers@Sun.COM      * (they were copied to new objects)
5037851SDana.Myers@Sun.COM      */
5047851SDana.Myers@Sun.COM     for (i = 0; i < ObjDesc->Method.ParamCount; i++)
5057851SDana.Myers@Sun.COM     {
5067851SDana.Myers@Sun.COM         AcpiUtRemoveReference (ThisWalkState->Operands [i]);
5077851SDana.Myers@Sun.COM         ThisWalkState->Operands [i] = NULL;
5087851SDana.Myers@Sun.COM     }
5097851SDana.Myers@Sun.COM 
5107851SDana.Myers@Sun.COM     /* Clear the operand stack */
5117851SDana.Myers@Sun.COM 
5127851SDana.Myers@Sun.COM     ThisWalkState->NumOperands = 0;
5137851SDana.Myers@Sun.COM 
5147851SDana.Myers@Sun.COM     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
5157851SDana.Myers@Sun.COM         "**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
5167851SDana.Myers@Sun.COM         MethodNode->Name.Ascii, NextWalkState));
5177851SDana.Myers@Sun.COM 
5187851SDana.Myers@Sun.COM     /* Invoke an internal method if necessary */
5197851SDana.Myers@Sun.COM 
5207851SDana.Myers@Sun.COM     if (ObjDesc->Method.MethodFlags & AML_METHOD_INTERNAL_ONLY)
5217851SDana.Myers@Sun.COM     {
5227851SDana.Myers@Sun.COM         Status = ObjDesc->Method.Implementation (NextWalkState);
5239980SDana.Myers@Sun.COM         if (Status == AE_OK)
5249980SDana.Myers@Sun.COM         {
5259980SDana.Myers@Sun.COM             Status = AE_CTRL_TERMINATE;
5269980SDana.Myers@Sun.COM         }
5277851SDana.Myers@Sun.COM     }
5287851SDana.Myers@Sun.COM 
5297851SDana.Myers@Sun.COM     return_ACPI_STATUS (Status);
5307851SDana.Myers@Sun.COM 
5317851SDana.Myers@Sun.COM 
5327851SDana.Myers@Sun.COM Cleanup:
5337851SDana.Myers@Sun.COM 
5347851SDana.Myers@Sun.COM     /* On error, we must terminate the method properly */
5357851SDana.Myers@Sun.COM 
5367851SDana.Myers@Sun.COM     AcpiDsTerminateControlMethod (ObjDesc, NextWalkState);
5377851SDana.Myers@Sun.COM     if (NextWalkState)
5387851SDana.Myers@Sun.COM     {
5397851SDana.Myers@Sun.COM         AcpiDsDeleteWalkState (NextWalkState);
5407851SDana.Myers@Sun.COM     }
5417851SDana.Myers@Sun.COM 
5427851SDana.Myers@Sun.COM     return_ACPI_STATUS (Status);
5437851SDana.Myers@Sun.COM }
5447851SDana.Myers@Sun.COM 
5457851SDana.Myers@Sun.COM 
5467851SDana.Myers@Sun.COM /*******************************************************************************
5477851SDana.Myers@Sun.COM  *
5487851SDana.Myers@Sun.COM  * FUNCTION:    AcpiDsRestartControlMethod
5497851SDana.Myers@Sun.COM  *
5507851SDana.Myers@Sun.COM  * PARAMETERS:  WalkState           - State for preempted method (caller)
5517851SDana.Myers@Sun.COM  *              ReturnDesc          - Return value from the called method
5527851SDana.Myers@Sun.COM  *
5537851SDana.Myers@Sun.COM  * RETURN:      Status
5547851SDana.Myers@Sun.COM  *
5557851SDana.Myers@Sun.COM  * DESCRIPTION: Restart a method that was preempted by another (nested) method
5567851SDana.Myers@Sun.COM  *              invocation.  Handle the return value (if any) from the callee.
5577851SDana.Myers@Sun.COM  *
5587851SDana.Myers@Sun.COM  ******************************************************************************/
5597851SDana.Myers@Sun.COM 
5607851SDana.Myers@Sun.COM ACPI_STATUS
AcpiDsRestartControlMethod(ACPI_WALK_STATE * WalkState,ACPI_OPERAND_OBJECT * ReturnDesc)5617851SDana.Myers@Sun.COM AcpiDsRestartControlMethod (
5627851SDana.Myers@Sun.COM     ACPI_WALK_STATE         *WalkState,
5637851SDana.Myers@Sun.COM     ACPI_OPERAND_OBJECT     *ReturnDesc)
5647851SDana.Myers@Sun.COM {
5657851SDana.Myers@Sun.COM     ACPI_STATUS             Status;
5667851SDana.Myers@Sun.COM     int                     SameAsImplicitReturn;
5677851SDana.Myers@Sun.COM 
5687851SDana.Myers@Sun.COM 
5697851SDana.Myers@Sun.COM     ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState);
5707851SDana.Myers@Sun.COM 
5717851SDana.Myers@Sun.COM 
5727851SDana.Myers@Sun.COM     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
5737851SDana.Myers@Sun.COM         "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
5747851SDana.Myers@Sun.COM         AcpiUtGetNodeName (WalkState->MethodNode),
5757851SDana.Myers@Sun.COM         WalkState->MethodCallOp, ReturnDesc));
5767851SDana.Myers@Sun.COM 
5777851SDana.Myers@Sun.COM     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
5787851SDana.Myers@Sun.COM         "    ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
5797851SDana.Myers@Sun.COM         WalkState->ReturnUsed,
5807851SDana.Myers@Sun.COM         WalkState->Results, WalkState));
5817851SDana.Myers@Sun.COM 
5827851SDana.Myers@Sun.COM     /* Did the called method return a value? */
5837851SDana.Myers@Sun.COM 
5847851SDana.Myers@Sun.COM     if (ReturnDesc)
5857851SDana.Myers@Sun.COM     {
5867851SDana.Myers@Sun.COM         /* Is the implicit return object the same as the return desc? */
5877851SDana.Myers@Sun.COM 
5887851SDana.Myers@Sun.COM         SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc);
5897851SDana.Myers@Sun.COM 
5907851SDana.Myers@Sun.COM         /* Are we actually going to use the return value? */
5917851SDana.Myers@Sun.COM 
5927851SDana.Myers@Sun.COM         if (WalkState->ReturnUsed)
5937851SDana.Myers@Sun.COM         {
5947851SDana.Myers@Sun.COM             /* Save the return value from the previous method */
5957851SDana.Myers@Sun.COM 
5967851SDana.Myers@Sun.COM             Status = AcpiDsResultPush (ReturnDesc, WalkState);
5977851SDana.Myers@Sun.COM             if (ACPI_FAILURE (Status))
5987851SDana.Myers@Sun.COM             {
5997851SDana.Myers@Sun.COM                 AcpiUtRemoveReference (ReturnDesc);
6007851SDana.Myers@Sun.COM                 return_ACPI_STATUS (Status);
6017851SDana.Myers@Sun.COM             }
6027851SDana.Myers@Sun.COM 
6037851SDana.Myers@Sun.COM             /*
6047851SDana.Myers@Sun.COM              * Save as THIS method's return value in case it is returned
6057851SDana.Myers@Sun.COM              * immediately to yet another method
6067851SDana.Myers@Sun.COM              */
6077851SDana.Myers@Sun.COM             WalkState->ReturnDesc = ReturnDesc;
6087851SDana.Myers@Sun.COM         }
6097851SDana.Myers@Sun.COM 
6107851SDana.Myers@Sun.COM         /*
6117851SDana.Myers@Sun.COM          * The following code is the optional support for the so-called
6127851SDana.Myers@Sun.COM          * "implicit return". Some AML code assumes that the last value of the
6137851SDana.Myers@Sun.COM          * method is "implicitly" returned to the caller, in the absence of an
6147851SDana.Myers@Sun.COM          * explicit return value.
6157851SDana.Myers@Sun.COM          *
6167851SDana.Myers@Sun.COM          * Just save the last result of the method as the return value.
6177851SDana.Myers@Sun.COM          *
6187851SDana.Myers@Sun.COM          * NOTE: this is optional because the ASL language does not actually
6197851SDana.Myers@Sun.COM          * support this behavior.
6207851SDana.Myers@Sun.COM          */
6217851SDana.Myers@Sun.COM         else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) ||
6227851SDana.Myers@Sun.COM                  SameAsImplicitReturn)
6237851SDana.Myers@Sun.COM         {
6247851SDana.Myers@Sun.COM             /*
6257851SDana.Myers@Sun.COM              * Delete the return value if it will not be used by the
6267851SDana.Myers@Sun.COM              * calling method or remove one reference if the explicit return
6277851SDana.Myers@Sun.COM              * is the same as the implicit return value.
6287851SDana.Myers@Sun.COM              */
6297851SDana.Myers@Sun.COM             AcpiUtRemoveReference (ReturnDesc);
6307851SDana.Myers@Sun.COM         }
6317851SDana.Myers@Sun.COM     }
6327851SDana.Myers@Sun.COM 
6337851SDana.Myers@Sun.COM     return_ACPI_STATUS (AE_OK);
6347851SDana.Myers@Sun.COM }
6357851SDana.Myers@Sun.COM 
6367851SDana.Myers@Sun.COM 
6377851SDana.Myers@Sun.COM /*******************************************************************************
6387851SDana.Myers@Sun.COM  *
6397851SDana.Myers@Sun.COM  * FUNCTION:    AcpiDsTerminateControlMethod
6407851SDana.Myers@Sun.COM  *
6417851SDana.Myers@Sun.COM  * PARAMETERS:  MethodDesc          - Method object
6427851SDana.Myers@Sun.COM  *              WalkState           - State associated with the method
6437851SDana.Myers@Sun.COM  *
6447851SDana.Myers@Sun.COM  * RETURN:      None
6457851SDana.Myers@Sun.COM  *
6467851SDana.Myers@Sun.COM  * DESCRIPTION: Terminate a control method.  Delete everything that the method
6477851SDana.Myers@Sun.COM  *              created, delete all locals and arguments, and delete the parse
6487851SDana.Myers@Sun.COM  *              tree if requested.
6497851SDana.Myers@Sun.COM  *
6507851SDana.Myers@Sun.COM  * MUTEX:       Interpreter is locked
6517851SDana.Myers@Sun.COM  *
6527851SDana.Myers@Sun.COM  ******************************************************************************/
6537851SDana.Myers@Sun.COM 
6547851SDana.Myers@Sun.COM void
AcpiDsTerminateControlMethod(ACPI_OPERAND_OBJECT * MethodDesc,ACPI_WALK_STATE * WalkState)6557851SDana.Myers@Sun.COM AcpiDsTerminateControlMethod (
6567851SDana.Myers@Sun.COM     ACPI_OPERAND_OBJECT     *MethodDesc,
6577851SDana.Myers@Sun.COM     ACPI_WALK_STATE         *WalkState)
6587851SDana.Myers@Sun.COM {
6597851SDana.Myers@Sun.COM 
6607851SDana.Myers@Sun.COM     ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState);
6617851SDana.Myers@Sun.COM 
6627851SDana.Myers@Sun.COM 
6637851SDana.Myers@Sun.COM     /* MethodDesc is required, WalkState is optional */
6647851SDana.Myers@Sun.COM 
6657851SDana.Myers@Sun.COM     if (!MethodDesc)
6667851SDana.Myers@Sun.COM     {
6677851SDana.Myers@Sun.COM         return_VOID;
6687851SDana.Myers@Sun.COM     }
6697851SDana.Myers@Sun.COM 
6707851SDana.Myers@Sun.COM     if (WalkState)
6717851SDana.Myers@Sun.COM     {
6727851SDana.Myers@Sun.COM         /* Delete all arguments and locals */
6737851SDana.Myers@Sun.COM 
6747851SDana.Myers@Sun.COM         AcpiDsMethodDataDeleteAll (WalkState);
6757851SDana.Myers@Sun.COM 
6767851SDana.Myers@Sun.COM         /*
6777851SDana.Myers@Sun.COM          * If method is serialized, release the mutex and restore the
6787851SDana.Myers@Sun.COM          * current sync level for this thread
6797851SDana.Myers@Sun.COM          */
6807851SDana.Myers@Sun.COM         if (MethodDesc->Method.Mutex)
6817851SDana.Myers@Sun.COM         {
6827851SDana.Myers@Sun.COM             /* Acquisition Depth handles recursive calls */
6837851SDana.Myers@Sun.COM 
6847851SDana.Myers@Sun.COM             MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--;
6857851SDana.Myers@Sun.COM             if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth)
6867851SDana.Myers@Sun.COM             {
6877851SDana.Myers@Sun.COM                 WalkState->Thread->CurrentSyncLevel =
6887851SDana.Myers@Sun.COM                     MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel;
6897851SDana.Myers@Sun.COM 
6907851SDana.Myers@Sun.COM                 AcpiOsReleaseMutex (MethodDesc->Method.Mutex->Mutex.OsMutex);
6917851SDana.Myers@Sun.COM                 MethodDesc->Method.Mutex->Mutex.ThreadId = 0;
6927851SDana.Myers@Sun.COM             }
6937851SDana.Myers@Sun.COM         }
6947851SDana.Myers@Sun.COM 
6957851SDana.Myers@Sun.COM         /*
696*11225SDana.Myers@Sun.COM          * Delete any namespace objects created anywhere within the
697*11225SDana.Myers@Sun.COM          * namespace by the execution of this method. Unless this method
698*11225SDana.Myers@Sun.COM          * is a module-level executable code method, in which case we
699*11225SDana.Myers@Sun.COM          * want make the objects permanent.
7007851SDana.Myers@Sun.COM          */
701*11225SDana.Myers@Sun.COM         if (!(MethodDesc->Method.Flags & AOPOBJ_MODULE_LEVEL))
702*11225SDana.Myers@Sun.COM         {
703*11225SDana.Myers@Sun.COM             AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId);
704*11225SDana.Myers@Sun.COM         }
7057851SDana.Myers@Sun.COM     }
7067851SDana.Myers@Sun.COM 
7077851SDana.Myers@Sun.COM     /* Decrement the thread count on the method */
7087851SDana.Myers@Sun.COM 
7097851SDana.Myers@Sun.COM     if (MethodDesc->Method.ThreadCount)
7107851SDana.Myers@Sun.COM     {
7117851SDana.Myers@Sun.COM         MethodDesc->Method.ThreadCount--;
7127851SDana.Myers@Sun.COM     }
7137851SDana.Myers@Sun.COM     else
7147851SDana.Myers@Sun.COM     {
7157851SDana.Myers@Sun.COM         ACPI_ERROR ((AE_INFO,
7167851SDana.Myers@Sun.COM             "Invalid zero thread count in method"));
7177851SDana.Myers@Sun.COM     }
7187851SDana.Myers@Sun.COM 
7197851SDana.Myers@Sun.COM     /* Are there any other threads currently executing this method? */
7207851SDana.Myers@Sun.COM 
7217851SDana.Myers@Sun.COM     if (MethodDesc->Method.ThreadCount)
7227851SDana.Myers@Sun.COM     {
7237851SDana.Myers@Sun.COM         /*
7247851SDana.Myers@Sun.COM          * Additional threads. Do not release the OwnerId in this case,
7257851SDana.Myers@Sun.COM          * we immediately reuse it for the next thread executing this method
7267851SDana.Myers@Sun.COM          */
7277851SDana.Myers@Sun.COM         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
7287851SDana.Myers@Sun.COM             "*** Completed execution of one thread, %d threads remaining\n",
7297851SDana.Myers@Sun.COM             MethodDesc->Method.ThreadCount));
7307851SDana.Myers@Sun.COM     }
7317851SDana.Myers@Sun.COM     else
7327851SDana.Myers@Sun.COM     {
7337851SDana.Myers@Sun.COM         /* This is the only executing thread for this method */
7347851SDana.Myers@Sun.COM 
7357851SDana.Myers@Sun.COM         /*
7367851SDana.Myers@Sun.COM          * Support to dynamically change a method from NotSerialized to
7377851SDana.Myers@Sun.COM          * Serialized if it appears that the method is incorrectly written and
7387851SDana.Myers@Sun.COM          * does not support multiple thread execution. The best example of this
7397851SDana.Myers@Sun.COM          * is if such a method creates namespace objects and blocks. A second
7407851SDana.Myers@Sun.COM          * thread will fail with an AE_ALREADY_EXISTS exception
7417851SDana.Myers@Sun.COM          *
7427851SDana.Myers@Sun.COM          * This code is here because we must wait until the last thread exits
7437851SDana.Myers@Sun.COM          * before creating the synchronization semaphore.
7447851SDana.Myers@Sun.COM          */
7457851SDana.Myers@Sun.COM         if ((MethodDesc->Method.MethodFlags & AML_METHOD_SERIALIZED) &&
7467851SDana.Myers@Sun.COM             (!MethodDesc->Method.Mutex))
7477851SDana.Myers@Sun.COM         {
7487851SDana.Myers@Sun.COM             (void) AcpiDsCreateMethodMutex (MethodDesc);
7497851SDana.Myers@Sun.COM         }
7507851SDana.Myers@Sun.COM 
7517851SDana.Myers@Sun.COM         /* No more threads, we can free the OwnerId */
7527851SDana.Myers@Sun.COM 
753*11225SDana.Myers@Sun.COM         if (!(MethodDesc->Method.Flags & AOPOBJ_MODULE_LEVEL))
754*11225SDana.Myers@Sun.COM         {
755*11225SDana.Myers@Sun.COM             AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId);
756*11225SDana.Myers@Sun.COM         }
7577851SDana.Myers@Sun.COM     }
7587851SDana.Myers@Sun.COM 
7597851SDana.Myers@Sun.COM     return_VOID;
7607851SDana.Myers@Sun.COM }
7617851SDana.Myers@Sun.COM 
7627851SDana.Myers@Sun.COM 
763