Subversion Repositories Kolibri OS

Rev

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

  1. /******************************************************************************
  2.  *
  3.  * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
  4.  *
  5.  *****************************************************************************/
  6.  
  7. /******************************************************************************
  8.  *
  9.  * 1. Copyright Notice
  10.  *
  11.  * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
  12.  * All rights reserved.
  13.  *
  14.  * 2. License
  15.  *
  16.  * 2.1. This is your license from Intel Corp. under its intellectual property
  17.  * rights.  You may have additional license terms from the party that provided
  18.  * you this software, covering your right to use that party's intellectual
  19.  * property rights.
  20.  *
  21.  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
  22.  * copy of the source code appearing in this file ("Covered Code") an
  23.  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
  24.  * base code distributed originally by Intel ("Original Intel Code") to copy,
  25.  * make derivatives, distribute, use and display any portion of the Covered
  26.  * Code in any form, with the right to sublicense such rights; and
  27.  *
  28.  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
  29.  * license (with the right to sublicense), under only those claims of Intel
  30.  * patents that are infringed by the Original Intel Code, to make, use, sell,
  31.  * offer to sell, and import the Covered Code and derivative works thereof
  32.  * solely to the minimum extent necessary to exercise the above copyright
  33.  * license, and in no event shall the patent license extend to any additions
  34.  * to or modifications of the Original Intel Code.  No other license or right
  35.  * is granted directly or by implication, estoppel or otherwise;
  36.  *
  37.  * The above copyright and patent license is granted only if the following
  38.  * conditions are met:
  39.  *
  40.  * 3. Conditions
  41.  *
  42.  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
  43.  * Redistribution of source code of any substantial portion of the Covered
  44.  * Code or modification with rights to further distribute source must include
  45.  * the above Copyright Notice, the above License, this list of Conditions,
  46.  * and the following Disclaimer and Export Compliance provision.  In addition,
  47.  * Licensee must cause all Covered Code to which Licensee contributes to
  48.  * contain a file documenting the changes Licensee made to create that Covered
  49.  * Code and the date of any change.  Licensee must include in that file the
  50.  * documentation of any changes made by any predecessor Licensee.  Licensee
  51.  * must include a prominent statement that the modification is derived,
  52.  * directly or indirectly, from Original Intel Code.
  53.  *
  54.  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
  55.  * Redistribution of source code of any substantial portion of the Covered
  56.  * Code or modification without rights to further distribute source must
  57.  * include the following Disclaimer and Export Compliance provision in the
  58.  * documentation and/or other materials provided with distribution.  In
  59.  * addition, Licensee may not authorize further sublicense of source of any
  60.  * portion of the Covered Code, and must include terms to the effect that the
  61.  * license from Licensee to its licensee is limited to the intellectual
  62.  * property embodied in the software Licensee provides to its licensee, and
  63.  * not to intellectual property embodied in modifications its licensee may
  64.  * make.
  65.  *
  66.  * 3.3. Redistribution of Executable. Redistribution in executable form of any
  67.  * substantial portion of the Covered Code or modification must reproduce the
  68.  * above Copyright Notice, and the following Disclaimer and Export Compliance
  69.  * provision in the documentation and/or other materials provided with the
  70.  * distribution.
  71.  *
  72.  * 3.4. Intel retains all right, title, and interest in and to the Original
  73.  * Intel Code.
  74.  *
  75.  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
  76.  * Intel shall be used in advertising or otherwise to promote the sale, use or
  77.  * other dealings in products derived from or relating to the Covered Code
  78.  * without prior written authorization from Intel.
  79.  *
  80.  * 4. Disclaimer and Export Compliance
  81.  *
  82.  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
  83.  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
  84.  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
  85.  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
  86.  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
  87.  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
  88.  * PARTICULAR PURPOSE.
  89.  *
  90.  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
  91.  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
  92.  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
  93.  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
  94.  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
  95.  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
  96.  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
  97.  * LIMITED REMEDY.
  98.  *
  99.  * 4.3. Licensee shall not export, either directly or indirectly, any of this
  100.  * software or system incorporating such software without first obtaining any
  101.  * required license or other approval from the U. S. Department of Commerce or
  102.  * any other agency or department of the United States Government.  In the
  103.  * event Licensee exports any such software from the United States or
  104.  * re-exports any such software from a foreign destination, Licensee shall
  105.  * ensure that the distribution and export/re-export of the software is in
  106.  * compliance with all laws, regulations, orders, or other restrictions of the
  107.  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
  108.  * any of its subsidiaries will export/re-export any technical data, process,
  109.  * software, or service, directly or indirectly, to any country for which the
  110.  * United States government or any agency thereof requires an export license,
  111.  * other governmental approval, or letter of assurance, without first obtaining
  112.  * such license, approval or letter.
  113.  *
  114.  *****************************************************************************/
  115.  
  116. #define __DSMETHOD_C__
  117.  
  118. #include "acpi.h"
  119. #include "accommon.h"
  120. #include "amlcode.h"
  121. #include "acdispat.h"
  122. #include "acinterp.h"
  123. #include "acnamesp.h"
  124. #include "acdisasm.h"
  125.  
  126.  
  127. #define _COMPONENT          ACPI_DISPATCHER
  128.         ACPI_MODULE_NAME    ("dsmethod")
  129.  
  130. /* Local prototypes */
  131.  
  132. static ACPI_STATUS
  133. AcpiDsCreateMethodMutex (
  134.     ACPI_OPERAND_OBJECT     *MethodDesc);
  135.  
  136.  
  137. /*******************************************************************************
  138.  *
  139.  * FUNCTION:    AcpiDsMethodError
  140.  *
  141.  * PARAMETERS:  Status          - Execution status
  142.  *              WalkState       - Current state
  143.  *
  144.  * RETURN:      Status
  145.  *
  146.  * DESCRIPTION: Called on method error. Invoke the global exception handler if
  147.  *              present, dump the method data if the disassembler is configured
  148.  *
  149.  *              Note: Allows the exception handler to change the status code
  150.  *
  151.  ******************************************************************************/
  152.  
  153. ACPI_STATUS
  154. AcpiDsMethodError (
  155.     ACPI_STATUS             Status,
  156.     ACPI_WALK_STATE         *WalkState)
  157. {
  158.     ACPI_FUNCTION_ENTRY ();
  159.  
  160.  
  161.     /* Ignore AE_OK and control exception codes */
  162.  
  163.     if (ACPI_SUCCESS (Status) ||
  164.         (Status & AE_CODE_CONTROL))
  165.     {
  166.         return (Status);
  167.     }
  168.  
  169.     /* Invoke the global exception handler */
  170.  
  171.     if (AcpiGbl_ExceptionHandler)
  172.     {
  173.         /* Exit the interpreter, allow handler to execute methods */
  174.  
  175.         AcpiExExitInterpreter ();
  176.  
  177.         /*
  178.          * Handler can map the exception code to anything it wants, including
  179.          * AE_OK, in which case the executing method will not be aborted.
  180.          */
  181.         Status = AcpiGbl_ExceptionHandler (Status,
  182.                     WalkState->MethodNode ?
  183.                         WalkState->MethodNode->Name.Integer : 0,
  184.                     WalkState->Opcode, WalkState->AmlOffset, NULL);
  185.         AcpiExEnterInterpreter ();
  186.     }
  187.  
  188.     AcpiDsClearImplicitReturn (WalkState);
  189.  
  190. #ifdef ACPI_DISASSEMBLER
  191.     if (ACPI_FAILURE (Status))
  192.     {
  193.         /* Display method locals/args if disassembler is present */
  194.  
  195.         AcpiDmDumpMethodInfo (Status, WalkState, WalkState->Op);
  196.     }
  197. #endif
  198.  
  199.     return (Status);
  200. }
  201.  
  202.  
  203. /*******************************************************************************
  204.  *
  205.  * FUNCTION:    AcpiDsCreateMethodMutex
  206.  *
  207.  * PARAMETERS:  ObjDesc             - The method object
  208.  *
  209.  * RETURN:      Status
  210.  *
  211.  * DESCRIPTION: Create a mutex object for a serialized control method
  212.  *
  213.  ******************************************************************************/
  214.  
  215. static ACPI_STATUS
  216. AcpiDsCreateMethodMutex (
  217.     ACPI_OPERAND_OBJECT     *MethodDesc)
  218. {
  219.     ACPI_OPERAND_OBJECT     *MutexDesc;
  220.     ACPI_STATUS             Status;
  221.  
  222.  
  223.     ACPI_FUNCTION_TRACE (DsCreateMethodMutex);
  224.  
  225.  
  226.     /* Create the new mutex object */
  227.  
  228.     MutexDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX);
  229.     if (!MutexDesc)
  230.     {
  231.         return_ACPI_STATUS (AE_NO_MEMORY);
  232.     }
  233.  
  234.     /* Create the actual OS Mutex */
  235.  
  236.     Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex);
  237.     if (ACPI_FAILURE (Status))
  238.     {
  239.         return_ACPI_STATUS (Status);
  240.     }
  241.  
  242.     MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel;
  243.     MethodDesc->Method.Mutex = MutexDesc;
  244.     return_ACPI_STATUS (AE_OK);
  245. }
  246.  
  247.  
  248. /*******************************************************************************
  249.  *
  250.  * FUNCTION:    AcpiDsBeginMethodExecution
  251.  *
  252.  * PARAMETERS:  MethodNode          - Node of the method
  253.  *              ObjDesc             - The method object
  254.  *              WalkState           - current state, NULL if not yet executing
  255.  *                                    a method.
  256.  *
  257.  * RETURN:      Status
  258.  *
  259.  * DESCRIPTION: Prepare a method for execution.  Parses the method if necessary,
  260.  *              increments the thread count, and waits at the method semaphore
  261.  *              for clearance to execute.
  262.  *
  263.  ******************************************************************************/
  264.  
  265. ACPI_STATUS
  266. AcpiDsBeginMethodExecution (
  267.     ACPI_NAMESPACE_NODE     *MethodNode,
  268.     ACPI_OPERAND_OBJECT     *ObjDesc,
  269.     ACPI_WALK_STATE         *WalkState)
  270. {
  271.     ACPI_STATUS             Status = AE_OK;
  272.  
  273.  
  274.     ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode);
  275.  
  276.  
  277.     if (!MethodNode)
  278.     {
  279.         return_ACPI_STATUS (AE_NULL_ENTRY);
  280.     }
  281.  
  282.     /* Prevent wraparound of thread count */
  283.  
  284.     if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX)
  285.     {
  286.         ACPI_ERROR ((AE_INFO,
  287.             "Method reached maximum reentrancy limit (255)"));
  288.         return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
  289.     }
  290.  
  291.     /*
  292.      * If this method is serialized, we need to acquire the method mutex.
  293.      */
  294.     if (ObjDesc->Method.MethodFlags & AML_METHOD_SERIALIZED)
  295.     {
  296.         /*
  297.          * Create a mutex for the method if it is defined to be Serialized
  298.          * and a mutex has not already been created. We defer the mutex creation
  299.          * until a method is actually executed, to minimize the object count
  300.          */
  301.         if (!ObjDesc->Method.Mutex)
  302.         {
  303.             Status = AcpiDsCreateMethodMutex (ObjDesc);
  304.             if (ACPI_FAILURE (Status))
  305.             {
  306.                 return_ACPI_STATUS (Status);
  307.             }
  308.         }
  309.  
  310.         /*
  311.          * The CurrentSyncLevel (per-thread) must be less than or equal to
  312.          * the sync level of the method. This mechanism provides some
  313.          * deadlock prevention
  314.          *
  315.          * Top-level method invocation has no walk state at this point
  316.          */
  317.         if (WalkState &&
  318.             (WalkState->Thread->CurrentSyncLevel > ObjDesc->Method.Mutex->Mutex.SyncLevel))
  319.         {
  320.             ACPI_ERROR ((AE_INFO,
  321.                 "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)",
  322.                 AcpiUtGetNodeName (MethodNode),
  323.                 WalkState->Thread->CurrentSyncLevel));
  324.  
  325.             return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
  326.         }
  327.  
  328.         /*
  329.          * Obtain the method mutex if necessary. Do not acquire mutex for a
  330.          * recursive call.
  331.          */
  332.         if (!WalkState ||
  333.             !ObjDesc->Method.Mutex->Mutex.ThreadId ||
  334.             (WalkState->Thread->ThreadId != ObjDesc->Method.Mutex->Mutex.ThreadId))
  335.         {
  336.             /*
  337.              * Acquire the method mutex. This releases the interpreter if we
  338.              * block (and reacquires it before it returns)
  339.              */
  340.             Status = AcpiExSystemWaitMutex (ObjDesc->Method.Mutex->Mutex.OsMutex,
  341.                         ACPI_WAIT_FOREVER);
  342.             if (ACPI_FAILURE (Status))
  343.             {
  344.                 return_ACPI_STATUS (Status);
  345.             }
  346.  
  347.             /* Update the mutex and walk info and save the original SyncLevel */
  348.  
  349.             if (WalkState)
  350.             {
  351.                 ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
  352.                     WalkState->Thread->CurrentSyncLevel;
  353.  
  354.                 ObjDesc->Method.Mutex->Mutex.ThreadId = WalkState->Thread->ThreadId;
  355.                 WalkState->Thread->CurrentSyncLevel = ObjDesc->Method.SyncLevel;
  356.             }
  357.             else
  358.             {
  359.                 ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
  360.                     ObjDesc->Method.Mutex->Mutex.SyncLevel;
  361.             }
  362.         }
  363.  
  364.         /* Always increase acquisition depth */
  365.  
  366.         ObjDesc->Method.Mutex->Mutex.AcquisitionDepth++;
  367.     }
  368.  
  369.     /*
  370.      * Allocate an Owner ID for this method, only if this is the first thread
  371.      * to begin concurrent execution. We only need one OwnerId, even if the
  372.      * method is invoked recursively.
  373.      */
  374.     if (!ObjDesc->Method.OwnerId)
  375.     {
  376.         Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
  377.         if (ACPI_FAILURE (Status))
  378.         {
  379.             goto Cleanup;
  380.         }
  381.     }
  382.  
  383.     /*
  384.      * Increment the method parse tree thread count since it has been
  385.      * reentered one more time (even if it is the same thread)
  386.      */
  387.     ObjDesc->Method.ThreadCount++;
  388.     AcpiMethodCount++;
  389.     return_ACPI_STATUS (Status);
  390.  
  391.  
  392. Cleanup:
  393.     /* On error, must release the method mutex (if present) */
  394.  
  395.     if (ObjDesc->Method.Mutex)
  396.     {
  397.         AcpiOsReleaseMutex (ObjDesc->Method.Mutex->Mutex.OsMutex);
  398.     }
  399.     return_ACPI_STATUS (Status);
  400. }
  401.  
  402.  
  403. /*******************************************************************************
  404.  *
  405.  * FUNCTION:    AcpiDsCallControlMethod
  406.  *
  407.  * PARAMETERS:  Thread              - Info for this thread
  408.  *              ThisWalkState       - Current walk state
  409.  *              Op                  - Current Op to be walked
  410.  *
  411.  * RETURN:      Status
  412.  *
  413.  * DESCRIPTION: Transfer execution to a called control method
  414.  *
  415.  ******************************************************************************/
  416.  
  417. ACPI_STATUS
  418. AcpiDsCallControlMethod (
  419.     ACPI_THREAD_STATE       *Thread,
  420.     ACPI_WALK_STATE         *ThisWalkState,
  421.     ACPI_PARSE_OBJECT       *Op)
  422. {
  423.     ACPI_STATUS             Status;
  424.     ACPI_NAMESPACE_NODE     *MethodNode;
  425.     ACPI_WALK_STATE         *NextWalkState = NULL;
  426.     ACPI_OPERAND_OBJECT     *ObjDesc;
  427.     ACPI_EVALUATE_INFO      *Info;
  428.     UINT32                  i;
  429.  
  430.  
  431.     ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState);
  432.  
  433.     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Calling method %p, currentstate=%p\n",
  434.         ThisWalkState->PrevOp, ThisWalkState));
  435.  
  436.     /*
  437.      * Get the namespace entry for the control method we are about to call
  438.      */
  439.     MethodNode = ThisWalkState->MethodCallNode;
  440.     if (!MethodNode)
  441.     {
  442.         return_ACPI_STATUS (AE_NULL_ENTRY);
  443.     }
  444.  
  445.     ObjDesc = AcpiNsGetAttachedObject (MethodNode);
  446.     if (!ObjDesc)
  447.     {
  448.         return_ACPI_STATUS (AE_NULL_OBJECT);
  449.     }
  450.  
  451.     /* Init for new method, possibly wait on method mutex */
  452.  
  453.     Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc,
  454.                 ThisWalkState);
  455.     if (ACPI_FAILURE (Status))
  456.     {
  457.         return_ACPI_STATUS (Status);
  458.     }
  459.  
  460.     /* Begin method parse/execution. Create a new walk state */
  461.  
  462.     NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwnerId,
  463.                         NULL, ObjDesc, Thread);
  464.     if (!NextWalkState)
  465.     {
  466.         Status = AE_NO_MEMORY;
  467.         goto Cleanup;
  468.     }
  469.  
  470.     /*
  471.      * The resolved arguments were put on the previous walk state's operand
  472.      * stack. Operands on the previous walk state stack always
  473.      * start at index 0. Also, null terminate the list of arguments
  474.      */
  475.     ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL;
  476.  
  477.     /*
  478.      * Allocate and initialize the evaluation information block
  479.      * TBD: this is somewhat inefficient, should change interface to
  480.      * DsInitAmlWalk. For now, keeps this struct off the CPU stack
  481.      */
  482.     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
  483.     if (!Info)
  484.     {
  485.         return_ACPI_STATUS (AE_NO_MEMORY);
  486.     }
  487.  
  488.     Info->Parameters = &ThisWalkState->Operands[0];
  489.  
  490.     Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode,
  491.                 ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength,
  492.                 Info, ACPI_IMODE_EXECUTE);
  493.  
  494.     ACPI_FREE (Info);
  495.     if (ACPI_FAILURE (Status))
  496.     {
  497.         goto Cleanup;
  498.     }
  499.  
  500.     /*
  501.      * Delete the operands on the previous walkstate operand stack
  502.      * (they were copied to new objects)
  503.      */
  504.     for (i = 0; i < ObjDesc->Method.ParamCount; i++)
  505.     {
  506.         AcpiUtRemoveReference (ThisWalkState->Operands [i]);
  507.         ThisWalkState->Operands [i] = NULL;
  508.     }
  509.  
  510.     /* Clear the operand stack */
  511.  
  512.     ThisWalkState->NumOperands = 0;
  513.  
  514.     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  515.         "**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
  516.         MethodNode->Name.Ascii, NextWalkState));
  517.  
  518.     /* Invoke an internal method if necessary */
  519.  
  520.     if (ObjDesc->Method.MethodFlags & AML_METHOD_INTERNAL_ONLY)
  521.     {
  522.         Status = ObjDesc->Method.Extra.Implementation (NextWalkState);
  523.         if (Status == AE_OK)
  524.         {
  525.             Status = AE_CTRL_TERMINATE;
  526.         }
  527.     }
  528.  
  529.     return_ACPI_STATUS (Status);
  530.  
  531.  
  532. Cleanup:
  533.  
  534.     /* On error, we must terminate the method properly */
  535.  
  536.     AcpiDsTerminateControlMethod (ObjDesc, NextWalkState);
  537.     if (NextWalkState)
  538.     {
  539.         AcpiDsDeleteWalkState (NextWalkState);
  540.     }
  541.  
  542.     return_ACPI_STATUS (Status);
  543. }
  544.  
  545.  
  546. /*******************************************************************************
  547.  *
  548.  * FUNCTION:    AcpiDsRestartControlMethod
  549.  *
  550.  * PARAMETERS:  WalkState           - State for preempted method (caller)
  551.  *              ReturnDesc          - Return value from the called method
  552.  *
  553.  * RETURN:      Status
  554.  *
  555.  * DESCRIPTION: Restart a method that was preempted by another (nested) method
  556.  *              invocation.  Handle the return value (if any) from the callee.
  557.  *
  558.  ******************************************************************************/
  559.  
  560. ACPI_STATUS
  561. AcpiDsRestartControlMethod (
  562.     ACPI_WALK_STATE         *WalkState,
  563.     ACPI_OPERAND_OBJECT     *ReturnDesc)
  564. {
  565.     ACPI_STATUS             Status;
  566.     int                     SameAsImplicitReturn;
  567.  
  568.  
  569.     ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState);
  570.  
  571.  
  572.     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  573.         "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
  574.         AcpiUtGetNodeName (WalkState->MethodNode),
  575.         WalkState->MethodCallOp, ReturnDesc));
  576.  
  577.     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  578.         "    ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
  579.         WalkState->ReturnUsed,
  580.         WalkState->Results, WalkState));
  581.  
  582.     /* Did the called method return a value? */
  583.  
  584.     if (ReturnDesc)
  585.     {
  586.         /* Is the implicit return object the same as the return desc? */
  587.  
  588.         SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc);
  589.  
  590.         /* Are we actually going to use the return value? */
  591.  
  592.         if (WalkState->ReturnUsed)
  593.         {
  594.             /* Save the return value from the previous method */
  595.  
  596.             Status = AcpiDsResultPush (ReturnDesc, WalkState);
  597.             if (ACPI_FAILURE (Status))
  598.             {
  599.                 AcpiUtRemoveReference (ReturnDesc);
  600.                 return_ACPI_STATUS (Status);
  601.             }
  602.  
  603.             /*
  604.              * Save as THIS method's return value in case it is returned
  605.              * immediately to yet another method
  606.              */
  607.             WalkState->ReturnDesc = ReturnDesc;
  608.         }
  609.  
  610.         /*
  611.          * The following code is the optional support for the so-called
  612.          * "implicit return". Some AML code assumes that the last value of the
  613.          * method is "implicitly" returned to the caller, in the absence of an
  614.          * explicit return value.
  615.          *
  616.          * Just save the last result of the method as the return value.
  617.          *
  618.          * NOTE: this is optional because the ASL language does not actually
  619.          * support this behavior.
  620.          */
  621.         else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) ||
  622.                  SameAsImplicitReturn)
  623.         {
  624.             /*
  625.              * Delete the return value if it will not be used by the
  626.              * calling method or remove one reference if the explicit return
  627.              * is the same as the implicit return value.
  628.              */
  629.             AcpiUtRemoveReference (ReturnDesc);
  630.         }
  631.     }
  632.  
  633.     return_ACPI_STATUS (AE_OK);
  634. }
  635.  
  636.  
  637. /*******************************************************************************
  638.  *
  639.  * FUNCTION:    AcpiDsTerminateControlMethod
  640.  *
  641.  * PARAMETERS:  MethodDesc          - Method object
  642.  *              WalkState           - State associated with the method
  643.  *
  644.  * RETURN:      None
  645.  *
  646.  * DESCRIPTION: Terminate a control method.  Delete everything that the method
  647.  *              created, delete all locals and arguments, and delete the parse
  648.  *              tree if requested.
  649.  *
  650.  * MUTEX:       Interpreter is locked
  651.  *
  652.  ******************************************************************************/
  653.  
  654. void
  655. AcpiDsTerminateControlMethod (
  656.     ACPI_OPERAND_OBJECT     *MethodDesc,
  657.     ACPI_WALK_STATE         *WalkState)
  658. {
  659.  
  660.     ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState);
  661.  
  662.  
  663.     /* MethodDesc is required, WalkState is optional */
  664.  
  665.     if (!MethodDesc)
  666.     {
  667.         return_VOID;
  668.     }
  669.  
  670.     if (WalkState)
  671.     {
  672.         /* Delete all arguments and locals */
  673.  
  674.         AcpiDsMethodDataDeleteAll (WalkState);
  675.  
  676.         /*
  677.          * If method is serialized, release the mutex and restore the
  678.          * current sync level for this thread
  679.          */
  680.         if (MethodDesc->Method.Mutex)
  681.         {
  682.             /* Acquisition Depth handles recursive calls */
  683.  
  684.             MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--;
  685.             if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth)
  686.             {
  687.                 WalkState->Thread->CurrentSyncLevel =
  688.                     MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel;
  689.  
  690.                 AcpiOsReleaseMutex (MethodDesc->Method.Mutex->Mutex.OsMutex);
  691.                 MethodDesc->Method.Mutex->Mutex.ThreadId = 0;
  692.             }
  693.         }
  694.  
  695.         /*
  696.          * Delete any namespace objects created anywhere within the
  697.          * namespace by the execution of this method. Unless this method
  698.          * is a module-level executable code method, in which case we
  699.          * want make the objects permanent.
  700.          */
  701.         if (!(MethodDesc->Method.Flags & AOPOBJ_MODULE_LEVEL))
  702.         {
  703.             /* Delete any direct children of (created by) this method */
  704.  
  705.             AcpiNsDeleteNamespaceSubtree (WalkState->MethodNode);
  706.  
  707.             /*
  708.              * Delete any objects that were created by this method
  709.              * elsewhere in the namespace (if any were created).
  710.              */
  711.             if (MethodDesc->Method.Flags & AOPOBJ_MODIFIED_NAMESPACE)
  712.             {
  713.                 AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId);
  714.             }
  715.         }
  716.     }
  717.  
  718.     /* Decrement the thread count on the method */
  719.  
  720.     if (MethodDesc->Method.ThreadCount)
  721.     {
  722.         MethodDesc->Method.ThreadCount--;
  723.     }
  724.     else
  725.     {
  726.         ACPI_ERROR ((AE_INFO,
  727.             "Invalid zero thread count in method"));
  728.     }
  729.  
  730.     /* Are there any other threads currently executing this method? */
  731.  
  732.     if (MethodDesc->Method.ThreadCount)
  733.     {
  734.         /*
  735.          * Additional threads. Do not release the OwnerId in this case,
  736.          * we immediately reuse it for the next thread executing this method
  737.          */
  738.         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  739.             "*** Completed execution of one thread, %u threads remaining\n",
  740.             MethodDesc->Method.ThreadCount));
  741.     }
  742.     else
  743.     {
  744.         /* This is the only executing thread for this method */
  745.  
  746.         /*
  747.          * Support to dynamically change a method from NotSerialized to
  748.          * Serialized if it appears that the method is incorrectly written and
  749.          * does not support multiple thread execution. The best example of this
  750.          * is if such a method creates namespace objects and blocks. A second
  751.          * thread will fail with an AE_ALREADY_EXISTS exception
  752.          *
  753.          * This code is here because we must wait until the last thread exits
  754.          * before creating the synchronization semaphore.
  755.          */
  756.         if ((MethodDesc->Method.MethodFlags & AML_METHOD_SERIALIZED) &&
  757.             (!MethodDesc->Method.Mutex))
  758.         {
  759.             (void) AcpiDsCreateMethodMutex (MethodDesc);
  760.         }
  761.  
  762.         /* No more threads, we can free the OwnerId */
  763.  
  764.         if (!(MethodDesc->Method.Flags & AOPOBJ_MODULE_LEVEL))
  765.         {
  766.             AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId);
  767.         }
  768.     }
  769.  
  770.     return_VOID;
  771. }
  772.  
  773.  
  774.