summaryrefslogtreecommitdiff
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-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 79f311c3d1c4..a424a9e3fea4 100644
--- a/drivers/acpi/acpica/uttrack.c
+++ b/drivers/acpi/acpica/uttrack.c
@@ -61,7 +61,9 @@
ACPI_MODULE_NAME("uttrack")
/* Local prototypes */
-static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation);
+static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
+ acpi_debug_mem_block
+ *allocation);
static acpi_status
acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
@@ -263,31 +265,61 @@ acpi_ut_free_and_track(void *allocation,
*
* PARAMETERS: allocation - Address of allocated memory
*
- * RETURN: A list element if found; NULL otherwise.
+ * RETURN: Three cases:
+ * 1) List is empty, NULL is returned.
+ * 2) Element was found. Returns Allocation parameter.
+ * 3) Element was not found. Returns position where it should be
+ * inserted into the list.
*
* DESCRIPTION: Searches for an element in the global allocation tracking list.
+ * If the element is not found, returns the location within the
+ * list where the element should be inserted.
+ *
+ * Note: The list is ordered by larger-to-smaller addresses.
+ *
+ * This global list is used to detect memory leaks in ACPICA as
+ * well as other issues such as an attempt to release the same
+ * internal object more than once. Although expensive as far
+ * as cpu time, this list is much more helpful for finding these
+ * types of issues than using memory leak detectors outside of
+ * the ACPICA code.
*
******************************************************************************/
-static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation)
+static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
+ acpi_debug_mem_block
+ *allocation)
{
struct acpi_debug_mem_block *element;
- ACPI_FUNCTION_ENTRY();
-
element = acpi_gbl_global_list->list_head;
+ if (!element) {
+ return (NULL);
+ }
+
+ /*
+ * Search for the address.
+ *
+ * Note: List is ordered by larger-to-smaller addresses, on the
+ * assumption that a new allocation usually has a larger address
+ * than previous allocations.
+ */
+ while (element > allocation) {
- /* Search for the address. */
+ /* Check for end-of-list */
- while (element) {
- if (element == allocation) {
+ if (!element->next) {
return (element);
}
element = element->next;
}
- return (NULL);
+ if (element == allocation) {
+ return (element);
+ }
+
+ return (element->previous);
}
/*******************************************************************************
@@ -301,7 +333,7 @@ static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation)
* module - Source file name of caller
* line - Line number of caller
*
- * RETURN: None.
+ * RETURN: Status
*
* DESCRIPTION: Inserts an element into the global allocation tracking list.
*
@@ -330,22 +362,18 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
}
/*
- * Search list for this address to make sure it is not already on the list.
- * This will catch several kinds of problems.
+ * Search the global list for this address to make sure it is not
+ * already present. This will catch several kinds of problems.
*/
element = acpi_ut_find_allocation(allocation);
- if (element) {
+ if (element == allocation) {
ACPI_ERROR((AE_INFO,
- "UtTrackAllocation: Allocation already present in list! (%p)",
+ "UtTrackAllocation: Allocation (%p) already present in global list!",
allocation));
-
- ACPI_ERROR((AE_INFO, "Element %p Address %p",
- element, allocation));
-
goto unlock_and_exit;
}
- /* Fill in the instance data. */
+ /* Fill in the instance data */
allocation->size = (u32)size;
allocation->alloc_type = alloc_type;
@@ -355,17 +383,31 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME);
allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0;
- /* Insert at list head */
+ if (!element) {
- if (mem_list->list_head) {
- ((struct acpi_debug_mem_block *)(mem_list->list_head))->
- previous = allocation;
- }
+ /* Insert at list head */
+
+ if (mem_list->list_head) {
+ ((struct acpi_debug_mem_block *)(mem_list->list_head))->
+ previous = allocation;
+ }
+
+ allocation->next = mem_list->list_head;
+ allocation->previous = NULL;
- allocation->next = mem_list->list_head;
- allocation->previous = NULL;
+ mem_list->list_head = allocation;
+ } else {
+ /* Insert after element */
+
+ allocation->next = element->next;
+ allocation->previous = element;
+
+ if (element->next) {
+ (element->next)->previous = allocation;
+ }
- mem_list->list_head = allocation;
+ element->next = allocation;
+ }
unlock_and_exit:
status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
@@ -381,7 +423,7 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
* module - Source file name of caller
* line - Line number of caller
*
- * RETURN:
+ * RETURN: Status
*
* DESCRIPTION: Deletes an element from the global allocation tracking list.
*
@@ -443,7 +485,7 @@ acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
*
* FUNCTION: acpi_ut_dump_allocation_info
*
- * PARAMETERS:
+ * PARAMETERS: None
*
* RETURN: None
*