Skip to content

Commit

Permalink
ACPICA: Performance enhancement for namespace search and access
Browse files Browse the repository at this point in the history
This change enhances the performance of namespace searches and
walks by adding a backpointer to the parent in each namespace
node. On large namespaces, this change can improve overall ACPI
performance by up to 9X.  Adding a pointer to each namespace node
increases the overall size of the internal namespace by about 5%,
since each namespace entry usually consists of both a namespace
node and an ACPI operand object.

Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
Alexey Starikovskiy authored and Len Brown committed Jul 7, 2010
1 parent 5821f75 commit c45b5c0
Show file tree
Hide file tree
Showing 15 changed files with 52 additions and 218 deletions.
5 changes: 3 additions & 2 deletions drivers/acpi/acpica/aclocal.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,9 @@ struct acpi_namespace_node {
u8 flags; /* Miscellaneous flags */
acpi_owner_id owner_id; /* Node creator */
union acpi_name_union name; /* ACPI Name, always 4 chars per ACPI spec */
struct acpi_namespace_node *parent; /* Parent node */
struct acpi_namespace_node *child; /* First child */
struct acpi_namespace_node *peer; /* Peer. Parent if ANOBJ_END_OF_PEER_LIST set */
struct acpi_namespace_node *peer; /* First peer */

/*
* The following fields are used by the ASL compiler and disassembler only
Expand All @@ -199,7 +200,7 @@ struct acpi_namespace_node {

/* Namespace Node flags */

#define ANOBJ_END_OF_PEER_LIST 0x01 /* End-of-list, Peer field points to parent */
#define ANOBJ_RESERVED 0x01 /* Available for use */
#define ANOBJ_TEMPORARY 0x02 /* Node is create by a method and is temporary */
#define ANOBJ_METHOD_ARG 0x04 /* Node is a method argument */
#define ANOBJ_METHOD_LOCAL 0x08 /* Node is a method local */
Expand Down
7 changes: 0 additions & 7 deletions drivers/acpi/acpica/acnamesp.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,11 +369,4 @@ struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle);

void acpi_ns_terminate(void);

struct acpi_namespace_node *acpi_ns_get_parent_node(struct acpi_namespace_node
*node);

struct acpi_namespace_node *acpi_ns_get_next_valid_node(struct
acpi_namespace_node
*node);

#endif /* __ACNAMESP_H__ */
6 changes: 2 additions & 4 deletions drivers/acpi/acpica/dsmthdat.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
walk_state->arguments[i].name.integer |= (i << 24);
walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED;
walk_state->arguments[i].type = ACPI_TYPE_ANY;
walk_state->arguments[i].flags =
ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG;
walk_state->arguments[i].flags = ANOBJ_METHOD_ARG;
}

/* Init the method locals */
Expand All @@ -116,8 +115,7 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
walk_state->local_variables[i].descriptor_type =
ACPI_DESC_TYPE_NAMED;
walk_state->local_variables[i].type = ACPI_TYPE_ANY;
walk_state->local_variables[i].flags =
ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL;
walk_state->local_variables[i].flags = ANOBJ_METHOD_LOCAL;
}

return_VOID;
Expand Down
6 changes: 3 additions & 3 deletions drivers/acpi/acpica/dsopcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)

/* Execute the AML code for the term_arg arguments */

status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
status = acpi_ds_execute_arguments(node, node->parent,
extra_desc->extra.aml_length,
extra_desc->extra.aml_start);
return_ACPI_STATUS(status);
Expand Down Expand Up @@ -257,7 +257,7 @@ acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)

/* Execute the AML code for the term_arg arguments */

status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
status = acpi_ds_execute_arguments(node, node->parent,
extra_desc->extra.aml_length,
extra_desc->extra.aml_start);
return_ACPI_STATUS(status);
Expand Down Expand Up @@ -394,7 +394,7 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)

/* Execute the argument AML */

status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
status = acpi_ds_execute_arguments(node, node->parent,
extra_desc->extra.aml_length,
extra_desc->extra.aml_start);
if (ACPI_FAILURE(status)) {
Expand Down
10 changes: 5 additions & 5 deletions drivers/acpi/acpica/evrgnini.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
return_ACPI_STATUS(status);
}

