summaryrefslogtreecommitdiff
path: root/source/components/dispatcher
diff options
context:
space:
mode:
Diffstat (limited to 'source/components/dispatcher')
-rw-r--r--source/components/dispatcher/dsinit.c61
-rw-r--r--source/components/dispatcher/dsmethod.c139
-rw-r--r--source/components/dispatcher/dswload.c17
3 files changed, 205 insertions, 12 deletions
diff --git a/source/components/dispatcher/dsinit.c b/source/components/dispatcher/dsinit.c
index 47a42bc98f6b..3e7977d72c27 100644
--- a/source/components/dispatcher/dsinit.c
+++ b/source/components/dispatcher/dsinit.c
@@ -52,6 +52,7 @@
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME ("dsinit")
+
/* Local prototypes */
static ACPI_STATUS
@@ -91,8 +92,8 @@ AcpiDsInitOneObject (
{
ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context;
ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
- ACPI_OBJECT_TYPE Type;
ACPI_STATUS Status;
+ ACPI_OPERAND_OBJECT *ObjDesc;
ACPI_FUNCTION_ENTRY ();
@@ -111,9 +112,7 @@ AcpiDsInitOneObject (
/* And even then, we are only interested in a few object types */
- Type = AcpiNsGetType (ObjHandle);
-
- switch (Type)
+ switch (AcpiNsGetType (ObjHandle))
{
case ACPI_TYPE_REGION:
@@ -129,8 +128,45 @@ AcpiDsInitOneObject (
break;
case ACPI_TYPE_METHOD:
-
+ /*
+ * Auto-serialization support. We will examine each method that is
+ * NotSerialized to determine if it creates any Named objects. If
+ * it does, it will be marked serialized to prevent problems if
+ * the method is entered by two or more threads and an attempt is
+ * made to create the same named object twice -- which results in
+ * an AE_ALREADY_EXISTS exception and method abort.
+ */
Info->MethodCount++;
+ ObjDesc = AcpiNsGetAttachedObject (Node);
+ if (!ObjDesc)
+ {
+ break;
+ }
+
+ /* Ignore if already serialized */
+
+ if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED)
+ {
+ Info->SerialMethodCount++;
+ break;
+ }
+
+ if (AcpiGbl_AutoSerializeMethods)
+ {
+ /* Parse/scan method and serialize it if necessary */
+
+ AcpiDsAutoSerializeMethod (Node, ObjDesc);
+ if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED)
+ {
+ /* Method was just converted to Serialized */
+
+ Info->SerialMethodCount++;
+ Info->SerializedMethodCount++;
+ break;
+ }
+ }
+
+ Info->NonSerialMethodCount++;
break;
case ACPI_TYPE_DEVICE:
@@ -187,7 +223,6 @@ AcpiDsInitializeObjects (
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
"**** Starting initialization of namespace objects ****\n"));
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Parsing all Control Methods:"));
/* Set all init info to zero */
@@ -223,12 +258,14 @@ AcpiDsInitializeObjects (
}
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "\nTable [%4.4s](id %4.4X) - %u Objects with %u Devices %u Methods %u Regions\n",
- Table->Signature, OwnerId, Info.ObjectCount,
- Info.DeviceCount, Info.MethodCount, Info.OpRegionCount));
-
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "%u Methods, %u Regions\n", Info.MethodCount, Info.OpRegionCount));
+ "Table [%4.4s] (id %4.4X) - %4u Objects with %3u Devices, "
+ "%3u Regions, %3u Methods (%u/%u/%u Serial/Non/Cvt)\n",
+ Table->Signature, OwnerId, Info.ObjectCount, Info.DeviceCount,
+ Info.OpRegionCount, Info.MethodCount, Info.SerialMethodCount,
+ Info.NonSerialMethodCount, Info.SerializedMethodCount));
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "%u Methods, %u Regions\n",
+ Info.MethodCount, Info.OpRegionCount));
return_ACPI_STATUS (AE_OK);
}
diff --git a/source/components/dispatcher/dsmethod.c b/source/components/dispatcher/dsmethod.c
index 3fb2135fa887..5cefb4fbb627 100644
--- a/source/components/dispatcher/dsmethod.c
+++ b/source/components/dispatcher/dsmethod.c
@@ -49,6 +49,8 @@
#include "acinterp.h"
#include "acnamesp.h"
#include "acdisasm.h"
+#include "acparser.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_DISPATCHER
@@ -57,12 +59,149 @@
/* Local prototypes */
static ACPI_STATUS
+AcpiDsDetectNamedOpcodes (
+ ACPI_WALK_STATE *WalkState,
+ ACPI_PARSE_OBJECT **OutOp);
+
+static ACPI_STATUS
AcpiDsCreateMethodMutex (
ACPI_OPERAND_OBJECT *MethodDesc);
/*******************************************************************************
*
+ * FUNCTION: AcpiDsAutoSerializeMethod
+ *
+ * PARAMETERS: Node - Namespace Node of the method
+ * ObjDesc - Method object attached to node
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Parse a control method AML to scan for control methods that
+ * need serialization due to the creation of named objects.
+ *
+ * NOTE: It is a bit of overkill to mark all such methods serialized, since
+ * there is only a problem if the method actually blocks during execution.
+ * A blocking operation is, for example, a Sleep() operation, or any access
+ * to an operation region. However, it is probably not possible to easily
+ * detect whether a method will block or not, so we simply mark all suspicious
+ * methods as serialized.
+ *
+ * NOTE2: This code is essentially a generic routine for parsing a single
+ * control method.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiDsAutoSerializeMethod (
+ ACPI_NAMESPACE_NODE *Node,
+ ACPI_OPERAND_OBJECT *ObjDesc)
+{
+ ACPI_STATUS Status;
+ ACPI_PARSE_OBJECT *Op = NULL;
+ ACPI_WALK_STATE *WalkState;
+
+
+ ACPI_FUNCTION_TRACE_PTR (DsAutoSerializeMethod, Node);
+
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
+ "Method auto-serialization parse [%4.4s] %p\n",
+ AcpiUtGetNodeName (Node), Node));
+
+ /* Create/Init a root op for the method parse tree */
+
+ Op = AcpiPsAllocOp (AML_METHOD_OP);
+ if (!Op)
+ {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ AcpiPsSetName (Op, Node->Name.Integer);
+ Op->Common.Node = Node;
+
+ /* Create and initialize a new walk state */
+
+ WalkState = AcpiDsCreateWalkState (Node->OwnerId, NULL, NULL, NULL);
+ if (!WalkState)
+ {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ Status = AcpiDsInitAmlWalk (WalkState, Op, Node, ObjDesc->Method.AmlStart,
+ ObjDesc->Method.AmlLength, NULL, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ AcpiDsDeleteWalkState (WalkState);
+ return_ACPI_STATUS (Status);
+ }
+
+ WalkState->DescendingCallback = AcpiDsDetectNamedOpcodes;
+
+ /* Parse the method, scan for creation of named objects */
+
+ Status = AcpiPsParseAml (WalkState);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ AcpiPsDeleteParseTree (Op);
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDsDetectNamedOpcodes
+ *
+ * PARAMETERS: WalkState - Current state of the parse tree walk
+ * OutOp - Unused, required for parser interface
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Descending callback used during the loading of ACPI tables.
+ * Currently used to detect methods that must be marked serialized
+ * in order to avoid problems with the creation of named objects.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiDsDetectNamedOpcodes (
+ ACPI_WALK_STATE *WalkState,
+ ACPI_PARSE_OBJECT **OutOp)
+{
+
+ ACPI_FUNCTION_NAME (AcpiDsDetectNamedOpcodes);
+
+
+ /* We are only interested in opcodes that create a new name */
+
+ if (!(WalkState->OpInfo->Flags & (AML_NAMED | AML_CREATE | AML_FIELD)))
+ {
+ return (AE_OK);
+ }
+
+ /*
+ * At this point, we know we have a Named object opcode.
+ * Mark the method as serialized. Later code will create a mutex for
+ * this method to enforce serialization.
+ */
+ WalkState->MethodDesc->Method.InfoFlags |= ACPI_METHOD_SERIALIZED;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+ "Method serialized [%4.4s] %p - [%s] (%4.4X)\n",
+ WalkState->MethodNode->Name.Ascii, WalkState->MethodNode,
+ WalkState->OpInfo->Name, WalkState->Opcode));
+
+ /* Abort the parse, no need to examine this method any further */
+
+ return (AE_CTRL_TERMINATE);
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: AcpiDsMethodError
*
* PARAMETERS: Status - Execution status
diff --git a/source/components/dispatcher/dswload.c b/source/components/dispatcher/dswload.c
index d9bb12d5367c..0cafecd65c69 100644
--- a/source/components/dispatcher/dswload.c
+++ b/source/components/dispatcher/dswload.c
@@ -80,8 +80,21 @@ AcpiDsInitCallbacks (
switch (PassNumber)
{
+ case 0:
+
+ /* Parse only - caller will setup callbacks */
+
+ WalkState->ParseFlags = ACPI_PARSE_LOAD_PASS1 |
+ ACPI_PARSE_DELETE_TREE |
+ ACPI_PARSE_DISASSEMBLE;
+ WalkState->DescendingCallback = NULL;
+ WalkState->AscendingCallback = NULL;
+ break;
+
case 1:
+ /* Load pass 1 */
+
WalkState->ParseFlags = ACPI_PARSE_LOAD_PASS1 |
ACPI_PARSE_DELETE_TREE;
WalkState->DescendingCallback = AcpiDsLoad1BeginOp;
@@ -90,6 +103,8 @@ AcpiDsInitCallbacks (
case 2:
+ /* Load pass 2 */
+
WalkState->ParseFlags = ACPI_PARSE_LOAD_PASS1 |
ACPI_PARSE_DELETE_TREE;
WalkState->DescendingCallback = AcpiDsLoad2BeginOp;
@@ -98,6 +113,8 @@ AcpiDsInitCallbacks (
case 3:
+ /* Execution pass */
+
#ifndef ACPI_NO_METHOD_EXECUTION
WalkState->ParseFlags |= ACPI_PARSE_EXECUTE |
ACPI_PARSE_DELETE_TREE;