Added parser op cache, NsLookup during method parse

date	2000.05.04.20.52.00;	author rmoore1;	state Exp;
This commit is contained in:
aystarik 2005-06-29 18:06:46 +00:00
parent 1e2a2c0dea
commit 8dd72f7325
3 changed files with 381 additions and 99 deletions

View File

@ -160,7 +160,7 @@ PsDeleteCompletedOp (
ACPI_GENERIC_OP *Op)
{
CmFree (Op);
PsFreeOp (Op);
return AE_OK;
}
@ -438,8 +438,65 @@ PsParseLoop (
/* TBD: what if a control method references outside its scope? */
/* ie - should we be using nslookup here? */
Op = PsFind (PsGetParentScope (ParserState),
PsGetNextNamestring (ParserState), Opcode, 1);
if (Gbl_ParsedNamespaceRoot)
{
Op = PsFind (PsGetParentScope (ParserState),
PsGetNextNamestring (ParserState), Opcode, 1);
}
#ifndef PARSER_ONLY
else
{
/*
* The full parse tree has already been deleted -- therefore, we are parsing
* a control method. We can lookup the name in the namespace instead of
* the parse tree!
*/
NAME_TABLE_ENTRY *Nte = NULL;
ACPI_GENERIC_STATE ScopeInfo;
char *Path;
Path = PsGetNextNamestring (ParserState);
/*
* Lookup the name in the internal namespace
*/
ScopeInfo.Scope.Entry = NULL;
Nte = ParserState->StartOp->NameTableEntry;
if (Nte)
{
ScopeInfo.Scope.Entry = Nte->Scope;
}
/*
* Enter the object into the namespace
*/
Status = NsLookup (&ScopeInfo, Path, ACPI_TYPE_Any, IMODE_LoadPass2, /* Create if not found */
NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, NULL, &Nte);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
/* Create a new op */
Op = PsAllocOp (Opcode);
if (!Op)
{
return_ACPI_STATUS (AE_NO_MEMORY);
}
/* Initialize */
((ACPI_NAMED_OP *)Op)->Name = Nte->Name;
Op->NameTableEntry = Nte;
PsAppendArg (PsGetParentScope (ParserState), Op);
}
#endif
if (!Op)
{

View File

@ -122,6 +122,11 @@
MODULE_NAME ("psutils");
#define PARSEOP_GENERIC 1
#define PARSEOP_NAMED 2
#define PARSEOP_DEFERRED 3
#define PARSEOP_BYTELIST 4
/*******************************************************************************
*
@ -144,6 +149,7 @@ PsInitOp (
ACPI_OP_INFO *AmlOp;
Op->DataType = DESC_TYPE_PARSER;
Op->Opcode = Opcode;
@ -166,6 +172,8 @@ PsInitOp (
* RETURN: Pointer to the new Op.
*
* DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on opcode
* A cache of opcodes is available for the pure GENERIC_OP, since this
* is by far the most commonly used.
*
******************************************************************************/
@ -175,6 +183,7 @@ PsAllocOp (
{
ACPI_GENERIC_OP *Op = NULL;
UINT32 Size;
UINT8 Flags;
/* Allocate the minimum required size object */
@ -182,29 +191,63 @@ PsAllocOp (
if (PsIsDeferredOp (Opcode))
{
Size = sizeof (ACPI_DEFERRED_OP);
Flags = PARSEOP_DEFERRED;
}
else if (PsIsNamedOp (Opcode))
{
Size = sizeof (ACPI_NAMED_OP);
Flags = PARSEOP_NAMED;
}
else if (PsIsBytelistOp (Opcode))
{
Size = sizeof (ACPI_BYTELIST_OP);
Flags = PARSEOP_BYTELIST;
}
else
{
Size = sizeof (ACPI_GENERIC_OP);
Flags = PARSEOP_GENERIC;
/*
* The generic op is by far the most common (16 to 1), and therefore the op cache is
* implemented with this type.
*
* Check if there is an Op already available in the cache
*/
CmAcquireMutex (MTX_MEMORY);
if (Gbl_ParseCache)
{
/* Extract an op from the front of the cache list */
Gbl_ParseCacheRequests++;
Gbl_ParseCacheDepth--;
Op = Gbl_ParseCache;
Gbl_ParseCache = Op->Next;
/* Clear the previously used Op */
MEMSET (Op, 0, sizeof (ACPI_GENERIC_OP));
}
CmReleaseMutex (MTX_MEMORY);
}
/* Allocate and init the object */
/* Allocate a new Op if necessary */
Op = CmCallocate (Size);
if (!Op)
{
Op = CmCallocate (Size);
}
/* Initialize the Op */
if (Op)
{
PsInitOp (Op, Opcode);
Op->Flags = Flags;
}
return Op;
@ -212,16 +255,105 @@ PsAllocOp (
/*******************************************************************************
*
* FUNCTION: PsFreeOp
*
* PARAMETERS: Op - Op to be freed
*
* RETURN: None.
*
* DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list
* or actually free it.
*
******************************************************************************/
void
PsFreeOp (
ACPI_GENERIC_OP *Op)
{
if (Op->Flags == PARSEOP_GENERIC)
{
/* Is the cache full? */
if (Gbl_ParseCacheDepth < MAX_PARSE_CACHE_DEPTH)
{
/* Put a GENERIC_OP back into the cache */
CmAcquireMutex (MTX_MEMORY);
Gbl_ParseCacheDepth++;
Op->Next = Gbl_ParseCache;
Gbl_ParseCache = Op;
CmReleaseMutex (MTX_MEMORY);
return;
}
}
/*
* Not a GENERIC OP, or the cache is full, just free the Op
*/
CmFree (Op);
}
/*******************************************************************************
*
* FUNCTION: PsDeleteParseCache
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Free all objects that are on the parse cache list.
*
******************************************************************************/
void
PsDeleteParseCache (
void)
{
ACPI_GENERIC_OP *Next;
FUNCTION_TRACE ("PsDeleteParseCache");
/* Traverse the global cache list */
while (Gbl_ParseCache)
{
/* Delete one cached state object */
Next = Gbl_ParseCache->Next;
CmFree (Gbl_ParseCache);
Gbl_ParseCache = Next;
}
return_VOID;
}
/*
/*******************************************************************************
*
* FUNCTION: Utility functions
*
* DESCRIPTION: Low level functions
*
* TBD:
* 1) Some of these functions should be macros
* 2) Some can be simplified
*/
*
******************************************************************************/
/*
@ -248,6 +380,59 @@ PsIsPrefixChar (
}
BOOLEAN
PsIsNamespaceObjectOp (
UINT16 Opcode)
{
return ((BOOLEAN)
(Opcode == AML_ScopeOp ||
Opcode == AML_DeviceOp ||
Opcode == AML_ThermalZoneOp ||
Opcode == AML_MethodOp ||
Opcode == AML_PowerResOp ||
Opcode == AML_ProcessorOp ||
Opcode == AML_DefFieldOp ||
Opcode == AML_IndexFieldOp ||
Opcode == AML_BankFieldOp ||
Opcode == AML_NAMEDFIELD_OP ||
Opcode == AML_NameOp ||
Opcode == AML_AliasOp ||
Opcode == AML_MutexOp ||
Opcode == AML_EventOp ||
Opcode == AML_RegionOp ||
Opcode == AML_CreateFieldOp ||
Opcode == AML_BitFieldOp ||
Opcode == AML_ByteFieldOp ||
Opcode == AML_WordFieldOp ||
Opcode == AML_DWordFieldOp ||
Opcode == AML_METHODCALL_OP ||
Opcode == AML_NAMEPATH_OP));
}
BOOLEAN
PsIsNamespaceOp (
UINT16 Opcode)
{
return ((BOOLEAN)
(Opcode == AML_ScopeOp ||
Opcode == AML_DeviceOp ||
Opcode == AML_ThermalZoneOp ||
Opcode == AML_MethodOp ||
Opcode == AML_PowerResOp ||
Opcode == AML_ProcessorOp ||
Opcode == AML_DefFieldOp ||
Opcode == AML_IndexFieldOp ||
Opcode == AML_BankFieldOp ||
Opcode == AML_NameOp ||
Opcode == AML_AliasOp ||
Opcode == AML_MutexOp ||
Opcode == AML_EventOp ||
Opcode == AML_RegionOp ||
Opcode == AML_NAMEDFIELD_OP));
}
/*
* Is opcode for a named object Op?
@ -266,10 +451,7 @@ PsIsNamedObjectOp (
Opcode == AML_MethodOp ||
Opcode == AML_PowerResOp ||
Opcode == AML_ProcessorOp ||
Opcode == AML_DefFieldOp ||
Opcode == AML_IndexFieldOp ||
Opcode == AML_BankFieldOp ||
Opcode == AML_NAMEDFIELD ||
Opcode == AML_NAMEDFIELD_OP ||
Opcode == AML_NameOp ||
Opcode == AML_AliasOp ||
Opcode == AML_MutexOp ||
@ -282,8 +464,8 @@ PsIsNamedObjectOp (
Opcode == AML_ByteFieldOp ||
Opcode == AML_WordFieldOp ||
Opcode == AML_DWordFieldOp ||
Opcode == AML_METHODCALL ||
Opcode == AML_NAMEPATH));
Opcode == AML_METHODCALL_OP ||
Opcode == AML_NAMEPATH_OP));
}
@ -301,15 +483,12 @@ PsIsNamedOp (
Opcode == AML_MethodOp ||
Opcode == AML_PowerResOp ||
Opcode == AML_ProcessorOp ||
Opcode == AML_DefFieldOp ||
Opcode == AML_IndexFieldOp ||
Opcode == AML_BankFieldOp ||
Opcode == AML_NameOp ||
Opcode == AML_AliasOp ||
Opcode == AML_MutexOp ||
Opcode == AML_EventOp ||
Opcode == AML_RegionOp ||
Opcode == AML_NAMEDFIELD));
Opcode == AML_NAMEDFIELD_OP));
}
@ -330,7 +509,7 @@ BOOLEAN
PsIsBytelistOp (
UINT16 Opcode)
{
return ((BOOLEAN) (Opcode == AML_BYTELIST));
return ((BOOLEAN) (Opcode == AML_BYTELIST_OP));
}

View File

@ -118,6 +118,7 @@
#include <acpi.h>
#include <amlcode.h>
#include <parser.h>
#include <dispatch.h>
#include <namesp.h>
#include <interp.h>
@ -181,13 +182,15 @@ PsGetNextWalkOp (
* in case the Op object gets deleted by the callback routine
*/
Next = Op->Next;
Parent = Op->Parent;
Next = Op->Next;
Parent = Op->Parent;
Status = AscendingCallback (WalkState, Op);
if (Status == AE_TERMINATE)
switch (Status)
{
case AE_CTRL_TERMINATE:
/*
* A control method was terminated via a RETURN statement.
* The walk of this method is complete.
@ -196,50 +199,83 @@ PsGetNextWalkOp (
WalkState->NextOp = NULL;
return_ACPI_STATUS (AE_OK);
}
if (Status == AE_FALSE)
{
break;
case AE_CTRL_FALSE:
/*
* Predicate was false, so instead of moving on to the
* body (TermList), we close out the IF/WHILE
* Either an IF/WHILE Predicate was false or we encountered a BREAK opcode
*,In both cases, we do not execute the rest of the package; We simply
* close out the parent (finishing the walk of this branch of the tree)
* and continue execution at the parent level.
*/
Next = Parent->Next;
Status = AE_OK;
Status = AscendingCallback (WalkState, Parent);
/*
* If there is a sibling to the parent, we must close out the parent now,
* because we are going to continue to go downward (to the sibling)
* in the parse tree.
*/
if (Next)
{
Status = AscendingCallback (WalkState, Parent);
/* Now continue to the next node in the tree */
}
/* The parent sibling will be next */
/* Look for a sibling to the current op */
WalkState->PrevOp = Op;
WalkState->NextOp = Next;
WalkState->NextOpInfo = NEXT_OP_DOWNWARD;
if (Next)
{
/* There is a sibling, it will be next */
/* Continue downward */
WalkState->PrevOp = Op;
WalkState->NextOp = Next;
WalkState->NextOpInfo = NEXT_OP_DOWNWARD;
return_ACPI_STATUS (AE_OK);
}
return_ACPI_STATUS (Status);
}
/* Drop into the loop below because we are moving upwards in the tree */
break;
/*
* No sibling, but check status.
* Abort on error from callback routine
*/
default:
/*
* Check for a sibling to the current op. A sibling means
* we are still going "downward" in the tree.
*/
if (Status != AE_OK)
{
/* Next op will be the parent */
if (Next)
{
/* There is a sibling, it will be next */
WalkState->PrevOp = Op;
WalkState->NextOp = Parent;
WalkState->NextOpInfo = NEXT_OP_UPWARD;
WalkState->PrevOp = Op;
WalkState->NextOp = Next;
WalkState->NextOpInfo = NEXT_OP_DOWNWARD;
return_ACPI_STATUS (Status);
/* Continue downward */
return_ACPI_STATUS (Status);
}
/*
* No sibling, but check status.
* Abort on error from callback routine
*/
if (Status != AE_OK)
{
/* Next op will be the parent */
WalkState->PrevOp = Op;
WalkState->NextOp = Parent;
WalkState->NextOpInfo = NEXT_OP_UPWARD;
return_ACPI_STATUS (Status);
}
/* Drop into the loop below because we are moving upwards in the tree */
break;
}
}
@ -268,13 +304,16 @@ PsGetNextWalkOp (
Status = AscendingCallback (WalkState, Parent);
/* All evaluated predicates come through here */
if (Status == AE_FALSE)
switch (Status)
{
case AE_CTRL_FALSE:
/*
* Predicate was false, so instead of moving on to the
* body (TermList), we close out the IF/WHILE
* Either an IF/WHILE Predicate was false or we encountered a BREAK opcode
*,In both cases, we do not execute the rest of the package; We simply
* close out the parent (finishing the walk of this branch of the tree)
* and continue execution at the parent level.
*/
Parent = GrandParent;
@ -284,27 +323,31 @@ PsGetNextWalkOp (
Status = AscendingCallback (WalkState, Parent);
/* Now continue to the next node in the tree */
}
else if (Status == AE_TRUE)
{
break;
case AE_CTRL_TRUE:
/*
* Predicate of a WHILE was true and the loop just completed an execution.
* Go back to the start of the loop and reevaluate the predicate.
*/
Op = WalkState->ControlState->PredicateOp; /* Points to the predicate */
Op = WalkState->ControlState->Control.PredicateOp; /* Points to the predicate */
WalkState->ControlState->Common.State = CONTROL_PREDICATE_EXECUTING;
WalkState->ControlState->Exec = CONTROL_PREDICATE_EXECUTING;
WalkState->PrevOp = Op->Parent;
WalkState->NextOp = Op; /* Evaluate the predicate again (next) */
WalkState->NextOpInfo = NEXT_OP_DOWNWARD; /* Because we will traverse WHILE tree again */
return_ACPI_STATUS (AE_OK);
}
break;
case AE_CTRL_TERMINATE:
else if (Status == AE_TERMINATE)
{
/*
* A control method was terminated via a RETURN statement.
* The walk of this method is complete.
@ -313,8 +356,10 @@ PsGetNextWalkOp (
WalkState->NextOp = NULL;
return_ACPI_STATUS (AE_OK);
break;
}
/*
* If we are back to the starting point, the walk is complete.
*/
@ -405,7 +450,7 @@ PsWalkLoop (
FUNCTION_TRACE_PTR ("PsWalkLoop", StartOp);
WalkState = PsGetCurrentWalkState (WalkList);
WalkState = DsGetCurrentWalkState (WalkList);
/* Walk entire subtree, visiting all nodes depth-first */
@ -420,7 +465,7 @@ PsWalkLoop (
/*
* A TRUE exception means that an ELSE was detected, but the IF predicate evaluated TRUE.
*/
if (Status == AE_TRUE)
if (Status == AE_CTRL_TRUE)
{
/*
* Ignore the entire ELSE block by moving on to the the next opcode.
@ -437,15 +482,15 @@ PsWalkLoop (
/* A PENDING exception means that a control method invocation has been detected */
if (Status == AE_PENDING)
if (Status == AE_CTRL_PENDING)
{
/* Transfer control to the called control method */
Status = PsxCallControlMethod (WalkList, WalkState, Op);
Status = DsCallControlMethod (WalkList, WalkState, Op);
/* If the method call worked, a new walk state was created -- get it */
WalkState = PsGetCurrentWalkState (WalkList);
WalkState = DsGetCurrentWalkState (WalkList);
}
/* Abort the walk on any exception */
@ -486,9 +531,10 @@ PsWalkParsedAml (
ACPI_GENERIC_OP *StartOp,
ACPI_GENERIC_OP *EndOp,
ACPI_OBJECT_INTERNAL *MthDesc,
NAME_TABLE_ENTRY *StartScope,
NAME_TABLE_ENTRY *StartScope,
ACPI_OBJECT_INTERNAL **Params,
ACPI_OBJECT_INTERNAL **CallerReturnDesc,
ACPI_OWNER_ID OwnerId,
INTERPRETER_CALLBACK DescendingCallback,
INTERPRETER_CALLBACK AscendingCallback)
{
@ -514,33 +560,41 @@ PsWalkParsedAml (
WalkList.WalkState = NULL;
WalkState = PsCreateWalkState (EndOp, MthDesc, &WalkList);
WalkState = DsCreateWalkState (EndOp, MthDesc, &WalkList);
if (!WalkState)
{
return_ACPI_STATUS (AE_NO_MEMORY);
}
/* TBD: move to createWalkSTate */
WalkState->OwnerId = OwnerId;
/* TBD:
* TEMP until we pass WalkState to the interpreter
*/
PrevWalkList = Gbl_CurrentWalkList;
Gbl_CurrentWalkList = &WalkList;
if (MthDesc)
{
/* Push start scope on scope stack and make it current */
if (StartScope)
{
/* Push start scope on scope stack and make it current */
Status = NsScopeStackPush (StartScope, ACPI_TYPE_Method, WalkState);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
Status = DsScopeStackPush (StartScope, ACPI_TYPE_Method, WalkState);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
/* Init arguments if this is a control method */
/* TBD: add walkstate as a param */
}
PsxMthStackInitArgs (Params, MTH_NUM_ARGS);
}
if (MthDesc)
{
/* Init arguments if this is a control method */
/* TBD: add walkstate as a param */
DsMethodDataInitArgs (Params, MTH_NUM_ARGS);
}
Op = StartOp;
Status = AE_OK;
@ -566,11 +620,15 @@ PsWalkParsedAml (
BREAKPOINT3;
WalkState = PsPopWalkState (&WalkList);
WalkState = DsPopWalkState (&WalkList);
ReturnDesc = WalkState->ReturnDesc; /* Extract return value before we delete WalkState */
DEBUG_PRINT (TRACE_PARSE, ("PsWalkParsedAml: ReturnValue=%p, State=%p\n", WalkState->ReturnDesc, WalkState));
/* Reset the current scope to the beginning of scope stack */
DsScopeStackClear (WalkState);
/* If we just returned from the execution of a control method, there's lots of cleanup to do */
if (WalkState->MethodDesc)
@ -582,30 +640,18 @@ PsWalkParsedAml (
Status = OsdSignalSemaphore (WalkState->MethodDesc->Method.Semaphore, 1);
}
/* Reset the current scope to the beginning of scope stack */
NsScopeStackClear (WalkState);
/* Delete all arguments and locals */
PsxMthStackDeleteArgs (WalkState);
/* Delete the parse tree if asked to */
if (Gbl_WhenToParseMethods & METHOD_DELETE_AT_COMPLETION)
{
PsDeleteParseTree (WalkState->MethodDesc->Method.ParserOp);
WalkState->MethodDesc->Method.ParserOp = NULL;
}
DsMethodDataDeleteAll (WalkState);
}
/* Delete this walk state and all linked control states */
PsDeleteWalkState (WalkState);
DsDeleteWalkState (WalkState);
/* Check if we have restarted a preempted walk */
WalkState = PsGetCurrentWalkState (&WalkList);
WalkState = DsGetCurrentWalkState (&WalkList);
if (WalkState &&
Status == AE_OK)
{
@ -616,7 +662,7 @@ PsWalkParsedAml (
* The object is deleted
*/
PsxRestartControlMethod (WalkState, ReturnDesc);
DsRestartControlMethod (WalkState, ReturnDesc);
/* Get the next Op to process */
@ -632,7 +678,7 @@ PsWalkParsedAml (
else if (ReturnDesc)
{
CmDeleteInternalObject (ReturnDesc); /* Caller doesn't want it, must delete it */
CmRemoveReference (ReturnDesc); /* Caller doesn't want it, must delete it */
}
}