aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2012-10-30 22:27:32 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-14 18:31:27 -0500
commitd8da9151bb7e2d18624fdd8dbb066419186f0ec1 (patch)
tree1b8a37c22a45593e6f6ca40e01bba1e38c2b82cc /drivers/acpi/acpica
parent2489ef01849d3d7f62f53b47c245017406f02d32 (diff)
ACPICA: AcpiExec: Improve algorithm for tracking memory leaks
Add some intelligence to the code that maintains the global list of allocated memory. The list is now ordered by allocated memory address, significantly improving performance. When running AcpiExec on the ASLTS test suite, speed improvements of 3X to 5X are seen, depending on the platform and/or the environment. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r--drivers/acpi/acpica/uttrack.c100
1 files changed, 71 insertions, 29 deletions
diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c
index 79f311c3d1c..a424a9e3fea 100644
--- a/drivers/acpi/acpica/uttrack.c
+++ b/drivers/acpi/acpica/uttrack.c
@@ -61,7 +61,9 @@
61ACPI_MODULE_NAME("uttrack") 61ACPI_MODULE_NAME("uttrack")
62 62
63/* Local prototypes */ 63/* Local prototypes */
64static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation); 64static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
65 acpi_debug_mem_block
66 *allocation);
65 67
66static acpi_status 68static acpi_status
67acpi_ut_track_allocation(struct acpi_debug_mem_block *address, 69acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
@@ -263,31 +265,61 @@ acpi_ut_free_and_track(void *allocation,
263 * 265 *
264 * PARAMETERS: allocation - Address of allocated memory 266 * PARAMETERS: allocation - Address of allocated memory
265 * 267 *
266 * RETURN: A list element if found; NULL otherwise. 268 * RETURN: Three cases:
269 * 1) List is empty, NULL is returned.
270 * 2) Element was found. Returns Allocation parameter.
271 * 3) Element was not found. Returns position where it should be
272 * inserted into the list.
267 * 273 *
268 * DESCRIPTION: Searches for an element in the global allocation tracking list. 274 * DESCRIPTION: Searches for an element in the global allocation tracking list.
275 * If the element is not found, returns the location within the
276 * list where the element should be inserted.
277 *
278 * Note: The list is ordered by larger-to-smaller addresses.
279 *
280 * This global list is used to detect memory leaks in ACPICA as
281 * well as other issues such as an attempt to release the same
282 * internal object more than once. Although expensive as far
283 * as cpu time, this list is much more helpful for finding these
284 * types of issues than using memory leak detectors outside of
285 * the ACPICA code.
269 * 286 *
270 ******************************************************************************/ 287 ******************************************************************************/
271 288
272static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation) 289static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
290 acpi_debug_mem_block
291 *allocation)
273{ 292{
274 struct acpi_debug_mem_block *element; 293 struct acpi_debug_mem_block *element;
275 294
276 ACPI_FUNCTION_ENTRY();
277
278 element = acpi_gbl_global_list->list_head; 295 element = acpi_gbl_global_list->list_head;
296 if (!element) {
297 return (NULL);
298 }
299
300 /*
301 * Search for the address.
302 *
303 * Note: List is ordered by larger-to-smaller addresses, on the
304 * assumption that a new allocation usually has a larger address
305 * than previous allocations.
306 */
307 while (element > allocation) {
279 308
280 /* Search for the address. */ 309 /* Check for end-of-list */
281 310
282 while (element) { 311 if (!element->next) {
283 if (element == allocation) {
284 return (element); 312 return (element);
285 } 313 }
286 314
287 element = element->next; 315 element = element->next;
288 } 316 }
289 317
290 return (NULL); 318 if (element == allocation) {
319 return (element);
320 }
321
322 return (element->previous);
291} 323}
292 324
293/******************************************************************************* 325/*******************************************************************************
@@ -301,7 +333,7 @@ static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation)
301 * module - Source file name of caller 333 * module - Source file name of caller
302 * line - Line number of caller 334 * line - Line number of caller
303 * 335 *
304 * RETURN: None. 336 * RETURN: Status
305 * 337 *
306 * DESCRIPTION: Inserts an element into the global allocation tracking list. 338 * DESCRIPTION: Inserts an element into the global allocation tracking list.
307 * 339 *
@@ -330,22 +362,18 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
330 } 362 }
331 363
332 /* 364 /*
333 * Search list for this address to make sure it is not already on the list. 365 * Search the global list for this address to make sure it is not
334 * This will catch several kinds of problems. 366 * already present. This will catch several kinds of problems.
335 */ 367 */
336 element = acpi_ut_find_allocation(allocation); 368 element = acpi_ut_find_allocation(allocation);
337 if (element) { 369 if (element == allocation) {
338 ACPI_ERROR((AE_INFO, 370 ACPI_ERROR((AE_INFO,
339 "UtTrackAllocation: Allocation already present in list! (%p)", 371 "UtTrackAllocation: Allocation (%p) already present in global list!",
340 allocation)); 372 allocation));
341
342 ACPI_ERROR((AE_INFO, "Element %p Address %p",
343 element, allocation));
344
345 goto unlock_and_exit; 373 goto unlock_and_exit;
346 } 374 }
347 375
348 /* Fill in the instance data. */ 376 /* Fill in the instance data */
349 377
350 allocation->size = (u32)size; 378 allocation->size = (u32)size;
351 allocation->alloc_type = alloc_type; 379 allocation->alloc_type = alloc_type;
@@ -355,17 +383,31 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
355 ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME); 383 ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME);
356 allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0; 384 allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0;
357 385
358 /* Insert at list head */ 386 if (!element) {
359 387
360 if (mem_list->list_head) { 388 /* Insert at list head */
361 ((struct acpi_debug_mem_block *)(mem_list->list_head))-> 389
362 previous = allocation; 390 if (mem_list->list_head) {
363 } 391 ((struct acpi_debug_mem_block *)(mem_list->list_head))->
392 previous = allocation;
393 }
394
395 allocation->next = mem_list->list_head;
396 allocation->previous = NULL;
364 397
365 allocation->next = mem_list->list_head; 398 mem_list->list_head = allocation;
366 allocation->previous = NULL; 399 } else {
400 /* Insert after element */
401
402 allocation->next = element->next;
403 allocation->previous = element;
404
405 if (element->next) {
406 (element->next)->previous = allocation;
407 }
367 408
368 mem_list->list_head = allocation; 409 element->next = allocation;
410 }
369 411
370 unlock_and_exit: 412 unlock_and_exit:
371 status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); 413 status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
@@ -381,7 +423,7 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
381 * module - Source file name of caller 423 * module - Source file name of caller
382 * line - Line number of caller 424 * line - Line number of caller
383 * 425 *
384 * RETURN: 426 * RETURN: Status
385 * 427 *
386 * DESCRIPTION: Deletes an element from the global allocation tracking list. 428 * DESCRIPTION: Deletes an element from the global allocation tracking list.
387 * 429 *
@@ -443,7 +485,7 @@ acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
443 * 485 *
444 * FUNCTION: acpi_ut_dump_allocation_info 486 * FUNCTION: acpi_ut_dump_allocation_info
445 * 487 *
446 * PARAMETERS: 488 * PARAMETERS: None
447 * 489 *
448 * RETURN: None 490 * RETURN: None
449 * 491 *