Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 19499
b: refs/heads/master
c: 28f55eb
h: refs/heads/master
i:
  19497: 7826ea5
  19495: d37fda5
v: v3
  • Loading branch information
Bob Moore authored and Len Brown committed Dec 10, 2005
1 parent f68c84e commit 6044d10
Show file tree
Hide file tree
Showing 9 changed files with 351 additions and 227 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c51a4de85de720670f2fbc592a6f8040af72ad87
refs/heads/master: 28f55ebce5bd2fceec8adc7c8860953d3e4532a8
337 changes: 179 additions & 158 deletions trunk/drivers/acpi/dispatcher/dsmethod.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,133 +51,6 @@
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsmethod")

/*******************************************************************************
*
* FUNCTION: acpi_ds_parse_method
*
* PARAMETERS: Node - Method node
*
* RETURN: Status
*
* DESCRIPTION: Parse the AML that is associated with the method.
*
* MUTEX: Assumes parser is locked
*
******************************************************************************/
acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
{
acpi_status status;
union acpi_operand_object *obj_desc;
union acpi_parse_object *op;
struct acpi_walk_state *walk_state;

ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);

/* Parameter Validation */

if (!node) {
return_ACPI_STATUS(AE_NULL_ENTRY);
}

ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
"**** Parsing [%4.4s] **** named_obj=%p\n",
acpi_ut_get_node_name(node), node));

/* Extract the method object from the method Node */

obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return_ACPI_STATUS(AE_NULL_OBJECT);
}

/* Create a mutex for the method if there is a concurrency limit */

if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
(!obj_desc->method.semaphore)) {
status = acpi_os_create_semaphore(obj_desc->method.concurrency,
obj_desc->method.concurrency,
&obj_desc->method.semaphore);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}

/*
* Allocate a new parser op to be the root of the parsed
* method tree
*/
op = acpi_ps_alloc_op(AML_METHOD_OP);
if (!op) {
return_ACPI_STATUS(AE_NO_MEMORY);
}

/* Init new op with the method name and pointer back to the Node */

acpi_ps_set_name(op, node->name.integer);
op->common.node = node;

/*
* Get a new owner_id for objects created by this method. Namespace
* objects (such as Operation Regions) can be created during the
* first pass parse.
*/
status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
if (ACPI_FAILURE(status)) {
goto cleanup;
}

/* Create and initialize a new walk state */

walk_state =
acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL,
NULL);
if (!walk_state) {
status = AE_NO_MEMORY;
goto cleanup2;
}

status = acpi_ds_init_aml_walk(walk_state, op, node,
obj_desc->method.aml_start,
obj_desc->method.aml_length, NULL, 1);
if (ACPI_FAILURE(status)) {
acpi_ds_delete_walk_state(walk_state);
goto cleanup2;
}

/*
* Parse the method, first pass
*
* The first pass load is 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 = acpi_ps_parse_aml(walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup2;
}

ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
"**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
acpi_ut_get_node_name(node), node, op));

/*
* Delete the parse tree. We simply re-parse the method for every
* execution since there isn't much overhead (compared to keeping lots
* of parse trees around)
*/
acpi_ns_delete_namespace_subtree(node);
acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);

cleanup2:
acpi_ut_release_owner_id(&obj_desc->method.owner_id);

cleanup:
acpi_ps_delete_parse_tree(op);
return_ACPI_STATUS(status);
}

/*******************************************************************************
*
* FUNCTION: acpi_ds_begin_method_execution
Expand All @@ -193,7 +66,6 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
* for clearance to execute.
*
******************************************************************************/

acpi_status
acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
union acpi_operand_object *obj_desc,
Expand Down Expand Up @@ -545,16 +417,54 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
}
}

/*
* There are no more threads executing this method. Perform
* additional cleanup.
*
* The method Node is stored in the walk state
*/
method_node = walk_state->method_node;

/* Lock namespace for possible update */

status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto exit;
}

/*
* Delete any namespace entries created immediately underneath
* the method
*/
if (method_node->child) {
acpi_ns_delete_namespace_subtree(method_node);
}

/*
* Delete any namespace entries created anywhere else within
* the namespace by the execution of this method
*/
acpi_ns_delete_namespace_by_owner(walk_state->method_desc->method.
owner_id);
status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);

/* Are there any other threads currently executing this method? */

