diff options
author | Alexey Starikovskiy <astarikovskiy@suse.de> | 2010-05-25 23:53:07 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-07-06 22:33:56 -0400 |
commit | c45b5c097001480e66d4c523eb715ad317a4ef77 (patch) | |
tree | 5b9415840b97a724537273db99b2c66975c63347 /drivers/acpi/acpica/nsalloc.c | |
parent | 5821f75421aa7c7bafdec291223153597f649934 (diff) |
ACPICA: Performance enhancement for namespace search and access
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>
Diffstat (limited to 'drivers/acpi/acpica/nsalloc.c')
-rw-r--r-- | drivers/acpi/acpica/nsalloc.c | 74 |
1 files changed, 25 insertions, 49 deletions
diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index 982269c1fa48..8d3a43a061ab 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c | |||
@@ -159,7 +159,7 @@ void acpi_ns_remove_node(struct acpi_namespace_node *node) | |||
159 | 159 | ||
160 | ACPI_FUNCTION_TRACE_PTR(ns_remove_node, node); | 160 | ACPI_FUNCTION_TRACE_PTR(ns_remove_node, node); |
161 | 161 | ||
162 | parent_node = acpi_ns_get_parent_node(node); | 162 | parent_node = node->parent; |
163 | 163 | ||
164 | prev_node = NULL; | 164 | prev_node = NULL; |
165 | next_node = parent_node->child; | 165 | next_node = parent_node->child; |
@@ -168,29 +168,20 @@ void acpi_ns_remove_node(struct acpi_namespace_node *node) | |||
168 | 168 | ||
169 | while (next_node != node) { | 169 | while (next_node != node) { |
170 | prev_node = next_node; | 170 | prev_node = next_node; |
171 | next_node = prev_node->peer; | 171 | next_node = next_node->peer; |
172 | } | 172 | } |
173 | 173 | ||
174 | if (prev_node) { | 174 | if (prev_node) { |
175 | 175 | ||
176 | /* Node is not first child, unlink it */ | 176 | /* Node is not first child, unlink it */ |
177 | 177 | ||
178 | prev_node->peer = next_node->peer; | 178 | prev_node->peer = node->peer; |
179 | if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { | ||
180 | prev_node->flags |= ANOBJ_END_OF_PEER_LIST; | ||
181 | } | ||
182 | } else { | 179 | } else { |
183 | /* Node is first child (has no previous peer) */ | 180 | /* |
184 | 181 | * Node is first child (has no previous peer). | |
185 | if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { | 182 | * Link peer list to parent |
186 | 183 | */ | |
187 | /* No peers at all */ | 184 | parent_node->child = node->peer; |
188 | |||
189 | parent_node->child = NULL; | ||
190 | } else { /* Link peer list to parent */ | ||
191 | |||
192 | parent_node->child = next_node->peer; | ||
193 | } | ||
194 | } | 185 | } |
195 | 186 | ||
196 | /* Delete the node and any attached objects */ | 187 | /* Delete the node and any attached objects */ |
@@ -238,23 +229,20 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp | |||
238 | 229 | ||
239 | /* Link the new entry into the parent and existing children */ | 230 | /* Link the new entry into the parent and existing children */ |
240 | 231 | ||
232 | node->peer = NULL; | ||
233 | node->parent = parent_node; | ||
241 | child_node = parent_node->child; | 234 | child_node = parent_node->child; |
235 | |||
242 | if (!child_node) { | 236 | if (!child_node) { |
243 | parent_node->child = node; | 237 | parent_node->child = node; |
244 | node->flags |= ANOBJ_END_OF_PEER_LIST; | ||
245 | node->peer = parent_node; | ||
246 | } else { | 238 | } else { |
247 | while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) { | 239 | /* Add node to the end of the peer list */ |
240 | |||
241 | while (child_node->peer) { | ||
248 | child_node = child_node->peer; | 242 | child_node = child_node->peer; |
249 | } | 243 | } |
250 | 244 | ||
251 | child_node->peer = node; | 245 | child_node->peer = node; |
252 | |||
253 | /* Clear end-of-list flag */ | ||
254 | |||
255 | child_node->flags &= ~ANOBJ_END_OF_PEER_LIST; | ||
256 | node->flags |= ANOBJ_END_OF_PEER_LIST; | ||
257 | node->peer = parent_node; | ||
258 | } | 246 | } |
259 | 247 | ||
260 | /* Init the new entry */ | 248 | /* Init the new entry */ |
@@ -288,9 +276,8 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp | |||
288 | 276 | ||
289 | void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) | 277 | void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) |
290 | { | 278 | { |
291 | struct acpi_namespace_node *child_node; | ||
292 | struct acpi_namespace_node *next_node; | 279 | struct acpi_namespace_node *next_node; |
293 | u8 flags; | 280 | struct acpi_namespace_node *node_to_delete; |
294 | 281 | ||
295 | ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node); | 282 | ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node); |
296 | 283 | ||
@@ -298,37 +285,26 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) | |||
298 | return_VOID; | 285 | return_VOID; |
299 | } | 286 | } |
300 | 287 | ||
301 | /* If no children, all done! */ | ||
302 | |||
303 | child_node = parent_node->child; | ||
304 | if (!child_node) { | ||
305 | return_VOID; | ||
306 | } | ||
307 | |||
308 | /* Deallocate all children at this level */ | 288 | /* Deallocate all children at this level */ |
309 | 289 | ||
310 | do { | 290 | next_node = parent_node->child; |
311 | 291 | while (next_node) { | |
312 | /* Get the things we need */ | ||
313 | |||
314 | next_node = child_node->peer; | ||
315 | flags = child_node->flags; | ||
316 | 292 | ||
317 | /* Grandchildren should have all been deleted already */ | 293 | /* Grandchildren should have all been deleted already */ |
318 | 294 | ||
319 | if (child_node->child) { | 295 | if (next_node->child) { |
320 | ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p", | 296 | ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p", |
321 | parent_node, child_node)); | 297 | parent_node, next_node)); |
322 | } | 298 | } |
323 | 299 | ||
324 | /* | 300 | /* |
325 | * Delete this child node and move on to the next child in the list. | 301 | * Delete this child node and move on to the next child in the list. |
326 | * No need to unlink the node since we are deleting the entire branch. | 302 | * No need to unlink the node since we are deleting the entire branch. |
327 | */ | 303 | */ |
328 | acpi_ns_delete_node(child_node); | 304 | node_to_delete = next_node; |
329 | child_node = next_node; | 305 | next_node = next_node->peer; |
330 | 306 | acpi_ns_delete_node(node_to_delete); | |
331 | } while (!(flags & ANOBJ_END_OF_PEER_LIST)); | 307 | }; |
332 | 308 | ||
333 | /* Clear the parent's child pointer */ | 309 | /* Clear the parent's child pointer */ |
334 | 310 | ||
@@ -405,7 +381,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) | |||
405 | 381 | ||
406 | /* Move up the tree to the grandparent */ | 382 | /* Move up the tree to the grandparent */ |
407 | 383 | ||
408 | parent_node = acpi_ns_get_parent_node(parent_node); | 384 | parent_node = parent_node->parent; |
409 | } | 385 | } |
410 | } | 386 | } |
411 | 387 | ||
@@ -510,7 +486,7 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) | |||
510 | 486 | ||
511 | /* Move up the tree to the grandparent */ | 487 | /* Move up the tree to the grandparent */ |
512 | 488 | ||
513 | parent_node = acpi_ns_get_parent_node(parent_node); | 489 | parent_node = parent_node->parent; |
514 | } | 490 | } |
515 | } | 491 | } |
516 | 492 | ||