parent_node = acpi_ns_get_parent_node(region_obj->region.node);
parent_node = region_obj->region.node->parent;

/*
* Get the _SEG and _BBN values from the device upon which the handler
Expand Down Expand Up @@ -248,7 +248,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
break;
}

pci_root_node = acpi_ns_get_parent_node(pci_root_node);
pci_root_node = pci_root_node->parent;
}

/* PCI root bridge not found, use namespace root node */
Expand Down Expand Up @@ -280,7 +280,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
*/
pci_device_node = region_obj->region.node;
while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) {
pci_device_node = acpi_ns_get_parent_node(pci_device_node);
pci_device_node = pci_device_node->parent;
}

if (!pci_device_node) {
Expand Down Expand Up @@ -521,7 +521,7 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
return_ACPI_STATUS(AE_NOT_EXIST);
}

node = acpi_ns_get_parent_node(region_obj->region.node);
node = region_obj->region.node->parent;
space_id = region_obj->region.space_id;

/* Setup defaults */
Expand Down Expand Up @@ -654,7 +654,7 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,

/* This node does not have the handler we need; Pop up one level */

node = acpi_ns_get_parent_node(node);
node = node->parent;
}

/* If we get here, there is no handler for this region */
Expand Down
2 changes: 1 addition & 1 deletion drivers/acpi/acpica/exdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags)
acpi_ex_out_string("Type", acpi_ut_get_type_name(node->type));
acpi_ex_out_pointer("Attached Object",
acpi_ns_get_attached_object(node));
acpi_ex_out_pointer("Parent", acpi_ns_get_parent_node(node));
acpi_ex_out_pointer("Parent", node->parent);

acpi_ex_dump_object(ACPI_CAST_PTR(union acpi_operand_object, node),
acpi_ex_dump_node);
Expand Down
5 changes: 2 additions & 3 deletions drivers/acpi/acpica/nsaccess.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
*/
while (!acpi_ns_opens_scope(prefix_node->type) &&
prefix_node->type != ACPI_TYPE_ANY) {
prefix_node =
acpi_ns_get_parent_node(prefix_node);
prefix_node = prefix_node->parent;
}
}
}
Expand Down Expand Up @@ -419,7 +418,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
/* Backup to the parent node */

num_carats++;
this_node = acpi_ns_get_parent_node(this_node);
this_node = this_node->parent;
if (!this_node) {

/* Current scope has no parent scope */
Expand Down
74 changes: 25 additions & 49 deletions drivers/acpi/acpica/nsalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ void acpi_ns_remove_node(struct acpi_namespace_node *node)

ACPI_FUNCTION_TRACE_PTR(ns_remove_node, node);

parent_node = acpi_ns_get_parent_node(node);
parent_node = node->parent;

prev_node = NULL;
next_node = parent_node->child;
Expand All @@ -168,29 +168,20 @@ void acpi_ns_remove_node(struct acpi_namespace_node *node)

while (next_node != node) {
prev_node = next_node;
next_node = prev_node->peer;
next_node = next_node->peer;
}

if (prev_node) {

/* Node is not first child, unlink it */

prev_node->peer = next_node->peer;
if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
prev_node->flags |= ANOBJ_END_OF_PEER_LIST;
}
prev_node->peer = node->peer;
} else {
/* Node is first child (has no previous peer) */

if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {

/* No peers at all */

parent_node->child = NULL;
} else { /* Link peer list to parent */

parent_node->child = next_node->peer;
}
/*
* Node is first child (has no previous peer).
* Link peer list to parent
*/
parent_node->child = node->peer;
}

/* Delete the node and any attached objects */
Expand Down Expand Up @@ -238,23 +229,20 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp

/* Link the new entry into the parent and existing children */

node->peer = NULL;
node->parent = parent_node;
child_node = parent_node->child;

if (!child_node) {
parent_node->child = node;
node->flags |= ANOBJ_END_OF_PEER_LIST;
node->peer = parent_node;
} else {
while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) {
/* Add node to the end of the peer list */

while (child_node->peer) {
child_node = child_node->peer;
}

child_node->peer = node;

/* Clear end-of-list flag */

child_node->flags &= ~ANOBJ_END_OF_PEER_LIST;
node->flags |= ANOBJ_END_OF_PEER_LIST;
node->peer = parent_node;
}