if (walk_state->method_desc->method.thread_count) {
/*
* Additional threads. Do not release the owner_id in this case,
* we immediately reuse it for the next thread executing this method
*/
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"*** Not deleting method namespace, there are still %d threads\n",
"*** Completed execution of one thread, %d threads remaining\n",
walk_state->method_desc->method.
thread_count));
} else { /* This is the last executing thread */
} else {
/* This is the only executing thread for this method */

/*
* Support to dynamically change a method from not_serialized to
* Serialized if it appears that the method is written foolishly and
* Serialized if it appears that the method is incorrectly written and
* does not support multiple thread execution. The best example of this
* is if such a method creates namespace objects and blocks. A second
* thread will fail with an AE_ALREADY_EXISTS exception
Expand All @@ -570,34 +480,8 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
semaphore);
}

/*
* There are no more threads executing this method. Perform
* additional cleanup.
*
* The method Node is stored in the walk state
*/
method_node = walk_state->method_node;

/*
* Delete any namespace entries created immediately underneath
* the method
*/
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto exit;
}

if (method_node->child) {
acpi_ns_delete_namespace_subtree(method_node);
}
/* No more threads, we can free the owner_id */

/*
* Delete any namespace entries created anywhere else within
* the namespace
*/
acpi_ns_delete_namespace_by_owner(walk_state->method_desc->
method.owner_id);
status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_ut_release_owner_id(&walk_state->method_desc->method.
owner_id);
}
Expand All @@ -606,3 +490,140 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
(void)acpi_ut_release_mutex(ACPI_MTX_PARSER);
return_VOID;
}

#ifdef ACPI_INIT_PARSE_METHODS
/*
* Note 11/2005: Removed this code to parse all methods during table
* load because it causes problems if there are any errors during the
* parse. Also, it seems like overkill and we probably don't want to
* abort a table load because of an issue with a single method.
*/

/*******************************************************************************
*
* FUNCTION: acpi_ds_parse_method
*
* PARAMETERS: Node - Method node
*
* RETURN: Status
*
* DESCRIPTION: Parse the AML that is associated with the method.
*
* MUTEX: Assumes parser is locked
*
******************************************************************************/

acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
{
acpi_status status;
union acpi_operand_object *obj_desc;
union acpi_parse_object *op;
struct acpi_walk_state *walk_state;

ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);

/* Parameter Validation */

if (!node) {
return_ACPI_STATUS(AE_NULL_ENTRY);
}

ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
"**** Parsing [%4.4s] **** named_obj=%p\n",
acpi_ut_get_node_name(node), node));

/* Extract the method object from the method Node */

obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return_ACPI_STATUS(AE_NULL_OBJECT);
}

/* Create a mutex for the method if there is a concurrency limit */

if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
(!obj_desc->method.semaphore)) {
status = acpi_os_create_semaphore(obj_desc->method.concurrency,
obj_desc->method.concurrency,
&obj_desc->method.semaphore);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}

/*
* Allocate a new parser op to be the root of the parsed
* method tree
*/
op = acpi_ps_alloc_op(AML_METHOD_OP);
if (!op) {
return_ACPI_STATUS(AE_NO_MEMORY);
}

/* Init new op with the method name and pointer back to the Node */

acpi_ps_set_name(op, node->name.integer);
op->common.node = node;

/*
* Get a new owner_id for objects created by this method. Namespace
* objects (such as Operation Regions) can be created during the
* first pass parse.
*/
status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
if (ACPI_FAILURE(status)) {
goto cleanup;
}

/* Create and initialize a new walk state */

walk_state =
acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL,
NULL);
if (!walk_state) {
status = AE_NO_MEMORY;
goto cleanup2;
}

status = acpi_ds_init_aml_walk(walk_state, op, node,
obj_desc->method.aml_start,
obj_desc->method.aml_length, NULL, 1);
if (ACPI_FAILURE(status)) {
acpi_ds_delete_walk_state(walk_state);
goto cleanup2;
}

/*
* Parse the method, first pass
*
* The first pass load is 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 = acpi_ps_parse_aml(walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup2;
}

ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
"**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
acpi_ut_get_node_name(node), node, op));

/*
* Delete the parse tree. We simply re-parse the method for every
* execution since there isn't much overhead (compared to keeping lots
* of parse trees around)
*/
acpi_ns_delete_namespace_subtree(node);
acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);

cleanup2:
acpi_ut_release_owner_id(&obj_desc->method.owner_id);

cleanup:
acpi_ps_delete_parse_tree(op);
return_ACPI_STATUS(status);
}
#endif
Loading

0 comments on commit 6044d10

Please sign in to comment.