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