195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
26d33b6beSLv Zheng /******************************************************************************
36d33b6beSLv Zheng *
46d33b6beSLv Zheng * Module Name: uttrack - Memory allocation tracking routines (debug only)
56d33b6beSLv Zheng *
6*612c2932SBob Moore * Copyright (C) 2000 - 2023, Intel Corp.
76d33b6beSLv Zheng *
895857638SErik Schmauss *****************************************************************************/
96d33b6beSLv Zheng
106d33b6beSLv Zheng /*
116d33b6beSLv Zheng * These procedures are used for tracking memory leaks in the subsystem, and
126d33b6beSLv Zheng * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
136d33b6beSLv Zheng *
146d33b6beSLv Zheng * Each memory allocation is tracked via a doubly linked list. Each
156d33b6beSLv Zheng * element contains the caller's component, module name, function name, and
166d33b6beSLv Zheng * line number. acpi_ut_allocate and acpi_ut_allocate_zeroed call
176d33b6beSLv Zheng * acpi_ut_track_allocation to add an element to the list; deletion
186d33b6beSLv Zheng * occurs in the body of acpi_ut_free.
196d33b6beSLv Zheng */
206d33b6beSLv Zheng
216d33b6beSLv Zheng #include <acpi/acpi.h>
226d33b6beSLv Zheng #include "accommon.h"
236d33b6beSLv Zheng
246d33b6beSLv Zheng #ifdef ACPI_DBG_TRACK_ALLOCATIONS
256d33b6beSLv Zheng
266d33b6beSLv Zheng #define _COMPONENT ACPI_UTILITIES
276d33b6beSLv Zheng ACPI_MODULE_NAME("uttrack")
286d33b6beSLv Zheng
296d33b6beSLv Zheng /* Local prototypes */
30d8da9151SBob Moore static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
31d8da9151SBob Moore acpi_debug_mem_block
32d8da9151SBob Moore *allocation);
336d33b6beSLv Zheng
346d33b6beSLv Zheng static acpi_status
356d33b6beSLv Zheng acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
366d33b6beSLv Zheng acpi_size size,
376d33b6beSLv Zheng u8 alloc_type,
386d33b6beSLv Zheng u32 component, const char *module, u32 line);
396d33b6beSLv Zheng
406d33b6beSLv Zheng static acpi_status
416d33b6beSLv Zheng acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
426d33b6beSLv Zheng u32 component, const char *module, u32 line);
436d33b6beSLv Zheng
446d33b6beSLv Zheng /*******************************************************************************
456d33b6beSLv Zheng *
466d33b6beSLv Zheng * FUNCTION: acpi_ut_create_list
476d33b6beSLv Zheng *
486d33b6beSLv Zheng * PARAMETERS: cache_name - Ascii name for the cache
496d33b6beSLv Zheng * object_size - Size of each cached object
506d33b6beSLv Zheng * return_cache - Where the new cache object is returned
516d33b6beSLv Zheng *
526d33b6beSLv Zheng * RETURN: Status
536d33b6beSLv Zheng *
546d33b6beSLv Zheng * DESCRIPTION: Create a local memory list for tracking purposed
556d33b6beSLv Zheng *
566d33b6beSLv Zheng ******************************************************************************/
576d33b6beSLv Zheng
586d33b6beSLv Zheng acpi_status
acpi_ut_create_list(const char * list_name,u16 object_size,struct acpi_memory_list ** return_cache)590dfaaa3dSBob Moore acpi_ut_create_list(const char *list_name,
606d33b6beSLv Zheng u16 object_size, struct acpi_memory_list **return_cache)
616d33b6beSLv Zheng {
626d33b6beSLv Zheng struct acpi_memory_list *cache;
636d33b6beSLv Zheng
649556ec4eSBob Moore cache = acpi_os_allocate_zeroed(sizeof(struct acpi_memory_list));
656d33b6beSLv Zheng if (!cache) {
666d33b6beSLv Zheng return (AE_NO_MEMORY);
676d33b6beSLv Zheng }
686d33b6beSLv Zheng
696d33b6beSLv Zheng cache->list_name = list_name;
706d33b6beSLv Zheng cache->object_size = object_size;
716d33b6beSLv Zheng
726d33b6beSLv Zheng *return_cache = cache;
736d33b6beSLv Zheng return (AE_OK);
746d33b6beSLv Zheng }
756d33b6beSLv Zheng
766d33b6beSLv Zheng /*******************************************************************************
776d33b6beSLv Zheng *
786d33b6beSLv Zheng * FUNCTION: acpi_ut_allocate_and_track
796d33b6beSLv Zheng *
806d33b6beSLv Zheng * PARAMETERS: size - Size of the allocation
816d33b6beSLv Zheng * component - Component type of caller
826d33b6beSLv Zheng * module - Source file name of caller
836d33b6beSLv Zheng * line - Line number of caller
846d33b6beSLv Zheng *
856d33b6beSLv Zheng * RETURN: Address of the allocated memory on success, NULL on failure.
866d33b6beSLv Zheng *
876d33b6beSLv Zheng * DESCRIPTION: The subsystem's equivalent of malloc.
886d33b6beSLv Zheng *
896d33b6beSLv Zheng ******************************************************************************/
906d33b6beSLv Zheng
acpi_ut_allocate_and_track(acpi_size size,u32 component,const char * module,u32 line)916d33b6beSLv Zheng void *acpi_ut_allocate_and_track(acpi_size size,
926d33b6beSLv Zheng u32 component, const char *module, u32 line)
936d33b6beSLv Zheng {
946d33b6beSLv Zheng struct acpi_debug_mem_block *allocation;
956d33b6beSLv Zheng acpi_status status;
966d33b6beSLv Zheng
97b3c86c30SLv Zheng /* Check for an inadvertent size of zero bytes */
98b3c86c30SLv Zheng
99b3c86c30SLv Zheng if (!size) {
100b3c86c30SLv Zheng ACPI_WARNING((module, line,
101b3c86c30SLv Zheng "Attempt to allocate zero bytes, allocating 1 byte"));
102b3c86c30SLv Zheng size = 1;
103b3c86c30SLv Zheng }
104b3c86c30SLv Zheng
1056d33b6beSLv Zheng allocation =
106b3c86c30SLv Zheng acpi_os_allocate(size + sizeof(struct acpi_debug_mem_header));
1076d33b6beSLv Zheng if (!allocation) {
108b3c86c30SLv Zheng
109b3c86c30SLv Zheng /* Report allocation error */
110b3c86c30SLv Zheng
111b3c86c30SLv Zheng ACPI_WARNING((module, line,
112b3c86c30SLv Zheng "Could not allocate size %u", (u32)size));
113b3c86c30SLv Zheng
1146d33b6beSLv Zheng return (NULL);
1156d33b6beSLv Zheng }
1166d33b6beSLv Zheng
1171fad8738SBob Moore status =
1181fad8738SBob Moore acpi_ut_track_allocation(allocation, size, ACPI_MEM_MALLOC,
1191fad8738SBob Moore component, module, line);
1206d33b6beSLv Zheng if (ACPI_FAILURE(status)) {
1216d33b6beSLv Zheng acpi_os_free(allocation);
1226d33b6beSLv Zheng return (NULL);
1236d33b6beSLv Zheng }
1246d33b6beSLv Zheng
1256d33b6beSLv Zheng acpi_gbl_global_list->total_allocated++;
1266d33b6beSLv Zheng acpi_gbl_global_list->total_size += (u32)size;
1276d33b6beSLv Zheng acpi_gbl_global_list->current_total_size += (u32)size;
1281fad8738SBob Moore
1296d33b6beSLv Zheng if (acpi_gbl_global_list->current_total_size >
1306d33b6beSLv Zheng acpi_gbl_global_list->max_occupied) {
1316d33b6beSLv Zheng acpi_gbl_global_list->max_occupied =
1326d33b6beSLv Zheng acpi_gbl_global_list->current_total_size;
1336d33b6beSLv Zheng }
1346d33b6beSLv Zheng
1356d33b6beSLv Zheng return ((void *)&allocation->user_space);
1366d33b6beSLv Zheng }
1376d33b6beSLv Zheng
1386d33b6beSLv Zheng /*******************************************************************************
1396d33b6beSLv Zheng *
1406d33b6beSLv Zheng * FUNCTION: acpi_ut_allocate_zeroed_and_track
1416d33b6beSLv Zheng *
1426d33b6beSLv Zheng * PARAMETERS: size - Size of the allocation
1436d33b6beSLv Zheng * component - Component type of caller
1446d33b6beSLv Zheng * module - Source file name of caller
1456d33b6beSLv Zheng * line - Line number of caller
1466d33b6beSLv Zheng *
1476d33b6beSLv Zheng * RETURN: Address of the allocated memory on success, NULL on failure.
1486d33b6beSLv Zheng *
1496d33b6beSLv Zheng * DESCRIPTION: Subsystem equivalent of calloc.
1506d33b6beSLv Zheng *
1516d33b6beSLv Zheng ******************************************************************************/
1526d33b6beSLv Zheng
acpi_ut_allocate_zeroed_and_track(acpi_size size,u32 component,const char * module,u32 line)1536d33b6beSLv Zheng void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
1546d33b6beSLv Zheng u32 component,
1556d33b6beSLv Zheng const char *module, u32 line)
1566d33b6beSLv Zheng {
1576d33b6beSLv Zheng struct acpi_debug_mem_block *allocation;
1586d33b6beSLv Zheng acpi_status status;
1596d33b6beSLv Zheng
160b3c86c30SLv Zheng /* Check for an inadvertent size of zero bytes */
161b3c86c30SLv Zheng
162b3c86c30SLv Zheng if (!size) {
163b3c86c30SLv Zheng ACPI_WARNING((module, line,
164b3c86c30SLv Zheng "Attempt to allocate zero bytes, allocating 1 byte"));
165b3c86c30SLv Zheng size = 1;
166b3c86c30SLv Zheng }
167b3c86c30SLv Zheng
1686d33b6beSLv Zheng allocation =
169b3c86c30SLv Zheng acpi_os_allocate_zeroed(size +
170b3c86c30SLv Zheng sizeof(struct acpi_debug_mem_header));
1716d33b6beSLv Zheng if (!allocation) {
1726d33b6beSLv Zheng
1736d33b6beSLv Zheng /* Report allocation error */
1746d33b6beSLv Zheng
1756d33b6beSLv Zheng ACPI_ERROR((module, line,
1766d33b6beSLv Zheng "Could not allocate size %u", (u32)size));
1776d33b6beSLv Zheng return (NULL);
1786d33b6beSLv Zheng }
1796d33b6beSLv Zheng
1806d33b6beSLv Zheng status = acpi_ut_track_allocation(allocation, size,
1816d33b6beSLv Zheng ACPI_MEM_CALLOC, component, module,
1826d33b6beSLv Zheng line);
1836d33b6beSLv Zheng if (ACPI_FAILURE(status)) {
1846d33b6beSLv Zheng acpi_os_free(allocation);
1856d33b6beSLv Zheng return (NULL);
1866d33b6beSLv Zheng }
1876d33b6beSLv Zheng
1886d33b6beSLv Zheng acpi_gbl_global_list->total_allocated++;
1896d33b6beSLv Zheng acpi_gbl_global_list->total_size += (u32)size;
1906d33b6beSLv Zheng acpi_gbl_global_list->current_total_size += (u32)size;
1911fad8738SBob Moore
1926d33b6beSLv Zheng if (acpi_gbl_global_list->current_total_size >
1936d33b6beSLv Zheng acpi_gbl_global_list->max_occupied) {
1946d33b6beSLv Zheng acpi_gbl_global_list->max_occupied =
1956d33b6beSLv Zheng acpi_gbl_global_list->current_total_size;
1966d33b6beSLv Zheng }
1976d33b6beSLv Zheng
1986d33b6beSLv Zheng return ((void *)&allocation->user_space);
1996d33b6beSLv Zheng }
2006d33b6beSLv Zheng
2016d33b6beSLv Zheng /*******************************************************************************
2026d33b6beSLv Zheng *
2036d33b6beSLv Zheng * FUNCTION: acpi_ut_free_and_track
2046d33b6beSLv Zheng *
2056d33b6beSLv Zheng * PARAMETERS: allocation - Address of the memory to deallocate
2066d33b6beSLv Zheng * component - Component type of caller
2076d33b6beSLv Zheng * module - Source file name of caller
2086d33b6beSLv Zheng * line - Line number of caller
2096d33b6beSLv Zheng *
2106d33b6beSLv Zheng * RETURN: None
2116d33b6beSLv Zheng *
2126d33b6beSLv Zheng * DESCRIPTION: Frees the memory at Allocation
2136d33b6beSLv Zheng *
2146d33b6beSLv Zheng ******************************************************************************/
2156d33b6beSLv Zheng
2166d33b6beSLv Zheng void
acpi_ut_free_and_track(void * allocation,u32 component,const char * module,u32 line)2176d33b6beSLv Zheng acpi_ut_free_and_track(void *allocation,
2186d33b6beSLv Zheng u32 component, const char *module, u32 line)
2196d33b6beSLv Zheng {
2206d33b6beSLv Zheng struct acpi_debug_mem_block *debug_block;
2216d33b6beSLv Zheng acpi_status status;
2226d33b6beSLv Zheng
2236d33b6beSLv Zheng ACPI_FUNCTION_TRACE_PTR(ut_free, allocation);
2246d33b6beSLv Zheng
2256d33b6beSLv Zheng if (NULL == allocation) {
2266d33b6beSLv Zheng ACPI_ERROR((module, line, "Attempt to delete a NULL address"));
2276d33b6beSLv Zheng
2286d33b6beSLv Zheng return_VOID;
2296d33b6beSLv Zheng }
2306d33b6beSLv Zheng
2316d33b6beSLv Zheng debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block,
2326d33b6beSLv Zheng (((char *)allocation) -
2336d33b6beSLv Zheng sizeof(struct acpi_debug_mem_header)));
2346d33b6beSLv Zheng
2356d33b6beSLv Zheng acpi_gbl_global_list->total_freed++;
2366d33b6beSLv Zheng acpi_gbl_global_list->current_total_size -= debug_block->size;
2376d33b6beSLv Zheng
2381fad8738SBob Moore status =
2391fad8738SBob Moore acpi_ut_remove_allocation(debug_block, component, module, line);
2406d33b6beSLv Zheng if (ACPI_FAILURE(status)) {
2416d33b6beSLv Zheng ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
2426d33b6beSLv Zheng }
2436d33b6beSLv Zheng
2446d33b6beSLv Zheng acpi_os_free(debug_block);
245d72c17a8SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n",
246d72c17a8SBob Moore allocation, debug_block));
2476d33b6beSLv Zheng return_VOID;
2486d33b6beSLv Zheng }
2496d33b6beSLv Zheng
2506d33b6beSLv Zheng /*******************************************************************************
2516d33b6beSLv Zheng *
2526d33b6beSLv Zheng * FUNCTION: acpi_ut_find_allocation
2536d33b6beSLv Zheng *
2546d33b6beSLv Zheng * PARAMETERS: allocation - Address of allocated memory
2556d33b6beSLv Zheng *
256d8da9151SBob Moore * RETURN: Three cases:
257d8da9151SBob Moore * 1) List is empty, NULL is returned.
258d8da9151SBob Moore * 2) Element was found. Returns Allocation parameter.
259d8da9151SBob Moore * 3) Element was not found. Returns position where it should be
260d8da9151SBob Moore * inserted into the list.
2616d33b6beSLv Zheng *
2626d33b6beSLv Zheng * DESCRIPTION: Searches for an element in the global allocation tracking list.
263d8da9151SBob Moore * If the element is not found, returns the location within the
264d8da9151SBob Moore * list where the element should be inserted.
265d8da9151SBob Moore *
266d8da9151SBob Moore * Note: The list is ordered by larger-to-smaller addresses.
267d8da9151SBob Moore *
268d8da9151SBob Moore * This global list is used to detect memory leaks in ACPICA as
269d8da9151SBob Moore * well as other issues such as an attempt to release the same
270d8da9151SBob Moore * internal object more than once. Although expensive as far
271d8da9151SBob Moore * as cpu time, this list is much more helpful for finding these
272d8da9151SBob Moore * types of issues than using memory leak detectors outside of
273d8da9151SBob Moore * the ACPICA code.
2746d33b6beSLv Zheng *
2756d33b6beSLv Zheng ******************************************************************************/
2766d33b6beSLv Zheng
acpi_ut_find_allocation(struct acpi_debug_mem_block * allocation)277d8da9151SBob Moore static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
278d8da9151SBob Moore acpi_debug_mem_block
279d8da9151SBob Moore *allocation)
2806d33b6beSLv Zheng {
2816d33b6beSLv Zheng struct acpi_debug_mem_block *element;
2826d33b6beSLv Zheng
2836d33b6beSLv Zheng element = acpi_gbl_global_list->list_head;
284d8da9151SBob Moore if (!element) {
285d8da9151SBob Moore return (NULL);
286d8da9151SBob Moore }
2876d33b6beSLv Zheng
288d8da9151SBob Moore /*
289d8da9151SBob Moore * Search for the address.
290d8da9151SBob Moore *
291d8da9151SBob Moore * Note: List is ordered by larger-to-smaller addresses, on the
292d8da9151SBob Moore * assumption that a new allocation usually has a larger address
293d8da9151SBob Moore * than previous allocations.
294d8da9151SBob Moore */
295d8da9151SBob Moore while (element > allocation) {
2966d33b6beSLv Zheng
297d8da9151SBob Moore /* Check for end-of-list */
298d8da9151SBob Moore
299d8da9151SBob Moore if (!element->next) {
3006d33b6beSLv Zheng return (element);
3016d33b6beSLv Zheng }
3026d33b6beSLv Zheng
3036d33b6beSLv Zheng element = element->next;
3046d33b6beSLv Zheng }
3056d33b6beSLv Zheng
306d8da9151SBob Moore if (element == allocation) {
307d8da9151SBob Moore return (element);
308d8da9151SBob Moore }
309d8da9151SBob Moore
310d8da9151SBob Moore return (element->previous);
3116d33b6beSLv Zheng }
3126d33b6beSLv Zheng
3136d33b6beSLv Zheng /*******************************************************************************
3146d33b6beSLv Zheng *
3156d33b6beSLv Zheng * FUNCTION: acpi_ut_track_allocation
3166d33b6beSLv Zheng *
3176d33b6beSLv Zheng * PARAMETERS: allocation - Address of allocated memory
3186d33b6beSLv Zheng * size - Size of the allocation
3196d33b6beSLv Zheng * alloc_type - MEM_MALLOC or MEM_CALLOC
3206d33b6beSLv Zheng * component - Component type of caller
3216d33b6beSLv Zheng * module - Source file name of caller
3226d33b6beSLv Zheng * line - Line number of caller
3236d33b6beSLv Zheng *
324d8da9151SBob Moore * RETURN: Status
3256d33b6beSLv Zheng *
3266d33b6beSLv Zheng * DESCRIPTION: Inserts an element into the global allocation tracking list.
3276d33b6beSLv Zheng *
3286d33b6beSLv Zheng ******************************************************************************/
3296d33b6beSLv Zheng
3306d33b6beSLv Zheng static acpi_status
acpi_ut_track_allocation(struct acpi_debug_mem_block * allocation,acpi_size size,u8 alloc_type,u32 component,const char * module,u32 line)3316d33b6beSLv Zheng acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
3326d33b6beSLv Zheng acpi_size size,
3336d33b6beSLv Zheng u8 alloc_type,
3346d33b6beSLv Zheng u32 component, const char *module, u32 line)
3356d33b6beSLv Zheng {
3366d33b6beSLv Zheng struct acpi_memory_list *mem_list;
3376d33b6beSLv Zheng struct acpi_debug_mem_block *element;
3386d33b6beSLv Zheng acpi_status status = AE_OK;
3396d33b6beSLv Zheng
3406d33b6beSLv Zheng ACPI_FUNCTION_TRACE_PTR(ut_track_allocation, allocation);
3416d33b6beSLv Zheng
3426d33b6beSLv Zheng if (acpi_gbl_disable_mem_tracking) {
3436d33b6beSLv Zheng return_ACPI_STATUS(AE_OK);
3446d33b6beSLv Zheng }
3456d33b6beSLv Zheng
3466d33b6beSLv Zheng mem_list = acpi_gbl_global_list;
3476d33b6beSLv Zheng status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
3486d33b6beSLv Zheng if (ACPI_FAILURE(status)) {
3496d33b6beSLv Zheng return_ACPI_STATUS(status);
3506d33b6beSLv Zheng }
3516d33b6beSLv Zheng
3526d33b6beSLv Zheng /*
353d8da9151SBob Moore * Search the global list for this address to make sure it is not
354d8da9151SBob Moore * already present. This will catch several kinds of problems.
3556d33b6beSLv Zheng */
3566d33b6beSLv Zheng element = acpi_ut_find_allocation(allocation);
357d8da9151SBob Moore if (element == allocation) {
3586d33b6beSLv Zheng ACPI_ERROR((AE_INFO,
359d8da9151SBob Moore "UtTrackAllocation: Allocation (%p) already present in global list!",
3606d33b6beSLv Zheng allocation));
3616d33b6beSLv Zheng goto unlock_and_exit;
3626d33b6beSLv Zheng }
3636d33b6beSLv Zheng
364d8da9151SBob Moore /* Fill in the instance data */
3656d33b6beSLv Zheng
3666d33b6beSLv Zheng allocation->size = (u32)size;
3676d33b6beSLv Zheng allocation->alloc_type = alloc_type;
3686d33b6beSLv Zheng allocation->component = component;
3696d33b6beSLv Zheng allocation->line = line;
3706d33b6beSLv Zheng
371ee68d477SBob Moore acpi_ut_safe_strncpy(allocation->module, (char *)module,
372ee68d477SBob Moore ACPI_MAX_MODULE_NAME);
3736d33b6beSLv Zheng
374d8da9151SBob Moore if (!element) {
375d8da9151SBob Moore
3766d33b6beSLv Zheng /* Insert at list head */
3776d33b6beSLv Zheng
3786d33b6beSLv Zheng if (mem_list->list_head) {
3796d33b6beSLv Zheng ((struct acpi_debug_mem_block *)(mem_list->list_head))->
3806d33b6beSLv Zheng previous = allocation;
3816d33b6beSLv Zheng }
3826d33b6beSLv Zheng
3836d33b6beSLv Zheng allocation->next = mem_list->list_head;
3846d33b6beSLv Zheng allocation->previous = NULL;
3856d33b6beSLv Zheng
3866d33b6beSLv Zheng mem_list->list_head = allocation;
387d8da9151SBob Moore } else {
388d8da9151SBob Moore /* Insert after element */
389d8da9151SBob Moore
390d8da9151SBob Moore allocation->next = element->next;
391d8da9151SBob Moore allocation->previous = element;
392d8da9151SBob Moore
393d8da9151SBob Moore if (element->next) {
394d8da9151SBob Moore (element->next)->previous = allocation;
395d8da9151SBob Moore }
396d8da9151SBob Moore
397d8da9151SBob Moore element->next = allocation;
398d8da9151SBob Moore }
3996d33b6beSLv Zheng
4006d33b6beSLv Zheng unlock_and_exit:
4016d33b6beSLv Zheng status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
4026d33b6beSLv Zheng return_ACPI_STATUS(status);
4036d33b6beSLv Zheng }
4046d33b6beSLv Zheng
4056d33b6beSLv Zheng /*******************************************************************************
4066d33b6beSLv Zheng *
4076d33b6beSLv Zheng * FUNCTION: acpi_ut_remove_allocation
4086d33b6beSLv Zheng *
4096d33b6beSLv Zheng * PARAMETERS: allocation - Address of allocated memory
4106d33b6beSLv Zheng * component - Component type of caller
4116d33b6beSLv Zheng * module - Source file name of caller
4126d33b6beSLv Zheng * line - Line number of caller
4136d33b6beSLv Zheng *
414d8da9151SBob Moore * RETURN: Status
4156d33b6beSLv Zheng *
4166d33b6beSLv Zheng * DESCRIPTION: Deletes an element from the global allocation tracking list.
4176d33b6beSLv Zheng *
4186d33b6beSLv Zheng ******************************************************************************/
4196d33b6beSLv Zheng
4206d33b6beSLv Zheng static acpi_status
acpi_ut_remove_allocation(struct acpi_debug_mem_block * allocation,u32 component,const char * module,u32 line)4216d33b6beSLv Zheng acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
4226d33b6beSLv Zheng u32 component, const char *module, u32 line)
4236d33b6beSLv Zheng {
4246d33b6beSLv Zheng struct acpi_memory_list *mem_list;
4256d33b6beSLv Zheng acpi_status status;
4266d33b6beSLv Zheng
4270e770b32SBob Moore ACPI_FUNCTION_NAME(ut_remove_allocation);
4286d33b6beSLv Zheng
4296d33b6beSLv Zheng if (acpi_gbl_disable_mem_tracking) {
4300e770b32SBob Moore return (AE_OK);
4316d33b6beSLv Zheng }
4326d33b6beSLv Zheng
4336d33b6beSLv Zheng mem_list = acpi_gbl_global_list;
4346d33b6beSLv Zheng if (NULL == mem_list->list_head) {
4356d33b6beSLv Zheng
4366d33b6beSLv Zheng /* No allocations! */
4376d33b6beSLv Zheng
4386d33b6beSLv Zheng ACPI_ERROR((module, line,
4396d33b6beSLv Zheng "Empty allocation list, nothing to free!"));
4406d33b6beSLv Zheng
4410e770b32SBob Moore return (AE_OK);
4426d33b6beSLv Zheng }
4436d33b6beSLv Zheng
4446d33b6beSLv Zheng status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
4456d33b6beSLv Zheng if (ACPI_FAILURE(status)) {
4460e770b32SBob Moore return (status);
4476d33b6beSLv Zheng }
4486d33b6beSLv Zheng
4496d33b6beSLv Zheng /* Unlink */
4506d33b6beSLv Zheng
4516d33b6beSLv Zheng if (allocation->previous) {
4526d33b6beSLv Zheng (allocation->previous)->next = allocation->next;
4536d33b6beSLv Zheng } else {
4546d33b6beSLv Zheng mem_list->list_head = allocation->next;
4556d33b6beSLv Zheng }
4566d33b6beSLv Zheng
4576d33b6beSLv Zheng if (allocation->next) {
4586d33b6beSLv Zheng (allocation->next)->previous = allocation->previous;
4596d33b6beSLv Zheng }
4606d33b6beSLv Zheng
4610e770b32SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
4620e770b32SBob Moore &allocation->user_space, allocation->size));
4630e770b32SBob Moore
4646d33b6beSLv Zheng /* Mark the segment as deleted */
4656d33b6beSLv Zheng
4664fa4616eSBob Moore memset(&allocation->user_space, 0xEA, allocation->size);
4676d33b6beSLv Zheng
4686d33b6beSLv Zheng status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
4690e770b32SBob Moore return (status);
4706d33b6beSLv Zheng }
4716d33b6beSLv Zheng
4726d33b6beSLv Zheng /*******************************************************************************
4736d33b6beSLv Zheng *
4746d33b6beSLv Zheng * FUNCTION: acpi_ut_dump_allocation_info
4756d33b6beSLv Zheng *
476d8da9151SBob Moore * PARAMETERS: None
4776d33b6beSLv Zheng *
4786d33b6beSLv Zheng * RETURN: None
4796d33b6beSLv Zheng *
4806d33b6beSLv Zheng * DESCRIPTION: Print some info about the outstanding allocations.
4816d33b6beSLv Zheng *
4826d33b6beSLv Zheng ******************************************************************************/
4836d33b6beSLv Zheng
acpi_ut_dump_allocation_info(void)4846d33b6beSLv Zheng void acpi_ut_dump_allocation_info(void)
4856d33b6beSLv Zheng {
4866d33b6beSLv Zheng /*
4876d33b6beSLv Zheng struct acpi_memory_list *mem_list;
4886d33b6beSLv Zheng */
4896d33b6beSLv Zheng
4906d33b6beSLv Zheng ACPI_FUNCTION_TRACE(ut_dump_allocation_info);
4916d33b6beSLv Zheng
4926d33b6beSLv Zheng /*
4936d33b6beSLv Zheng ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
4946d33b6beSLv Zheng ("%30s: %4d (%3d Kb)\n", "Current allocations",
4956d33b6beSLv Zheng mem_list->current_count,
4966d33b6beSLv Zheng ROUND_UP_TO_1K (mem_list->current_size)));
4976d33b6beSLv Zheng
4986d33b6beSLv Zheng ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
4996d33b6beSLv Zheng ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
5006d33b6beSLv Zheng mem_list->max_concurrent_count,
5016d33b6beSLv Zheng ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
5026d33b6beSLv Zheng
5036d33b6beSLv Zheng ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
5046d33b6beSLv Zheng ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
5056d33b6beSLv Zheng running_object_count,
5066d33b6beSLv Zheng ROUND_UP_TO_1K (running_object_size)));
5076d33b6beSLv Zheng
5086d33b6beSLv Zheng ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
5096d33b6beSLv Zheng ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
5106d33b6beSLv Zheng running_alloc_count,
5116d33b6beSLv Zheng ROUND_UP_TO_1K (running_alloc_size)));
5126d33b6beSLv Zheng
5136d33b6beSLv Zheng ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
5146d33b6beSLv Zheng ("%30s: %4d (%3d Kb)\n", "Current Nodes",
5156d33b6beSLv Zheng acpi_gbl_current_node_count,
5166d33b6beSLv Zheng ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
5176d33b6beSLv Zheng
5186d33b6beSLv Zheng ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
5196d33b6beSLv Zheng ("%30s: %4d (%3d Kb)\n", "Max Nodes",
5206d33b6beSLv Zheng acpi_gbl_max_concurrent_node_count,
5216d33b6beSLv Zheng ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
5226d33b6beSLv Zheng sizeof (struct acpi_namespace_node)))));
5236d33b6beSLv Zheng */
5246d33b6beSLv Zheng return_VOID;
5256d33b6beSLv Zheng }
5266d33b6beSLv Zheng
5276d33b6beSLv Zheng /*******************************************************************************
5286d33b6beSLv Zheng *
5296d33b6beSLv Zheng * FUNCTION: acpi_ut_dump_allocations
5306d33b6beSLv Zheng *
5316d33b6beSLv Zheng * PARAMETERS: component - Component(s) to dump info for.
5326d33b6beSLv Zheng * module - Module to dump info for. NULL means all.
5336d33b6beSLv Zheng *
5346d33b6beSLv Zheng * RETURN: None
5356d33b6beSLv Zheng *
5366d33b6beSLv Zheng * DESCRIPTION: Print a list of all outstanding allocations.
5376d33b6beSLv Zheng *
5386d33b6beSLv Zheng ******************************************************************************/
5396d33b6beSLv Zheng
acpi_ut_dump_allocations(u32 component,const char * module)5406d33b6beSLv Zheng void acpi_ut_dump_allocations(u32 component, const char *module)
5416d33b6beSLv Zheng {
5426d33b6beSLv Zheng struct acpi_debug_mem_block *element;
5436d33b6beSLv Zheng union acpi_descriptor *descriptor;
5446d33b6beSLv Zheng u32 num_outstanding = 0;
5456d33b6beSLv Zheng u8 descriptor_type;
5466d33b6beSLv Zheng
5476d33b6beSLv Zheng ACPI_FUNCTION_TRACE(ut_dump_allocations);
5486d33b6beSLv Zheng
5496d33b6beSLv Zheng if (acpi_gbl_disable_mem_tracking) {
55068aafc35SBob Moore return_VOID;
5516d33b6beSLv Zheng }
5526d33b6beSLv Zheng
5536d33b6beSLv Zheng /*
5546d33b6beSLv Zheng * Walk the allocation list.
5556d33b6beSLv Zheng */
5566d33b6beSLv Zheng if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
55768aafc35SBob Moore return_VOID;
5586d33b6beSLv Zheng }
5596d33b6beSLv Zheng
560a62a7117SBob Moore if (!acpi_gbl_global_list) {
561a62a7117SBob Moore goto exit;
562a62a7117SBob Moore }
563a62a7117SBob Moore
5646d33b6beSLv Zheng element = acpi_gbl_global_list->list_head;
5656d33b6beSLv Zheng while (element) {
5666d33b6beSLv Zheng if ((element->component & component) &&
5676d33b6beSLv Zheng ((module == NULL)
5684fa4616eSBob Moore || (0 == strcmp(module, element->module)))) {
5696d33b6beSLv Zheng descriptor =
5706d33b6beSLv Zheng ACPI_CAST_PTR(union acpi_descriptor,
5716d33b6beSLv Zheng &element->user_space);
5726d33b6beSLv Zheng
5736d33b6beSLv Zheng if (element->size <
5746d33b6beSLv Zheng sizeof(struct acpi_common_descriptor)) {
575a62a7117SBob Moore acpi_os_printf("%p Length 0x%04X %9.9s-%4.4u "
5766d33b6beSLv Zheng "[Not a Descriptor - too small]\n",
5776d33b6beSLv Zheng descriptor, element->size,
5786d33b6beSLv Zheng element->module, element->line);
5796d33b6beSLv Zheng } else {
5806d33b6beSLv Zheng /* Ignore allocated objects that are in a cache */
5816d33b6beSLv Zheng
5826d33b6beSLv Zheng if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) !=
5836d33b6beSLv Zheng ACPI_DESC_TYPE_CACHED) {
5846d33b6beSLv Zheng acpi_os_printf
585a62a7117SBob Moore ("%p Length 0x%04X %9.9s-%4.4u [%s] ",
5866d33b6beSLv Zheng descriptor, element->size,
5876d33b6beSLv Zheng element->module, element->line,
5886d33b6beSLv Zheng acpi_ut_get_descriptor_name
5896d33b6beSLv Zheng (descriptor));
5906d33b6beSLv Zheng
591894b5cc5SBob Moore /* Optional object hex dump */
592894b5cc5SBob Moore
593894b5cc5SBob Moore if (acpi_gbl_verbose_leak_dump) {
594894b5cc5SBob Moore acpi_os_printf("\n");
595894b5cc5SBob Moore acpi_ut_dump_buffer((u8 *)
596894b5cc5SBob Moore descriptor,
597894b5cc5SBob Moore element->
598894b5cc5SBob Moore size,
599894b5cc5SBob Moore DB_BYTE_DISPLAY,
600894b5cc5SBob Moore 0);
601894b5cc5SBob Moore }
602894b5cc5SBob Moore
6036d33b6beSLv Zheng /* Validate the descriptor type using Type field and length */
6046d33b6beSLv Zheng
6056d33b6beSLv Zheng descriptor_type = 0; /* Not a valid descriptor type */
6066d33b6beSLv Zheng
6076d33b6beSLv Zheng switch (ACPI_GET_DESCRIPTOR_TYPE
6086d33b6beSLv Zheng (descriptor)) {
6096d33b6beSLv Zheng case ACPI_DESC_TYPE_OPERAND:
6101d1ea1b7SChao Guan
6116d33b6beSLv Zheng if (element->size ==
6126d33b6beSLv Zheng sizeof(union
6136d33b6beSLv Zheng acpi_operand_object))
6146d33b6beSLv Zheng {
6156d33b6beSLv Zheng descriptor_type =
6166d33b6beSLv Zheng ACPI_DESC_TYPE_OPERAND;
6176d33b6beSLv Zheng }
6186d33b6beSLv Zheng break;
6196d33b6beSLv Zheng
6206d33b6beSLv Zheng case ACPI_DESC_TYPE_PARSER:
6211d1ea1b7SChao Guan
6226d33b6beSLv Zheng if (element->size ==
6236d33b6beSLv Zheng sizeof(union
6246d33b6beSLv Zheng acpi_parse_object)) {
6256d33b6beSLv Zheng descriptor_type =
6266d33b6beSLv Zheng ACPI_DESC_TYPE_PARSER;
6276d33b6beSLv Zheng }
6286d33b6beSLv Zheng break;
6296d33b6beSLv Zheng
6306d33b6beSLv Zheng case ACPI_DESC_TYPE_NAMED:
6311d1ea1b7SChao Guan
6326d33b6beSLv Zheng if (element->size ==
6336d33b6beSLv Zheng sizeof(struct
6346d33b6beSLv Zheng acpi_namespace_node))
6356d33b6beSLv Zheng {
6366d33b6beSLv Zheng descriptor_type =
6376d33b6beSLv Zheng ACPI_DESC_TYPE_NAMED;
6386d33b6beSLv Zheng }
6396d33b6beSLv Zheng break;
6406d33b6beSLv Zheng
6416d33b6beSLv Zheng default:
6421d1ea1b7SChao Guan
6436d33b6beSLv Zheng break;
6446d33b6beSLv Zheng }
6456d33b6beSLv Zheng
6466d33b6beSLv Zheng /* Display additional info for the major descriptor types */
6476d33b6beSLv Zheng
6486d33b6beSLv Zheng switch (descriptor_type) {
6496d33b6beSLv Zheng case ACPI_DESC_TYPE_OPERAND:
6501d1ea1b7SChao Guan
6516d33b6beSLv Zheng acpi_os_printf
6526d33b6beSLv Zheng ("%12.12s RefCount 0x%04X\n",
6536d33b6beSLv Zheng acpi_ut_get_type_name
6546d33b6beSLv Zheng (descriptor->object.common.
6556d33b6beSLv Zheng type),
6566d33b6beSLv Zheng descriptor->object.common.
6576d33b6beSLv Zheng reference_count);
6586d33b6beSLv Zheng break;
6596d33b6beSLv Zheng
6606d33b6beSLv Zheng case ACPI_DESC_TYPE_PARSER:
6611d1ea1b7SChao Guan
6626d33b6beSLv Zheng acpi_os_printf
663edc5935eSBob Moore ("AmlOpcode 0x%04X\n",
6646d33b6beSLv Zheng descriptor->op.asl.
6656d33b6beSLv Zheng aml_opcode);
6666d33b6beSLv Zheng break;
6676d33b6beSLv Zheng
6686d33b6beSLv Zheng case ACPI_DESC_TYPE_NAMED:
6691d1ea1b7SChao Guan
6706d33b6beSLv Zheng acpi_os_printf("%4.4s\n",
6716d33b6beSLv Zheng acpi_ut_get_node_name
6726d33b6beSLv Zheng (&descriptor->
6736d33b6beSLv Zheng node));
6746d33b6beSLv Zheng break;
6756d33b6beSLv Zheng
6766d33b6beSLv Zheng default:
6771d1ea1b7SChao Guan
6786d33b6beSLv Zheng acpi_os_printf("\n");
6796d33b6beSLv Zheng break;
6806d33b6beSLv Zheng }
6816d33b6beSLv Zheng }
6826d33b6beSLv Zheng }
6836d33b6beSLv Zheng
6846d33b6beSLv Zheng num_outstanding++;
6856d33b6beSLv Zheng }
6866d33b6beSLv Zheng
6876d33b6beSLv Zheng element = element->next;
6886d33b6beSLv Zheng }
6896d33b6beSLv Zheng
690a62a7117SBob Moore exit:
6916d33b6beSLv Zheng (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
6926d33b6beSLv Zheng
6936d33b6beSLv Zheng /* Print summary */
6946d33b6beSLv Zheng
6956d33b6beSLv Zheng if (!num_outstanding) {
69605fb04b5SBob Moore ACPI_INFO(("No outstanding allocations"));
6976d33b6beSLv Zheng } else {
698b12ebe59SErik Schmauss ACPI_ERROR((AE_INFO, "%u (0x%X) Outstanding cache allocations",
6996d33b6beSLv Zheng num_outstanding, num_outstanding));
7006d33b6beSLv Zheng }
7016d33b6beSLv Zheng
7026d33b6beSLv Zheng return_VOID;
7036d33b6beSLv Zheng }
7046d33b6beSLv Zheng
7056d33b6beSLv Zheng #endif /* ACPI_DBG_TRACK_ALLOCATIONS */
706