/* Init the new entry */
Expand Down Expand Up @@ -288,47 +276,35 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp

void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
{
struct acpi_namespace_node *child_node;
struct acpi_namespace_node *next_node;
u8 flags;
struct acpi_namespace_node *node_to_delete;

ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node);

if (!parent_node) {
return_VOID;
}

/* If no children, all done! */

child_node = parent_node->child;
if (!child_node) {
return_VOID;
}

/* Deallocate all children at this level */

do {

/* Get the things we need */

next_node = child_node->peer;
flags = child_node->flags;
next_node = parent_node->child;
while (next_node) {

/* Grandchildren should have all been deleted already */

if (child_node->child) {
if (next_node->child) {
ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p",
parent_node, child_node));
parent_node, next_node));
}

/*
* Delete this child node and move on to the next child in the list.
* No need to unlink the node since we are deleting the entire branch.
*/
acpi_ns_delete_node(child_node);
child_node = next_node;

} while (!(flags & ANOBJ_END_OF_PEER_LIST));
node_to_delete = next_node;
next_node = next_node->peer;
acpi_ns_delete_node(node_to_delete);
};

/* Clear the parent's child pointer */

Expand Down Expand Up @@ -405,7 +381,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)

/* Move up the tree to the grandparent */

parent_node = acpi_ns_get_parent_node(parent_node);
parent_node = parent_node->parent;
}
}

Expand Down Expand Up @@ -510,7 +486,7 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)

/* Move up the tree to the grandparent */

parent_node = acpi_ns_get_parent_node(parent_node);
parent_node = parent_node->parent;
}
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/acpi/acpica/nsinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ acpi_ns_find_ini_methods(acpi_handle obj_handle,
* The only _INI methods that we care about are those that are
* present under Device, Processor, and Thermal objects.
*/
parent_node = acpi_ns_get_parent_node(node);
parent_node = node->parent;
switch (parent_node->type) {
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_PROCESSOR:
Expand All @@ -420,7 +420,7 @@ acpi_ns_find_ini_methods(acpi_handle obj_handle,

while (parent_node) {
parent_node->flags |= ANOBJ_SUBTREE_HAS_INI;
parent_node = acpi_ns_get_parent_node(parent_node);
parent_node = parent_node->parent;
}
break;

Expand Down
4 changes: 2 additions & 2 deletions drivers/acpi/acpica/nsnames.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node,
/* Put the name into the buffer */

ACPI_MOVE_32_TO_32((name_buffer + index), &parent_node->name);
parent_node = acpi_ns_get_parent_node(parent_node);
parent_node = parent_node->parent;

/* Prefix name with the path separator */

Expand Down Expand Up @@ -198,7 +198,7 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
return 0;
}
size += ACPI_PATH_SEGMENT_LENGTH;
next_node = acpi_ns_get_parent_node(next_node);
next_node = next_node->parent;
}

if (!size) {
Expand Down
15 changes: 2 additions & 13 deletions drivers/acpi/acpica/nssearch.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,17 +152,6 @@ acpi_ns_search_one_scope(u32 target_name,
return_ACPI_STATUS(AE_OK);
}

/*
* The last entry in the list points back to the parent,
* so a flag is used to indicate the end-of-list
*/
if (node->flags & ANOBJ_END_OF_PEER_LIST) {

/* Searched entire list, we are done */

break;
}

/* Didn't match name, move on to the next peer object */

node = node->peer;
Expand Down Expand Up @@ -217,7 +206,7 @@ acpi_ns_search_parent_tree(u32 target_name,

ACPI_FUNCTION_TRACE(ns_search_parent_tree);

parent_node = acpi_ns_get_parent_node(node);
parent_node = node->parent;

/*
* If there is no parent (i.e., we are at the root) or type is "local",
Expand Down Expand Up @@ -261,7 +250,7 @@ acpi_ns_search_parent_tree(u32 target_name,

/* Not found here, go up another level (until we reach the root) */

parent_node = acpi_ns_get_parent_node(parent_node);
parent_node = parent_node->parent;
}

/* Not found in parent tree */
Expand Down
Loading

0 comments on commit c45b5c0

Please sign in to comment.