Subversion Repositories Kolibri OS

Rev

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

  1. /******************************************************************************
  2.  *
  3.  * 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 - 2011, 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 "acdispat.h"
  121. #include "acinterp.h"
  122. #include "acnamesp.h"
  123. #include "acdisasm.h"
  124.  
  125.  
  126. #define _COMPONENT          ACPI_DISPATCHER
  127.         ACPI_MODULE_NAME    ("dsmethod")
  128.  
  129. /* Local prototypes */
  130.  
  131. static ACPI_STATUS
  132. AcpiDsCreateMethodMutex (
  133.     ACPI_OPERAND_OBJECT     *MethodDesc);
  134.  
  135.  
  136. /*******************************************************************************
  137.  *
  138.  * FUNCTION:    AcpiDsMethodError
  139.  *
  140.  * PARAMETERS:  Status          - Execution status
  141.  *              WalkState       - Current state
  142.  *
  143.  * RETURN:      Status
  144.  *
  145.  * DESCRIPTION: Called on method error. Invoke the global exception handler if
  146.  *              present, dump the method data if the disassembler is configured
  147.  *
  148.  *              Note: Allows the exception handler to change the status code
  149.  *
  150.  ******************************************************************************/
  151.  
  152. ACPI_STATUS
  153. AcpiDsMethodError (
  154.     ACPI_STATUS             Status,
  155.     ACPI_WALK_STATE         *WalkState)
  156. {
  157.     ACPI_FUNCTION_ENTRY ();
  158.  
  159.  
  160.     /* Ignore AE_OK and control exception codes */
  161.  
  162.     if (ACPI_SUCCESS (Status) ||
  163.         (Status & AE_CODE_CONTROL))
  164.     {
  165.         return (Status);
  166.     }
  167.  
  168.     /* Invoke the global exception handler */
  169.  
  170.     if (AcpiGbl_ExceptionHandler)
  171.     {
  172.         /* Exit the interpreter, allow handler to execute methods */
  173.  
  174.         AcpiExExitInterpreter ();
  175.  
  176.         /*
  177.          * Handler can map the exception code to anything it wants, including
  178.          * AE_OK, in which case the executing method will not be aborted.
  179.          */
  180.         Status = AcpiGbl_ExceptionHandler (Status,
  181.                     WalkState->MethodNode ?
  182.                         WalkState->MethodNode->Name.Integer : 0,
  183.                     WalkState->Opcode, WalkState->AmlOffset, NULL);
  184.         AcpiExEnterInterpreter ();
  185.     }
  186.  
  187.     AcpiDsClearImplicitReturn (WalkState);
  188.  
  189. #ifdef ACPI_DISASSEMBLER
  190.     if (ACPI_FAILURE (Status))
  191.     {
  192.         /* Display method locals/args if disassembler is present */
  193.  
  194.         AcpiDmDumpMethodInfo (Status, WalkState, WalkState->Op);
  195.     }
  196. #endif
  197.  
  198.     return (Status);
  199. }
  200.  
  201.  
  202. /*******************************************************************************
  203.  *
  204.  * FUNCTION:    AcpiDsCreateMethodMutex
  205.  *
  206.  * PARAMETERS:  ObjDesc             - The method object
  207.  *
  208.  * RETURN:      Status
  209.  *
  210.  * DESCRIPTION: Create a mutex object for a serialized control method
  211.  *
  212.  ******************************************************************************/
  213.  
  214. static ACPI_STATUS
  215. AcpiDsCreateMethodMutex (
  216.     ACPI_OPERAND_OBJECT     *MethodDesc)
  217. {
  218.     ACPI_OPERAND_OBJECT     *MutexDesc;
  219.     ACPI_STATUS             Status;
  220.  
  221.  
  222.     ACPI_FUNCTION_TRACE (DsCreateMethodMutex);
  223.  
  224.  
  225.     /* Create the new mutex object */
  226.  
  227.     MutexDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX);
  228.     if (!MutexDesc)
  229.     {
  230.         return_ACPI_STATUS (AE_NO_MEMORY);
  231.     }
  232.  
  233.     /* Create the actual OS Mutex */
  234.  
  235.     Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex);
  236.     if (ACPI_FAILURE (Status))
  237.     {
  238.         return_ACPI_STATUS (Status);
  239.     }
  240.  
  241.     MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel;
  242.     MethodDesc->Method.Mutex = MutexDesc;
  243.     return_ACPI_STATUS (AE_OK);
  244. }
  245.  
  246.  
  247. /*******************************************************************************
  248.  *
  249.  * FUNCTION:    AcpiDsBeginMethodExecution
  250.  *
  251.  * PARAMETERS:  MethodNode          - Node of the method
  252.  *              ObjDesc             - The method object
  253.  *              WalkState           - current state, NULL if not yet executing
  254.  *                                    a method.
  255.  *
  256.  * RETURN:      Status
  257.  *
  258.  * DESCRIPTION: Prepare a method for execution.  Parses the method if necessary,
  259.  *              increments the thread count, and waits at the method semaphore
  260.  *              for clearance to execute.
  261.  *
  262.  ******************************************************************************/
  263.  
  264. ACPI_STATUS
  265. AcpiDsBeginMethodExecution (
  266.     ACPI_NAMESPACE_NODE     *MethodNode,
  267.     ACPI_OPERAND_OBJECT     *ObjDesc,
  268.     ACPI_WALK_STATE         *WalkState)
  269. {
  270.     ACPI_STATUS             Status = AE_OK;
  271.  
  272.  
  273.     ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode);
  274.  
  275.  
  276.     if (!MethodNode)
  277.     {
  278.         return_ACPI_STATUS (AE_NULL_ENTRY);
  279.     }
  280.  
  281.     /* Prevent wraparound of thread count */
  282.  
  283.     if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX)
  284.     {
  285.         ACPI_ERROR ((AE_INFO,
  286.             "Method reached maximum reentrancy limit (255)"));
  287.         return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
  288.     }
  289.  
  290.     /*
  291.      * If this method is serialized, we need to acquire the method mutex.
  292.      */
  293.     if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED)
  294.     {
  295.         /*
  296.          * Create a mutex for the method if it is defined to be Serialized
  297.          * and a mutex has not already been created. We defer the mutex creation
  298.          * until a method is actually executed, to minimize the object count
  299.          */
  300.         if (!ObjDesc->Method.Mutex)
  301.         {
  302.             Status = AcpiDsCreateMethodMutex (ObjDesc);
  303.             if (ACPI_FAILURE (Status))
  304.             {
  305.                 return_ACPI_STATUS (Status);
  306.             }
  307.         }
  308.  
  309.         /*
  310.          * The CurrentSyncLevel (per-thread) must be less than or equal to
  311.          * the sync level of the method. This mechanism provides some
  312.          * deadlock prevention
  313.          *
  314.          * Top-level method invocation has no walk state at this point
  315.          */
  316.         if (WalkState &&
  317.             (WalkState->Thread->CurrentSyncLevel > ObjDesc->Method.Mutex->Mutex.SyncLevel))
  318.         {
  319.             ACPI_ERROR ((AE_INFO,
  320.                 "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)",
  321.                 AcpiUtGetNodeName (MethodNode),
  322.                 WalkState->Thread->CurrentSyncLevel));
  323.  
  324.             return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
  325.         }
  326.  
  327.         /*
  328.          * Obtain the method mutex if necessary. Do not acquire mutex for a
  329.          * recursive call.
  330.          */
  331.         if (!WalkState ||
  332.             !ObjDesc->Method.Mutex->Mutex.ThreadId ||
  333.             (WalkState->Thread->ThreadId != ObjDesc->Method.Mutex->Mutex.ThreadId))
  334.         {
  335.             /*
  336.              * Acquire the method mutex. This releases the interpreter if we
  337.              * block (and reacquires it before it returns)
  338.              */
  339.             Status = AcpiExSystemWaitMutex (ObjDesc->Method.Mutex->Mutex.OsMutex,
  340.                         ACPI_WAIT_FOREVER);
  341.             if (ACPI_FAILURE (Status))
  342.             {
  343.                 return_ACPI_STATUS (Status);
  344.             }
  345.  
  346.             /* Update the mutex and walk info and save the original SyncLevel */
  347.  
  348.             if (WalkState)
  349.             {
  350.                 ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
  351.                     WalkState->Thread->CurrentSyncLevel;
  352.  
  353.                 ObjDesc->Method.Mutex->Mutex.ThreadId = WalkState->Thread->ThreadId;
  354.                 WalkState->Thread->CurrentSyncLevel = ObjDesc->Method.SyncLevel;
  355.             }
  356.             else
  357.             {
  358.                 ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
  359.                     ObjDesc->Method.Mutex->Mutex.SyncLevel;
  360.             }
  361.         }
  362.  
  363.         /* Always increase acquisition depth */
  364.  
  365.         ObjDesc->Method.Mutex->Mutex.AcquisitionDepth++;
  366.     }
  367.  
  368.     /*
  369.      * Allocate an Owner ID for this method, only if this is the first thread
  370.      * to begin concurrent execution. We only need one OwnerId, even if the
  371.      * method is invoked recursively.
  372.      */
  373.     if (!ObjDesc->Method.OwnerId)
  374.     {
  375.         Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
  376.         if (ACPI_FAILURE (Status))
  377.         {
  378.             goto Cleanup;
  379.         }
  380.     }
  381.  
  382.     /*
  383.      * Increment the method parse tree thread count since it has been
  384.      * reentered one more time (even if it is the same thread)
  385.      */
  386.     ObjDesc->Method.ThreadCount++;
  387.     AcpiMethodCount++;
  388.     return_ACPI_STATUS (Status);
  389.  
  390.  
  391. Cleanup:
  392.     /* On error, must release the method mutex (if present) */
  393.  
  394.     if (ObjDesc->Method.Mutex)
  395.     {
  396.         AcpiOsReleaseMutex (ObjDesc->Method.Mutex->Mutex.OsMutex);
  397.     }
  398.     return_ACPI_STATUS (Status);
  399. }
  400.  
  401.  
  402. /*******************************************************************************
  403.  *
  404.  * FUNCTION:    AcpiDsCallControlMethod
  405.  *
  406.  * PARAMETERS:  Thread              - Info for this thread
  407.  *              ThisWalkState       - Current walk state
  408.  *              Op                  - Current Op to be walked
  409.  *
  410.  * RETURN:      Status
  411.  *
  412.  * DESCRIPTION: Transfer execution to a called control method
  413.  *
  414.  ******************************************************************************/
  415.  
  416. ACPI_STATUS
  417. AcpiDsCallControlMethod (
  418.     ACPI_THREAD_STATE       *Thread,
  419.     ACPI_WALK_STATE         *ThisWalkState,
  420.     ACPI_PARSE_OBJECT       *Op)
  421. {
  422.     ACPI_STATUS             Status;
  423.     ACPI_NAMESPACE_NODE     *MethodNode;
  424.     ACPI_WALK_STATE         *NextWalkState = NULL;
  425.     ACPI_OPERAND_OBJECT     *ObjDesc;
  426.     ACPI_EVALUATE_INFO      *Info;
  427.     UINT32                  i;
  428.  
  429.  
  430.     ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState);
  431.  
  432.     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Calling method %p, currentstate=%p\n",
  433.         ThisWalkState->PrevOp, ThisWalkState));
  434.  
  435.     /*
  436.      * Get the namespace entry for the control method we are about to call
  437.      */
  438.     MethodNode = ThisWalkState->MethodCallNode;
  439.     if (!MethodNode)
  440.     {
  441.         return_ACPI_STATUS (AE_NULL_ENTRY);
  442.     }
  443.  
  444.     ObjDesc = AcpiNsGetAttachedObject (MethodNode);
  445.     if (!ObjDesc)
  446.     {
  447.         return_ACPI_STATUS (AE_NULL_OBJECT);
  448.     }
  449.  
  450.     /* Init for new method, possibly wait on method mutex */
  451.  
  452.     Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc,
  453.                 ThisWalkState);
  454.     if (ACPI_FAILURE (Status))
  455.     {
  456.         return_ACPI_STATUS (Status);
  457.     }
  458.  
  459.     /* Begin method parse/execution. Create a new walk state */
  460.  
  461.     NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwnerId,
  462.                         NULL, ObjDesc, Thread);
  463.     if (!NextWalkState)
  464.     {
  465.         Status = AE_NO_MEMORY;
  466.         goto Cleanup;
  467.     }
  468.  
  469.     /*
  470.      * The resolved arguments were put on the previous walk state's operand
  471.      * stack. Operands on the previous walk state stack always
  472.      * start at index 0. Also, null terminate the list of arguments
  473.      */
  474.     ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL;
  475.  
  476.     /*
  477.      * Allocate and initialize the evaluation information block
  478.      * TBD: this is somewhat inefficient, should change interface to
  479.      * DsInitAmlWalk. For now, keeps this struct off the CPU stack
  480.      */
  481.     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
  482.     if (!Info)
  483.     {
  484.         return_ACPI_STATUS (AE_NO_MEMORY);
  485.     }
  486.  
  487.     Info->Parameters = &ThisWalkState->Operands[0];
  488.  
  489.     Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode,
  490.                 ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength,
  491.                 Info, ACPI_IMODE_EXECUTE);
  492.  
  493.     ACPI_FREE (Info);
  494.     if (ACPI_FAILURE (Status))
  495.     {
  496.         goto Cleanup;
  497.     }
  498.  
  499.     /*
  500.      * Delete the operands on the previous walkstate operand stack
  501.      * (they were copied to new objects)
  502.      */
  503.     for (i = 0; i < ObjDesc->Method.ParamCount; i++)
  504.     {
  505.         AcpiUtRemoveReference (ThisWalkState->Operands [i]);
  506.         ThisWalkState->Operands [i] = NULL;
  507.     }
  508.  
  509.     /* Clear the operand stack */
  510.  
  511.     ThisWalkState->NumOperands = 0;
  512.  
  513.     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  514.         "**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
  515.         MethodNode->Name.Ascii, NextWalkState));
  516.  
  517.     /* Invoke an internal method if necessary */
  518.  
  519.     if (ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY)
  520.     {
  521.         Status = ObjDesc->Method.Dispatch.Implementation (NextWalkState);
  522.         if (Status == AE_OK)
  523.         {
  524.             Status = AE_CTRL_TERMINATE;
  525.         }
  526.     }
  527.  
  528.     return_ACPI_STATUS (Status);
  529.  
  530.  
  531. Cleanup:
  532.  
  533.     /* On error, we must terminate the method properly */
  534.  
  535.     AcpiDsTerminateControlMethod (ObjDesc, NextWalkState);
  536.     if (NextWalkState)
  537.     {
  538.         AcpiDsDeleteWalkState (NextWalkState);
  539.     }
  540.  
  541.     return_ACPI_STATUS (Status);
  542. }
  543.  
  544.  
  545. /*******************************************************************************
  546.  *
  547.  * FUNCTION:    AcpiDsRestartControlMethod
  548.  *
  549.  * PARAMETERS:  WalkState           - State for preempted method (caller)
  550.  *              ReturnDesc          - Return value from the called method
  551.  *
  552.  * RETURN:      Status
  553.  *
  554.  * DESCRIPTION: Restart a method that was preempted by another (nested) method
  555.  *              invocation.  Handle the return value (if any) from the callee.
  556.  *
  557.  ******************************************************************************/
  558.  
  559. ACPI_STATUS
  560. AcpiDsRestartControlMethod (
  561.     ACPI_WALK_STATE         *WalkState,
  562.     ACPI_OPERAND_OBJECT     *ReturnDesc)
  563. {
  564.     ACPI_STATUS             Status;
  565.     int                     SameAsImplicitReturn;
  566.  
  567.  
  568.     ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState);
  569.  
  570.  
  571.     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  572.         "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
  573.         AcpiUtGetNodeName (WalkState->MethodNode),
  574.         WalkState->MethodCallOp, ReturnDesc));
  575.  
  576.     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  577.         "    ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
  578.         WalkState->ReturnUsed,
  579.         WalkState->Results, WalkState));
  580.  
  581.     /* Did the called method return a value? */
  582.  
  583.     if (ReturnDesc)
  584.     {
  585.         /* Is the implicit return object the same as the return desc? */
  586.  
  587.         SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc);
  588.  
  589.         /* Are we actually going to use the return value? */
  590.  
  591.         if (WalkState->ReturnUsed)
  592.         {
  593.             /* Save the return value from the previous method */
  594.  
  595.             Status = AcpiDsResultPush (ReturnDesc, WalkState);
  596.             if (ACPI_FAILURE (Status))
  597.             {
  598.                 AcpiUtRemoveReference (ReturnDesc);
  599.                 return_ACPI_STATUS (Status);
  600.             }
  601.  
  602.             /*
  603.              * Save as THIS method's return value in case it is returned
  604.              * immediately to yet another method
  605.              */
  606.             WalkState->ReturnDesc = ReturnDesc;
  607.         }
  608.  
  609.         /*
  610.          * The following code is the optional support for the so-called
  611.          * "implicit return". Some AML code assumes that the last value of the
  612.          * method is "implicitly" returned to the caller, in the absence of an
  613.          * explicit return value.
  614.          *
  615.          * Just save the last result of the method as the return value.
  616.          *
  617.          * NOTE: this is optional because the ASL language does not actually
  618.          * support this behavior.
  619.          */
  620.         else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) ||
  621.                  SameAsImplicitReturn)
  622.         {
  623.             /*
  624.              * Delete the return value if it will not be used by the
  625.              * calling method or remove one reference if the explicit return
  626.              * is the same as the implicit return value.
  627.              */
  628.             AcpiUtRemoveReference (ReturnDesc);
  629.         }
  630.     }
  631.  
  632.     return_ACPI_STATUS (AE_OK);
  633. }
  634.  
  635.  
  636. /*******************************************************************************
  637.  *
  638.  * FUNCTION:    AcpiDsTerminateControlMethod
  639.  *
  640.  * PARAMETERS:  MethodDesc          - Method object
  641.  *              WalkState           - State associated with the method
  642.  *
  643.  * RETURN:      None
  644.  *
  645.  * DESCRIPTION: Terminate a control method.  Delete everything that the method
  646.  *              created, delete all locals and arguments, and delete the parse
  647.  *              tree if requested.
  648.  *
  649.  * MUTEX:       Interpreter is locked
  650.  *
  651.  ******************************************************************************/
  652.  
  653. void
  654. AcpiDsTerminateControlMethod (
  655.     ACPI_OPERAND_OBJECT     *MethodDesc,
  656.     ACPI_WALK_STATE         *WalkState)
  657. {
  658.  
  659.     ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState);
  660.  
  661.  
  662.     /* MethodDesc is required, WalkState is optional */
  663.  
  664.     if (!MethodDesc)
  665.     {
  666.         return_VOID;
  667.     }
  668.  
  669.     if (WalkState)
  670.     {
  671.         /* Delete all arguments and locals */
  672.  
  673.         AcpiDsMethodDataDeleteAll (WalkState);
  674.  
  675.         /*
  676.          * If method is serialized, release the mutex and restore the
  677.          * current sync level for this thread
  678.          */
  679.         if (MethodDesc->Method.Mutex)
  680.         {
  681.             /* Acquisition Depth handles recursive calls */
  682.  
  683.             MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--;
  684.             if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth)
  685.             {
  686.                 WalkState->Thread->CurrentSyncLevel =
  687.                     MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel;
  688.  
  689.                 AcpiOsReleaseMutex (MethodDesc->Method.Mutex->Mutex.OsMutex);
  690.                 MethodDesc->Method.Mutex->Mutex.ThreadId = 0;
  691.             }
  692.         }
  693.  
  694.         /*
  695.          * Delete any namespace objects created anywhere within the
  696.          * namespace by the execution of this method. Unless:
  697.          * 1) This method is a module-level executable code method, in which
  698.          *    case we want make the objects permanent.
  699.          * 2) There are other threads executing the method, in which case we
  700.          *    will wait until the last thread has completed.
  701.          */
  702.         if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) &&
  703.              (MethodDesc->Method.ThreadCount == 1))
  704.         {
  705.             /* Delete any direct children of (created by) this method */
  706.  
  707.             AcpiNsDeleteNamespaceSubtree (WalkState->MethodNode);
  708.  
  709.             /*
  710.              * Delete any objects that were created by this method
  711.              * elsewhere in the namespace (if any were created).
  712.              * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the
  713.              * deletion such that we don't have to perform an entire
  714.              * namespace walk for every control method execution.
  715.              */
  716.             if (MethodDesc->Method.InfoFlags & ACPI_METHOD_MODIFIED_NAMESPACE)
  717.             {
  718.                 AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId);
  719.                 MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_MODIFIED_NAMESPACE;
  720.             }
  721.         }
  722.     }
  723.  
  724.     /* Decrement the thread count on the method */
  725.  
  726.     if (MethodDesc->Method.ThreadCount)
  727.     {
  728.         MethodDesc->Method.ThreadCount--;
  729.     }
  730.     else
  731.     {
  732.         ACPI_ERROR ((AE_INFO,
  733.             "Invalid zero thread count in method"));
  734.     }
  735.  
  736.     /* Are there any other threads currently executing this method? */
  737.  
  738.     if (MethodDesc->Method.ThreadCount)
  739.     {
  740.         /*
  741.          * Additional threads. Do not release the OwnerId in this case,
  742.          * we immediately reuse it for the next thread executing this method
  743.          */
  744.         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  745.             "*** Completed execution of one thread, %u threads remaining\n",
  746.             MethodDesc->Method.ThreadCount));
  747.     }
  748.     else
  749.     {
  750.         /* This is the only executing thread for this method */
  751.  
  752.         /*
  753.          * Support to dynamically change a method from NotSerialized to
  754.          * Serialized if it appears that the method is incorrectly written and
  755.          * does not support multiple thread execution. The best example of this
  756.          * is if such a method creates namespace objects and blocks. A second
  757.          * thread will fail with an AE_ALREADY_EXISTS exception.
  758.          *
  759.          * This code is here because we must wait until the last thread exits
  760.          * before marking the method as serialized.
  761.          */
  762.         if (MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED_PENDING)
  763.         {
  764.             if (WalkState)
  765.             {
  766.                 ACPI_INFO ((AE_INFO,
  767.                     "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
  768.                     WalkState->MethodNode->Name.Ascii));
  769.             }
  770.  
  771.             /*
  772.              * Method tried to create an object twice and was marked as
  773.              * "pending serialized". The probable cause is that the method
  774.              * cannot handle reentrancy.
  775.              *
  776.              * The method was created as NotSerialized, but it tried to create
  777.              * a named object and then blocked, causing the second thread
  778.              * entrance to begin and then fail. Workaround this problem by
  779.              * marking the method permanently as Serialized when the last
  780.              * thread exits here.
  781.              */
  782.             MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_SERIALIZED_PENDING;
  783.             MethodDesc->Method.InfoFlags |= ACPI_METHOD_SERIALIZED;
  784.             MethodDesc->Method.SyncLevel = 0;
  785.         }
  786.  
  787.         /* No more threads, we can free the OwnerId */
  788.  
  789.         if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL))
  790.         {
  791.             AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId);
  792.         }
  793.     }
  794.  
  795.     return_VOID;
  796. }
  797.  
  798.  
  799.