Need to pass in the Method NTE

date	2000.08.09.17.09.00;	author rmoore1;	state Exp;
This commit is contained in:
aystarik 2005-06-29 17:01:34 +00:00
parent 6188aaa5a0
commit fc522540d4

View File

@ -117,19 +117,28 @@
#define __DSMETHOD_C__
#include "acpi.h"
#include "parser.h"
#include "acparser.h"
#include "amlcode.h"
#include "dispatch.h"
#include "interp.h"
#include "namesp.h"
#include "tables.h"
#include "debugger.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
#include "actables.h"
#include "acdebug.h"
#define _COMPONENT DISPATCHER
MODULE_NAME ("dsmethod");
/* TBD: move to acparser.h */
ACPI_PARSE_STATE *
AcpiPsCreateState (
UINT8 *Aml,
INT32 AmlSize);
/*******************************************************************************
*
* FUNCTION: AcpiDsParseMethod
@ -155,7 +164,7 @@ AcpiDsParseMethod (
ACPI_STATUS Status;
ACPI_OBJECT_INTERNAL *ObjDesc;
ACPI_GENERIC_OP *Op;
NAME_TABLE_ENTRY *Entry;
ACPI_NAMED_OBJECT *Entry;
ACPI_OWNER_ID OwnerId;
@ -169,13 +178,14 @@ AcpiDsParseMethod (
return_ACPI_STATUS (AE_NULL_ENTRY);
}
DEBUG_PRINT (ACPI_INFO, ("DsParseMethod: **** Parsing [%4.4s] **** Nte=%p\n",
&((NAME_TABLE_ENTRY *)ObjHandle)->Name, ObjHandle));
DEBUG_PRINT (ACPI_INFO,
("DsParseMethod: **** Parsing [%4.4s] **** Nte=%p\n",
&((ACPI_NAMED_OBJECT*)ObjHandle)->Name, ObjHandle));
/* Extract the method object from the method NTE */
Entry = (NAME_TABLE_ENTRY *) ObjHandle;
Entry = (ACPI_NAMED_OBJECT*) ObjHandle;
ObjDesc = Entry->Object;
if (!ObjDesc)
{
@ -187,14 +197,18 @@ AcpiDsParseMethod (
if ((ObjDesc->Method.Concurrency != INFINITE_CONCURRENCY) &&
(!ObjDesc->Method.Semaphore))
{
Status = AcpiOsCreateSemaphore (1, ObjDesc->Method.Concurrency, &ObjDesc->Method.Semaphore);
Status = AcpiOsCreateSemaphore (1,ObjDesc->Method.Concurrency,
&ObjDesc->Method.Semaphore);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
}
/* Allocate a new parser op to be the root of the parsed method tree */
/*
* Allocate a new parser op to be the root of the parsed
* method tree
*/
Op = AcpiPsAllocOp (AML_METHOD_OP);
if (!Op)
@ -205,39 +219,46 @@ AcpiDsParseMethod (
/* Init new op with the method name and pointer back to the NTE */
AcpiPsSetName (Op, Entry->Name);
Op->NameTableEntry = Entry;
Op->AcpiNamedObject = Entry;
/*
* Parse the method, creating a parse tree.
*
* The parse also includes a first pass load of the namespace where
* newly declared named objects are added into the namespace. Actual evaluation
* of the named objects (what would be called a "second pass") happens during the
* actual execution of the method so that operands to the named objects can take
* on dynamic run-time values.
* The parse also includes a first pass load of the
* namespace where newly declared named objects are
* added into the namespace. Actual evaluation of
* the named objects (what would be called a "second
* pass") happens during the actual execution of the
* method so that operands to the named objects can
* take on dynamic run-time values.
*/
Status = AcpiPsParseAml (Op, ObjDesc->Method.Pcode, ObjDesc->Method.PcodeLength, 0);
Status = AcpiPsParseAml (Op, ObjDesc->Method.Pcode,
ObjDesc->Method.PcodeLength, PARSE_DELETE_TREE,
Entry, NULL, NULL,
AcpiDsLoad1BeginOp, AcpiDsLoad1EndOp);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
/* Get a new OwnerId for objects created by this method */
OwnerId = AcpiCmAllocateOwnerId (OWNER_TYPE_METHOD);
ObjDesc->Method.OwningId = OwnerId;
/* Install the parsed tree in the method object */
/* TBD: [Restructure] Obsolete field? */
ObjDesc->Method.ParserOp = Op;
ObjDesc->Method.OwningId = OwnerId;
DEBUG_EXEC (AcpiDbGenerateStatistics (Op, 1));
DEBUG_PRINT (ACPI_INFO, ("DsParseMethod: **** [%4.4s] Parsed **** Nte=%p Op=%p\n",
&((NAME_TABLE_ENTRY *)ObjHandle)->Name, ObjHandle, Op));
DEBUG_PRINT (ACPI_INFO,
("DsParseMethod: **** [%4.4s] Parsed **** Nte=%p Op=%p\n",
&((ACPI_NAMED_OBJECT*)ObjHandle)->Name, ObjHandle, Op));
return_ACPI_STATUS (Status);
}
@ -253,8 +274,8 @@ AcpiDsParseMethod (
* RETURN: Status
*
* DESCRIPTION: Prepare a method for execution. Parses the method if necessary,
* increments the thread count, and waits at the method semaphore for
* clearance to execute.
* increments the thread count, and waits at the method semaphore
* for clearance to execute.
*
* MUTEX: Locks/unlocks parser.
*
@ -262,7 +283,7 @@ AcpiDsParseMethod (
ACPI_STATUS
AcpiDsBeginMethodExecution (
NAME_TABLE_ENTRY *MethodEntry,
ACPI_NAMED_OBJECT *MethodEntry,
ACPI_OBJECT_INTERNAL *ObjDesc)
{
ACPI_STATUS Status = AE_OK;
@ -283,51 +304,60 @@ AcpiDsBeginMethodExecution (
}
/*
* Lock the parser while we check for and possibly parse the control method
* Lock the parser while we check for and possibly parse the
* control method
*/
AcpiCmAcquireMutex (MTX_PARSER);
AcpiCmAcquireMutex (ACPI_MTX_PARSER);
/* If method is not parsed at this time, we must parse it first */
/* TBD: REMOVE
if (!ObjDesc->Method.ParserOp)
{
DEBUG_PRINT (ACPI_INFO, ("PsxExecute: **** Parsing Method **** obj=%p\n", ObjDesc));
DEBUG_PRINT (ACPI_INFO,
("PsxExecute: **** Parsing Method **** obj=%p\n", ObjDesc));
Status = AcpiDsParseMethod (MethodEntry);
if (ACPI_FAILURE (Status))
{
AcpiCmReleaseMutex (MTX_PARSER);
AcpiCmReleaseMutex (ACPI_MTX_PARSER);
return_ACPI_STATUS (Status);
}
}
*/
/*
* Increment the method parse tree thread count since there is one additional thread executing
* in it. If configured for deletion-on-exit, the parse tree will be deleted when the last
* thread completes execution of the method
* Increment the method parse tree thread count since there
* is one additional thread executing in it. If configured
* for deletion-on-exit, the parse tree will be deleted when
* the last thread completes execution of the method
*/
/* TBD: REMOVE
((ACPI_DEFERRED_OP *) ObjDesc->Method.ParserOp)->ThreadCount++;
*/
/*
* Parsing is complete, we can unlock the parser. Parse tree cannot be deleted
* at least until this thread completes.
* Parsing is complete, we can unlock the parser. Parse tree
* cannot be deleted at least until this thread completes.
*/
AcpiCmReleaseMutex (MTX_PARSER);
AcpiCmReleaseMutex (ACPI_MTX_PARSER);
/*
* If there is a concurrency limit on this method, we need to obtain a unit
* from the method semaphore. This releases the interpreter if we block
* If there is a concurrency limit on this method, we need to
* obtain a unit from the method semaphore. This releases the
* interpreter if we block
*/
if (ObjDesc->Method.Semaphore)
{
Status = AcpiAmlSystemWaitSemaphore (ObjDesc->Method.Semaphore, WAIT_FOREVER);
Status = AcpiAmlSystemWaitSemaphore (ObjDesc->Method.Semaphore,
WAIT_FOREVER);
}
@ -357,24 +387,24 @@ AcpiDsCallControlMethod (
{
ACPI_STATUS Status;
ACPI_DEFERRED_OP *Method;
NAME_TABLE_ENTRY *MethodEntry;
ACPI_NAMED_OBJECT *MethodEntry;
ACPI_OBJECT_INTERNAL *ObjDesc;
ACPI_WALK_STATE *NextWalkState;
ACPI_PARSE_STATE *ParserState;
UINT32 i;
FUNCTION_TRACE_PTR ("DsCallControlMethod", ThisWalkState);
DEBUG_PRINT (TRACE_DISPATCH, ("DsCall, execute method %p, currentstate=%p\n",
ThisWalkState->PrevOp, ThisWalkState));
DEBUG_PRINT (TRACE_DISPATCH,
("DsCall, execute method %p, currentstate=%p\n",
ThisWalkState->PrevOp, ThisWalkState));
/*
* PrevOp points to the METHOD_CALL Op.
* Get the NTE entry (in the METHOD_CALL->NAME Op) and the corresponding METHOD Op
* Get the namespace entry for this control method
*/
MethodEntry = (ThisWalkState->PrevOp->Value.Arg)->NameTableEntry;
MethodEntry = ThisWalkState->MethodEntry;
if (!MethodEntry)
{
return_ACPI_STATUS (AE_NULL_ENTRY);
@ -386,6 +416,7 @@ AcpiDsCallControlMethod (
return_ACPI_STATUS (AE_NULL_OBJECT);
}
/* Parse method if necessary, wait on concurrency semaphore */
Status = AcpiDsBeginMethodExecution (MethodEntry, ObjDesc);
@ -396,25 +427,51 @@ AcpiDsCallControlMethod (
/* Save the (current) Op for when this walk is restarted */
ThisWalkState->MethodCallOp = ThisWalkState->PrevOp;
ThisWalkState->PrevOp = Op;
// ThisWalkState->MethodCallOp = ThisWalkState->PrevOp;
// ThisWalkState->PrevOp = Op;
Method = ObjDesc->Method.ParserOp;
/* Create a new state for the preempting walk */
NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwningId, (ACPI_GENERIC_OP *) Method, ObjDesc, WalkList);
if (!NextWalkState)
/* Create and initialize a new parser state */
ParserState = AcpiPsCreateState (ObjDesc->Method.Pcode,
ObjDesc->Method.PcodeLength);
if (!ParserState)
{
return_ACPI_STATUS (AE_NO_MEMORY);
}
AcpiPsInitScope (ParserState, (ACPI_GENERIC_OP *) Method);
ParserState->StartEntry = MethodEntry;
/* Create a new state for the preempting walk */
NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwningId,
(ACPI_GENERIC_OP *) Method,
ObjDesc, WalkList);
if (!NextWalkState)
{
/* TBD: delete parser state */
return_ACPI_STATUS (AE_NO_MEMORY);
}
NextWalkState->WalkType = WALK_METHOD;
NextWalkState->ParserState = ParserState;
NextWalkState->ParseFlags = ThisWalkState->ParseFlags;
NextWalkState->DescendingCallback = ThisWalkState->DescendingCallback;
NextWalkState->AscendingCallback = ThisWalkState->AscendingCallback;
/* The NextOp of the NextWalk will be the beginning of the method */
NextWalkState->NextOp = (ACPI_GENERIC_OP *) Method;
/* Open a new scope */
Status = AcpiDsScopeStackPush (MethodEntry->Scope, ACPI_TYPE_METHOD, NextWalkState);
Status = AcpiDsScopeStackPush (MethodEntry->ChildTable,
ACPI_TYPE_METHOD, NextWalkState);
if (ACPI_FAILURE (Status))
{
goto Cleanup;
@ -422,22 +479,50 @@ AcpiDsCallControlMethod (
/*
* Initialize the arguments for the method. The resolved arguments were put
* on the previous walk state's operand stack. Operands on the previous walk state
* stack always start at index 0.
* Initialize the arguments for the method. The resolved
* arguments were put on the previous walk state's operand
* stack. Operands on the previous walk state stack always
* start at index 0.
*/
Status = AcpiDsMethodDataInitArgs (&ThisWalkState->Operands[0], ThisWalkState->NumOperands);
Status = AcpiDsMethodDataInitArgs (&ThisWalkState->Operands[0],
ThisWalkState->NumOperands,
NextWalkState);
if (ACPI_FAILURE (Status))
{
goto Cleanup;
}
/* Delete the operands on the previous walkstate operand stack (they were copied to new objects) */
/* Create and init a root object */
Op = AcpiPsAllocOp (AML_SCOPE_OP);
if (!Op)
{
return_ACPI_STATUS (AE_NO_MEMORY);
}
Status = AcpiPsParseAml (Op, ObjDesc->Method.Pcode,
ObjDesc->Method.PcodeLength, PARSE_DELETE_TREE,
MethodEntry, NULL, NULL,
AcpiDsLoad1BeginOp, AcpiDsLoad1EndOp);
AcpiPsDeleteParseTree (Op);
/*
* Delete the operands on the previous walkstate operand stack
* (they were copied to new objects)
*/
for (i = 0; i < ObjDesc->Method.ParamCount; i++)
{
AcpiCmRemoveReference (ThisWalkState->Operands [i]);
ThisWalkState->Operands [i] = NULL;
}
/* Clear the operand stack */
@ -445,7 +530,8 @@ AcpiDsCallControlMethod (
ThisWalkState->NumOperands = 0;
DEBUG_PRINT (TRACE_DISPATCH, ("DsCall, starting nested execution, newstate=%p\n", NextWalkState));
DEBUG_PRINT (TRACE_DISPATCH,
("DsCall, starting nested execution, newstate=%p\n", NextWalkState));
return_ACPI_STATUS (AE_OK);
@ -486,22 +572,35 @@ AcpiDsRestartControlMethod (
if (ReturnDesc)
{
/* Get the return value (if any) from the previous method. NULL if no return value */
Status = AcpiDsResultStackPush (ReturnDesc, WalkState);
if (ACPI_FAILURE (Status))
if (WalkState->ReturnUsed)
{
/*
* Get the return value (if any) from the previous method.
* NULL if no return value
*/
Status = AcpiDsResultStackPush (ReturnDesc, WalkState);
if (ACPI_FAILURE (Status))
{
AcpiCmRemoveReference (ReturnDesc);
return_ACPI_STATUS (Status);
}
}
else
{
/*
* Delete the return value if it will not be used by the
* calling method
*/
AcpiCmRemoveReference (ReturnDesc);
return_ACPI_STATUS (Status);
}
/* Delete the return value if it will not be used by the calling method */
AcpiDsDeleteResultIfNotUsed (WalkState->MethodCallOp, ReturnDesc, WalkState);
}
DEBUG_PRINT (TRACE_DISPATCH, ("DsRestart: Method=%p Return=%p State=%p\n",
WalkState->MethodCallOp, ReturnDesc, WalkState));
DEBUG_PRINT (TRACE_DISPATCH,
("DsRestart: Method=%p Return=%p State=%p\n",
WalkState->MethodCallOp, ReturnDesc, WalkState));
return_ACPI_STATUS (AE_OK);
@ -529,7 +628,7 @@ AcpiDsTerminateControlMethod (
ACPI_STATUS Status;
ACPI_OBJECT_INTERNAL *ObjDesc;
ACPI_DEFERRED_OP *Op;
NAME_TABLE_ENTRY *MethodEntry;
ACPI_NAMED_OBJECT *MethodEntry;
FUNCTION_TRACE_PTR ("DsTerminateControlMethod", WalkState);
@ -549,13 +648,16 @@ AcpiDsTerminateControlMethod (
/*
* Lock the parser while we terminate this method.
* If this is the last thread executing the method, we have
* additional cleanup to perform
* If this is the last thread executing the method,
* we have additional cleanup to perform
*/
AcpiCmAcquireMutex (MTX_PARSER);
AcpiCmAcquireMutex (ACPI_MTX_PARSER);
/* The root of the method parse tree should be stored in the method object */
/*
* The root of the method parse tree should be stored
* in the method object
*/
Op = ObjDesc->Method.ParserOp;
if (!Op)
@ -567,7 +669,8 @@ AcpiDsTerminateControlMethod (
if (WalkState->MethodDesc->Method.Semaphore)
{
Status = AcpiOsSignalSemaphore (WalkState->MethodDesc->Method.Semaphore, 1);
Status = AcpiOsSignalSemaphore (
WalkState->MethodDesc->Method.Semaphore, 1);
}
/* Decrement the thread count on the method parse tree */
@ -576,43 +679,46 @@ AcpiDsTerminateControlMethod (
if (!Op->ThreadCount)
{
/*
* There are no more threads executing this method. Perform additional cleanup.
* There are no more threads executing this method. Perform
* additional cleanup.
*
* The method NTE is stored in the method Op
*/
MethodEntry = Op->NameTableEntry;
MethodEntry = Op->AcpiNamedObject;
/*
* Delete any namespace entries created immediately underneath the method
* Delete any namespace entries created immediately underneath
* the method
*/
AcpiCmAcquireMutex (MTX_NAMESPACE);
if (MethodEntry->Scope)
AcpiCmAcquireMutex (ACPI_MTX_NAMESPACE);
if (MethodEntry->ChildTable)
{
AcpiNsDeleteNamespaceSubtree (MethodEntry);
}
/*
* Delete any namespace entries created anywhere else within the namespace
* Delete any namespace entries created anywhere else within
* the namespace
*/
AcpiNsDeleteNamespaceByOwner (WalkState->MethodDesc->Method.OwningId);
AcpiCmReleaseMutex (MTX_NAMESPACE);
AcpiCmReleaseMutex (ACPI_MTX_NAMESPACE);
/*
* Delete the method's parse tree if asked to
* Delete the method's parse tree
*/
if (AcpiGbl_WhenToParseMethods & METHOD_DELETE_AT_COMPLETION)
{
AcpiPsDeleteParseTree (WalkState->MethodDesc->Method.ParserOp);
WalkState->MethodDesc->Method.ParserOp = NULL;
}
AcpiPsDeleteParseTree (WalkState->MethodDesc->Method.ParserOp);
WalkState->MethodDesc->Method.ParserOp = NULL;
}
UnlockAndExit:
AcpiCmReleaseMutex (MTX_PARSER);
AcpiCmReleaseMutex (ACPI_MTX_PARSER);
return_ACPI_STATUS (AE_OK);
}