1149703c7Sjruoho /******************************************************************************
2149703c7Sjruoho *
3149703c7Sjruoho * Module Name: uttrack - Memory allocation tracking routines (debug only)
4149703c7Sjruoho *
5149703c7Sjruoho *****************************************************************************/
6149703c7Sjruoho
77af23240Sjruoho /*
8*ec12a2faSchristos * Copyright (C) 2000 - 2022, Intel Corp.
9149703c7Sjruoho * All rights reserved.
10149703c7Sjruoho *
117af23240Sjruoho * Redistribution and use in source and binary forms, with or without
127af23240Sjruoho * modification, are permitted provided that the following conditions
137af23240Sjruoho * are met:
147af23240Sjruoho * 1. Redistributions of source code must retain the above copyright
157af23240Sjruoho * notice, this list of conditions, and the following disclaimer,
167af23240Sjruoho * without modification.
177af23240Sjruoho * 2. Redistributions in binary form must reproduce at minimum a disclaimer
187af23240Sjruoho * substantially similar to the "NO WARRANTY" disclaimer below
197af23240Sjruoho * ("Disclaimer") and any redistribution must be conditioned upon
207af23240Sjruoho * including a substantially similar Disclaimer requirement for further
217af23240Sjruoho * binary redistribution.
227af23240Sjruoho * 3. Neither the names of the above-listed copyright holders nor the names
237af23240Sjruoho * of any contributors may be used to endorse or promote products derived
247af23240Sjruoho * from this software without specific prior written permission.
25149703c7Sjruoho *
267af23240Sjruoho * Alternatively, this software may be distributed under the terms of the
277af23240Sjruoho * GNU General Public License ("GPL") version 2 as published by the Free
287af23240Sjruoho * Software Foundation.
29149703c7Sjruoho *
307af23240Sjruoho * NO WARRANTY
317af23240Sjruoho * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
327af23240Sjruoho * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33adee7055Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
347af23240Sjruoho * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
357af23240Sjruoho * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
367af23240Sjruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
377af23240Sjruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
387af23240Sjruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
397af23240Sjruoho * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
407af23240Sjruoho * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
417af23240Sjruoho * POSSIBILITY OF SUCH DAMAGES.
427af23240Sjruoho */
43149703c7Sjruoho
44149703c7Sjruoho /*
45149703c7Sjruoho * These procedures are used for tracking memory leaks in the subsystem, and
46149703c7Sjruoho * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
47149703c7Sjruoho *
48149703c7Sjruoho * Each memory allocation is tracked via a doubly linked list. Each
49149703c7Sjruoho * element contains the caller's component, module name, function name, and
50149703c7Sjruoho * line number. AcpiUtAllocate and AcpiUtAllocateZeroed call
51149703c7Sjruoho * AcpiUtTrackAllocation to add an element to the list; deletion
52149703c7Sjruoho * occurs in the body of AcpiUtFree.
53149703c7Sjruoho */
54149703c7Sjruoho
55149703c7Sjruoho #include "acpi.h"
56149703c7Sjruoho #include "accommon.h"
57149703c7Sjruoho
58149703c7Sjruoho #ifdef ACPI_DBG_TRACK_ALLOCATIONS
59149703c7Sjruoho
60149703c7Sjruoho #define _COMPONENT ACPI_UTILITIES
61149703c7Sjruoho ACPI_MODULE_NAME ("uttrack")
62149703c7Sjruoho
6333841f6dSchristos
64149703c7Sjruoho /* Local prototypes */
65149703c7Sjruoho
66149703c7Sjruoho static ACPI_DEBUG_MEM_BLOCK *
67149703c7Sjruoho AcpiUtFindAllocation (
6833841f6dSchristos ACPI_DEBUG_MEM_BLOCK *Allocation);
69149703c7Sjruoho
70149703c7Sjruoho static ACPI_STATUS
71149703c7Sjruoho AcpiUtTrackAllocation (
72149703c7Sjruoho ACPI_DEBUG_MEM_BLOCK *Address,
73149703c7Sjruoho ACPI_SIZE Size,
74149703c7Sjruoho UINT8 AllocType,
75149703c7Sjruoho UINT32 Component,
76149703c7Sjruoho const char *Module,
77149703c7Sjruoho UINT32 Line);
78149703c7Sjruoho
79149703c7Sjruoho static ACPI_STATUS
80149703c7Sjruoho AcpiUtRemoveAllocation (
81149703c7Sjruoho ACPI_DEBUG_MEM_BLOCK *Address,
82149703c7Sjruoho UINT32 Component,
83149703c7Sjruoho const char *Module,
84149703c7Sjruoho UINT32 Line);
85149703c7Sjruoho
86149703c7Sjruoho
87149703c7Sjruoho /*******************************************************************************
88149703c7Sjruoho *
89149703c7Sjruoho * FUNCTION: AcpiUtCreateList
90149703c7Sjruoho *
91149703c7Sjruoho * PARAMETERS: CacheName - Ascii name for the cache
92149703c7Sjruoho * ObjectSize - Size of each cached object
93149703c7Sjruoho * ReturnCache - Where the new cache object is returned
94149703c7Sjruoho *
95149703c7Sjruoho * RETURN: Status
96149703c7Sjruoho *
97149703c7Sjruoho * DESCRIPTION: Create a local memory list for tracking purposed
98149703c7Sjruoho *
99149703c7Sjruoho ******************************************************************************/
100149703c7Sjruoho
101149703c7Sjruoho ACPI_STATUS
AcpiUtCreateList(const char * ListName,UINT16 ObjectSize,ACPI_MEMORY_LIST ** ReturnCache)102149703c7Sjruoho AcpiUtCreateList (
1035fa0b4b7Sjruoho const char *ListName,
104149703c7Sjruoho UINT16 ObjectSize,
105149703c7Sjruoho ACPI_MEMORY_LIST **ReturnCache)
106149703c7Sjruoho {
107149703c7Sjruoho ACPI_MEMORY_LIST *Cache;
108149703c7Sjruoho
109149703c7Sjruoho
110abb0e338Schristos Cache = AcpiOsAllocateZeroed (sizeof (ACPI_MEMORY_LIST));
111149703c7Sjruoho if (!Cache)
112149703c7Sjruoho {
113149703c7Sjruoho return (AE_NO_MEMORY);
114149703c7Sjruoho }
115149703c7Sjruoho
116abb0e338Schristos Cache->ListName = ListName;
117149703c7Sjruoho Cache->ObjectSize = ObjectSize;
118149703c7Sjruoho
119149703c7Sjruoho *ReturnCache = Cache;
120149703c7Sjruoho return (AE_OK);
121149703c7Sjruoho }
122149703c7Sjruoho
123149703c7Sjruoho
124149703c7Sjruoho /*******************************************************************************
125149703c7Sjruoho *
126149703c7Sjruoho * FUNCTION: AcpiUtAllocateAndTrack
127149703c7Sjruoho *
128149703c7Sjruoho * PARAMETERS: Size - Size of the allocation
129149703c7Sjruoho * Component - Component type of caller
130149703c7Sjruoho * Module - Source file name of caller
131149703c7Sjruoho * Line - Line number of caller
132149703c7Sjruoho *
133149703c7Sjruoho * RETURN: Address of the allocated memory on success, NULL on failure.
134149703c7Sjruoho *
135149703c7Sjruoho * DESCRIPTION: The subsystem's equivalent of malloc.
136149703c7Sjruoho *
137149703c7Sjruoho ******************************************************************************/
138149703c7Sjruoho
139149703c7Sjruoho void *
AcpiUtAllocateAndTrack(ACPI_SIZE Size,UINT32 Component,const char * Module,UINT32 Line)140149703c7Sjruoho AcpiUtAllocateAndTrack (
141149703c7Sjruoho ACPI_SIZE Size,
142149703c7Sjruoho UINT32 Component,
143149703c7Sjruoho const char *Module,
144149703c7Sjruoho UINT32 Line)
145149703c7Sjruoho {
146149703c7Sjruoho ACPI_DEBUG_MEM_BLOCK *Allocation;
147149703c7Sjruoho ACPI_STATUS Status;
148149703c7Sjruoho
149149703c7Sjruoho
15033841f6dSchristos /* Check for an inadvertent size of zero bytes */
15133841f6dSchristos
15233841f6dSchristos if (!Size)
15333841f6dSchristos {
15433841f6dSchristos ACPI_WARNING ((Module, Line,
15533841f6dSchristos "Attempt to allocate zero bytes, allocating 1 byte"));
15633841f6dSchristos Size = 1;
15733841f6dSchristos }
15833841f6dSchristos
15933841f6dSchristos Allocation = AcpiOsAllocate (Size + sizeof (ACPI_DEBUG_MEM_HEADER));
160149703c7Sjruoho if (!Allocation)
161149703c7Sjruoho {
16233841f6dSchristos /* Report allocation error */
16333841f6dSchristos
16433841f6dSchristos ACPI_WARNING ((Module, Line,
16533841f6dSchristos "Could not allocate size %u", (UINT32) Size));
16633841f6dSchristos
167149703c7Sjruoho return (NULL);
168149703c7Sjruoho }
169149703c7Sjruoho
17094e0d463Schristos Status = AcpiUtTrackAllocation (
17194e0d463Schristos Allocation, Size, ACPI_MEM_MALLOC, Component, Module, Line);
172149703c7Sjruoho if (ACPI_FAILURE (Status))
173149703c7Sjruoho {
174149703c7Sjruoho AcpiOsFree (Allocation);
175149703c7Sjruoho return (NULL);
176149703c7Sjruoho }
177149703c7Sjruoho
178149703c7Sjruoho AcpiGbl_GlobalList->TotalAllocated++;
179149703c7Sjruoho AcpiGbl_GlobalList->TotalSize += (UINT32) Size;
180149703c7Sjruoho AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
18194e0d463Schristos
18294e0d463Schristos if (AcpiGbl_GlobalList->CurrentTotalSize >
18394e0d463Schristos AcpiGbl_GlobalList->MaxOccupied)
184149703c7Sjruoho {
18594e0d463Schristos AcpiGbl_GlobalList->MaxOccupied =
18694e0d463Schristos AcpiGbl_GlobalList->CurrentTotalSize;
187149703c7Sjruoho }
188149703c7Sjruoho
189149703c7Sjruoho return ((void *) &Allocation->UserSpace);
190149703c7Sjruoho }
191149703c7Sjruoho
192149703c7Sjruoho
193149703c7Sjruoho /*******************************************************************************
194149703c7Sjruoho *
195149703c7Sjruoho * FUNCTION: AcpiUtAllocateZeroedAndTrack
196149703c7Sjruoho *
197149703c7Sjruoho * PARAMETERS: Size - Size of the allocation
198149703c7Sjruoho * Component - Component type of caller
199149703c7Sjruoho * Module - Source file name of caller
200149703c7Sjruoho * Line - Line number of caller
201149703c7Sjruoho *
202149703c7Sjruoho * RETURN: Address of the allocated memory on success, NULL on failure.
203149703c7Sjruoho *
204149703c7Sjruoho * DESCRIPTION: Subsystem equivalent of calloc.
205149703c7Sjruoho *
206149703c7Sjruoho ******************************************************************************/
207149703c7Sjruoho
208149703c7Sjruoho void *
AcpiUtAllocateZeroedAndTrack(ACPI_SIZE Size,UINT32 Component,const char * Module,UINT32 Line)209149703c7Sjruoho AcpiUtAllocateZeroedAndTrack (
210149703c7Sjruoho ACPI_SIZE Size,
211149703c7Sjruoho UINT32 Component,
212149703c7Sjruoho const char *Module,
213149703c7Sjruoho UINT32 Line)
214149703c7Sjruoho {
215149703c7Sjruoho ACPI_DEBUG_MEM_BLOCK *Allocation;
216149703c7Sjruoho ACPI_STATUS Status;
217149703c7Sjruoho
218149703c7Sjruoho
21933841f6dSchristos /* Check for an inadvertent size of zero bytes */
22033841f6dSchristos
22133841f6dSchristos if (!Size)
22233841f6dSchristos {
22333841f6dSchristos ACPI_WARNING ((Module, Line,
22433841f6dSchristos "Attempt to allocate zero bytes, allocating 1 byte"));
22533841f6dSchristos Size = 1;
22633841f6dSchristos }
22733841f6dSchristos
22894e0d463Schristos Allocation = AcpiOsAllocateZeroed (
22994e0d463Schristos Size + sizeof (ACPI_DEBUG_MEM_HEADER));
230149703c7Sjruoho if (!Allocation)
231149703c7Sjruoho {
232149703c7Sjruoho /* Report allocation error */
233149703c7Sjruoho
234149703c7Sjruoho ACPI_ERROR ((Module, Line,
235149703c7Sjruoho "Could not allocate size %u", (UINT32) Size));
236149703c7Sjruoho return (NULL);
237149703c7Sjruoho }
238149703c7Sjruoho
239149703c7Sjruoho Status = AcpiUtTrackAllocation (Allocation, Size,
240149703c7Sjruoho ACPI_MEM_CALLOC, Component, Module, Line);
241149703c7Sjruoho if (ACPI_FAILURE (Status))
242149703c7Sjruoho {
243149703c7Sjruoho AcpiOsFree (Allocation);
244149703c7Sjruoho return (NULL);
245149703c7Sjruoho }
246149703c7Sjruoho
247149703c7Sjruoho AcpiGbl_GlobalList->TotalAllocated++;
248149703c7Sjruoho AcpiGbl_GlobalList->TotalSize += (UINT32) Size;
249149703c7Sjruoho AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
25094e0d463Schristos
25194e0d463Schristos if (AcpiGbl_GlobalList->CurrentTotalSize >
25294e0d463Schristos AcpiGbl_GlobalList->MaxOccupied)
253149703c7Sjruoho {
25494e0d463Schristos AcpiGbl_GlobalList->MaxOccupied =
25594e0d463Schristos AcpiGbl_GlobalList->CurrentTotalSize;
256149703c7Sjruoho }
257149703c7Sjruoho
258149703c7Sjruoho return ((void *) &Allocation->UserSpace);
259149703c7Sjruoho }
260149703c7Sjruoho
261149703c7Sjruoho
262149703c7Sjruoho /*******************************************************************************
263149703c7Sjruoho *
264149703c7Sjruoho * FUNCTION: AcpiUtFreeAndTrack
265149703c7Sjruoho *
266149703c7Sjruoho * PARAMETERS: Allocation - Address of the memory to deallocate
267149703c7Sjruoho * Component - Component type of caller
268149703c7Sjruoho * Module - Source file name of caller
269149703c7Sjruoho * Line - Line number of caller
270149703c7Sjruoho *
271149703c7Sjruoho * RETURN: None
272149703c7Sjruoho *
273149703c7Sjruoho * DESCRIPTION: Frees the memory at Allocation
274149703c7Sjruoho *
275149703c7Sjruoho ******************************************************************************/
276149703c7Sjruoho
277149703c7Sjruoho void
AcpiUtFreeAndTrack(void * Allocation,UINT32 Component,const char * Module,UINT32 Line)278149703c7Sjruoho AcpiUtFreeAndTrack (
279149703c7Sjruoho void *Allocation,
280149703c7Sjruoho UINT32 Component,
281149703c7Sjruoho const char *Module,
282149703c7Sjruoho UINT32 Line)
283149703c7Sjruoho {
284149703c7Sjruoho ACPI_DEBUG_MEM_BLOCK *DebugBlock;
285149703c7Sjruoho ACPI_STATUS Status;
286149703c7Sjruoho
287149703c7Sjruoho
288149703c7Sjruoho ACPI_FUNCTION_TRACE_PTR (UtFree, Allocation);
289149703c7Sjruoho
290149703c7Sjruoho
291149703c7Sjruoho if (NULL == Allocation)
292149703c7Sjruoho {
293149703c7Sjruoho ACPI_ERROR ((Module, Line,
294149703c7Sjruoho "Attempt to delete a NULL address"));
295149703c7Sjruoho
296149703c7Sjruoho return_VOID;
297149703c7Sjruoho }
298149703c7Sjruoho
299149703c7Sjruoho DebugBlock = ACPI_CAST_PTR (ACPI_DEBUG_MEM_BLOCK,
300149703c7Sjruoho (((char *) Allocation) - sizeof (ACPI_DEBUG_MEM_HEADER)));
301149703c7Sjruoho
302149703c7Sjruoho AcpiGbl_GlobalList->TotalFreed++;
303149703c7Sjruoho AcpiGbl_GlobalList->CurrentTotalSize -= DebugBlock->Size;
304149703c7Sjruoho
30594e0d463Schristos Status = AcpiUtRemoveAllocation (DebugBlock, Component, Module, Line);
306149703c7Sjruoho if (ACPI_FAILURE (Status))
307149703c7Sjruoho {
308149703c7Sjruoho ACPI_EXCEPTION ((AE_INFO, Status, "Could not free memory"));
309149703c7Sjruoho }
310149703c7Sjruoho
311149703c7Sjruoho AcpiOsFree (DebugBlock);
312ea4d7e80Schristos ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n",
313ea4d7e80Schristos Allocation, DebugBlock));
314149703c7Sjruoho return_VOID;
315149703c7Sjruoho }
316149703c7Sjruoho
317149703c7Sjruoho
318149703c7Sjruoho /*******************************************************************************
319149703c7Sjruoho *
320149703c7Sjruoho * FUNCTION: AcpiUtFindAllocation
321149703c7Sjruoho *
322149703c7Sjruoho * PARAMETERS: Allocation - Address of allocated memory
323149703c7Sjruoho *
32433841f6dSchristos * RETURN: Three cases:
32533841f6dSchristos * 1) List is empty, NULL is returned.
32633841f6dSchristos * 2) Element was found. Returns Allocation parameter.
32733841f6dSchristos * 3) Element was not found. Returns position where it should be
32833841f6dSchristos * inserted into the list.
329149703c7Sjruoho *
330149703c7Sjruoho * DESCRIPTION: Searches for an element in the global allocation tracking list.
33133841f6dSchristos * If the element is not found, returns the location within the
33233841f6dSchristos * list where the element should be inserted.
33333841f6dSchristos *
33433841f6dSchristos * Note: The list is ordered by larger-to-smaller addresses.
33533841f6dSchristos *
33633841f6dSchristos * This global list is used to detect memory leaks in ACPICA as
33733841f6dSchristos * well as other issues such as an attempt to release the same
33833841f6dSchristos * internal object more than once. Although expensive as far
33933841f6dSchristos * as cpu time, this list is much more helpful for finding these
34033841f6dSchristos * types of issues than using memory leak detectors outside of
34133841f6dSchristos * the ACPICA code.
342149703c7Sjruoho *
343149703c7Sjruoho ******************************************************************************/
344149703c7Sjruoho
345149703c7Sjruoho static ACPI_DEBUG_MEM_BLOCK *
AcpiUtFindAllocation(ACPI_DEBUG_MEM_BLOCK * Allocation)346149703c7Sjruoho AcpiUtFindAllocation (
34733841f6dSchristos ACPI_DEBUG_MEM_BLOCK *Allocation)
348149703c7Sjruoho {
349149703c7Sjruoho ACPI_DEBUG_MEM_BLOCK *Element;
350149703c7Sjruoho
351149703c7Sjruoho
352149703c7Sjruoho Element = AcpiGbl_GlobalList->ListHead;
35333841f6dSchristos if (!Element)
354149703c7Sjruoho {
35533841f6dSchristos return (NULL);
35633841f6dSchristos }
35733841f6dSchristos
35833841f6dSchristos /*
35933841f6dSchristos * Search for the address.
36033841f6dSchristos *
36133841f6dSchristos * Note: List is ordered by larger-to-smaller addresses, on the
36233841f6dSchristos * assumption that a new allocation usually has a larger address
36333841f6dSchristos * than previous allocations.
36433841f6dSchristos */
36533841f6dSchristos while (Element > Allocation)
36633841f6dSchristos {
36733841f6dSchristos /* Check for end-of-list */
36833841f6dSchristos
36933841f6dSchristos if (!Element->Next)
370149703c7Sjruoho {
371149703c7Sjruoho return (Element);
372149703c7Sjruoho }
373149703c7Sjruoho
374149703c7Sjruoho Element = Element->Next;
375149703c7Sjruoho }
376149703c7Sjruoho
37733841f6dSchristos if (Element == Allocation)
37833841f6dSchristos {
37933841f6dSchristos return (Element);
38033841f6dSchristos }
38133841f6dSchristos
38233841f6dSchristos return (Element->Previous);
383149703c7Sjruoho }
384149703c7Sjruoho
385149703c7Sjruoho
386149703c7Sjruoho /*******************************************************************************
387149703c7Sjruoho *
388149703c7Sjruoho * FUNCTION: AcpiUtTrackAllocation
389149703c7Sjruoho *
390149703c7Sjruoho * PARAMETERS: Allocation - Address of allocated memory
391149703c7Sjruoho * Size - Size of the allocation
392149703c7Sjruoho * AllocType - MEM_MALLOC or MEM_CALLOC
393149703c7Sjruoho * Component - Component type of caller
394149703c7Sjruoho * Module - Source file name of caller
395149703c7Sjruoho * Line - Line number of caller
396149703c7Sjruoho *
39733841f6dSchristos * RETURN: Status
398149703c7Sjruoho *
399149703c7Sjruoho * DESCRIPTION: Inserts an element into the global allocation tracking list.
400149703c7Sjruoho *
401149703c7Sjruoho ******************************************************************************/
402149703c7Sjruoho
403149703c7Sjruoho static ACPI_STATUS
AcpiUtTrackAllocation(ACPI_DEBUG_MEM_BLOCK * Allocation,ACPI_SIZE Size,UINT8 AllocType,UINT32 Component,const char * Module,UINT32 Line)404149703c7Sjruoho AcpiUtTrackAllocation (
405149703c7Sjruoho ACPI_DEBUG_MEM_BLOCK *Allocation,
406149703c7Sjruoho ACPI_SIZE Size,
407149703c7Sjruoho UINT8 AllocType,
408149703c7Sjruoho UINT32 Component,
409149703c7Sjruoho const char *Module,
410149703c7Sjruoho UINT32 Line)
411149703c7Sjruoho {
412149703c7Sjruoho ACPI_MEMORY_LIST *MemList;
413149703c7Sjruoho ACPI_DEBUG_MEM_BLOCK *Element;
414149703c7Sjruoho ACPI_STATUS Status = AE_OK;
415149703c7Sjruoho
416149703c7Sjruoho
417149703c7Sjruoho ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation);
418149703c7Sjruoho
419149703c7Sjruoho
420149703c7Sjruoho if (AcpiGbl_DisableMemTracking)
421149703c7Sjruoho {
422149703c7Sjruoho return_ACPI_STATUS (AE_OK);
423149703c7Sjruoho }
424149703c7Sjruoho
425149703c7Sjruoho MemList = AcpiGbl_GlobalList;
426149703c7Sjruoho Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
427149703c7Sjruoho if (ACPI_FAILURE (Status))
428149703c7Sjruoho {
429149703c7Sjruoho return_ACPI_STATUS (Status);
430149703c7Sjruoho }
431149703c7Sjruoho
432149703c7Sjruoho /*
43333841f6dSchristos * Search the global list for this address to make sure it is not
43433841f6dSchristos * already present. This will catch several kinds of problems.
435149703c7Sjruoho */
436149703c7Sjruoho Element = AcpiUtFindAllocation (Allocation);
43733841f6dSchristos if (Element == Allocation)
438149703c7Sjruoho {
439149703c7Sjruoho ACPI_ERROR ((AE_INFO,
44033841f6dSchristos "UtTrackAllocation: Allocation (%p) already present in global list!",
441149703c7Sjruoho Allocation));
442149703c7Sjruoho goto UnlockAndExit;
443149703c7Sjruoho }
444149703c7Sjruoho
44533841f6dSchristos /* Fill in the instance data */
446149703c7Sjruoho
447149703c7Sjruoho Allocation->Size = (UINT32) Size;
448149703c7Sjruoho Allocation->AllocType = AllocType;
449149703c7Sjruoho Allocation->Component = Component;
450149703c7Sjruoho Allocation->Line = Line;
451149703c7Sjruoho
452da9fe235Sozaki-r AcpiUtSafeStrncpy (Allocation->Module, Module, ACPI_MAX_MODULE_NAME);
453149703c7Sjruoho
45433841f6dSchristos if (!Element)
45533841f6dSchristos {
456149703c7Sjruoho /* Insert at list head */
457149703c7Sjruoho
458149703c7Sjruoho if (MemList->ListHead)
459149703c7Sjruoho {
46094e0d463Schristos ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous =
46194e0d463Schristos Allocation;
462149703c7Sjruoho }
463149703c7Sjruoho
464149703c7Sjruoho Allocation->Next = MemList->ListHead;
465149703c7Sjruoho Allocation->Previous = NULL;
466149703c7Sjruoho
467149703c7Sjruoho MemList->ListHead = Allocation;
46833841f6dSchristos }
46933841f6dSchristos else
47033841f6dSchristos {
47133841f6dSchristos /* Insert after element */
47233841f6dSchristos
47333841f6dSchristos Allocation->Next = Element->Next;
47433841f6dSchristos Allocation->Previous = Element;
47533841f6dSchristos
47633841f6dSchristos if (Element->Next)
47733841f6dSchristos {
47833841f6dSchristos (Element->Next)->Previous = Allocation;
47933841f6dSchristos }
48033841f6dSchristos
48133841f6dSchristos Element->Next = Allocation;
48233841f6dSchristos }
483149703c7Sjruoho
484149703c7Sjruoho
485149703c7Sjruoho UnlockAndExit:
486149703c7Sjruoho Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
487149703c7Sjruoho return_ACPI_STATUS (Status);
488149703c7Sjruoho }
489149703c7Sjruoho
490149703c7Sjruoho
491149703c7Sjruoho /*******************************************************************************
492149703c7Sjruoho *
493149703c7Sjruoho * FUNCTION: AcpiUtRemoveAllocation
494149703c7Sjruoho *
495149703c7Sjruoho * PARAMETERS: Allocation - Address of allocated memory
496149703c7Sjruoho * Component - Component type of caller
497149703c7Sjruoho * Module - Source file name of caller
498149703c7Sjruoho * Line - Line number of caller
499149703c7Sjruoho *
50033841f6dSchristos * RETURN: Status
501149703c7Sjruoho *
502149703c7Sjruoho * DESCRIPTION: Deletes an element from the global allocation tracking list.
503149703c7Sjruoho *
504149703c7Sjruoho ******************************************************************************/
505149703c7Sjruoho
506149703c7Sjruoho static ACPI_STATUS
AcpiUtRemoveAllocation(ACPI_DEBUG_MEM_BLOCK * Allocation,UINT32 Component,const char * Module,UINT32 Line)507149703c7Sjruoho AcpiUtRemoveAllocation (
508149703c7Sjruoho ACPI_DEBUG_MEM_BLOCK *Allocation,
509149703c7Sjruoho UINT32 Component,
510149703c7Sjruoho const char *Module,
511149703c7Sjruoho UINT32 Line)
512149703c7Sjruoho {
513149703c7Sjruoho ACPI_MEMORY_LIST *MemList;
514149703c7Sjruoho ACPI_STATUS Status;
515149703c7Sjruoho
516149703c7Sjruoho
51733841f6dSchristos ACPI_FUNCTION_NAME (UtRemoveAllocation);
518149703c7Sjruoho
519149703c7Sjruoho
520149703c7Sjruoho if (AcpiGbl_DisableMemTracking)
521149703c7Sjruoho {
52233841f6dSchristos return (AE_OK);
523149703c7Sjruoho }
524149703c7Sjruoho
525149703c7Sjruoho MemList = AcpiGbl_GlobalList;
526149703c7Sjruoho if (NULL == MemList->ListHead)
527149703c7Sjruoho {
528149703c7Sjruoho /* No allocations! */
529149703c7Sjruoho
530149703c7Sjruoho ACPI_ERROR ((Module, Line,
531149703c7Sjruoho "Empty allocation list, nothing to free!"));
532149703c7Sjruoho
53333841f6dSchristos return (AE_OK);
534149703c7Sjruoho }
535149703c7Sjruoho
536149703c7Sjruoho Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
537149703c7Sjruoho if (ACPI_FAILURE (Status))
538149703c7Sjruoho {
53933841f6dSchristos return (Status);
540149703c7Sjruoho }
541149703c7Sjruoho
542149703c7Sjruoho /* Unlink */
543149703c7Sjruoho
544149703c7Sjruoho if (Allocation->Previous)
545149703c7Sjruoho {
546149703c7Sjruoho (Allocation->Previous)->Next = Allocation->Next;
547149703c7Sjruoho }
548149703c7Sjruoho else
549149703c7Sjruoho {
550149703c7Sjruoho MemList->ListHead = Allocation->Next;
551149703c7Sjruoho }
552149703c7Sjruoho
553149703c7Sjruoho if (Allocation->Next)
554149703c7Sjruoho {
555149703c7Sjruoho (Allocation->Next)->Previous = Allocation->Previous;
556149703c7Sjruoho }
557149703c7Sjruoho
55833841f6dSchristos ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
55933841f6dSchristos &Allocation->UserSpace, Allocation->Size));
56033841f6dSchristos
561149703c7Sjruoho /* Mark the segment as deleted */
562149703c7Sjruoho
563e34402d4Schristos memset (&Allocation->UserSpace, 0xEA, Allocation->Size);
564149703c7Sjruoho
565149703c7Sjruoho Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
56633841f6dSchristos return (Status);
567149703c7Sjruoho }
568149703c7Sjruoho
569149703c7Sjruoho
570149703c7Sjruoho /*******************************************************************************
571149703c7Sjruoho *
572149703c7Sjruoho * FUNCTION: AcpiUtDumpAllocationInfo
573149703c7Sjruoho *
57433841f6dSchristos * PARAMETERS: None
575149703c7Sjruoho *
576149703c7Sjruoho * RETURN: None
577149703c7Sjruoho *
578149703c7Sjruoho * DESCRIPTION: Print some info about the outstanding allocations.
579149703c7Sjruoho *
580149703c7Sjruoho ******************************************************************************/
581149703c7Sjruoho
582149703c7Sjruoho void
AcpiUtDumpAllocationInfo(void)583149703c7Sjruoho AcpiUtDumpAllocationInfo (
584149703c7Sjruoho void)
585149703c7Sjruoho {
586149703c7Sjruoho /*
587149703c7Sjruoho ACPI_MEMORY_LIST *MemList;
588149703c7Sjruoho */
589149703c7Sjruoho
590149703c7Sjruoho ACPI_FUNCTION_TRACE (UtDumpAllocationInfo);
591149703c7Sjruoho
592149703c7Sjruoho /*
593149703c7Sjruoho ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
594149703c7Sjruoho ("%30s: %4d (%3d Kb)\n", "Current allocations",
595149703c7Sjruoho MemList->CurrentCount,
596149703c7Sjruoho ROUND_UP_TO_1K (MemList->CurrentSize)));
597149703c7Sjruoho
598149703c7Sjruoho ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
599149703c7Sjruoho ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
600149703c7Sjruoho MemList->MaxConcurrentCount,
601149703c7Sjruoho ROUND_UP_TO_1K (MemList->MaxConcurrentSize)));
602149703c7Sjruoho
603149703c7Sjruoho
604149703c7Sjruoho ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
605149703c7Sjruoho ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
606149703c7Sjruoho RunningObjectCount,
607149703c7Sjruoho ROUND_UP_TO_1K (RunningObjectSize)));
608149703c7Sjruoho
609149703c7Sjruoho ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
610149703c7Sjruoho ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
611149703c7Sjruoho RunningAllocCount,
612149703c7Sjruoho ROUND_UP_TO_1K (RunningAllocSize)));
613149703c7Sjruoho
614149703c7Sjruoho
615149703c7Sjruoho ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
616149703c7Sjruoho ("%30s: %4d (%3d Kb)\n", "Current Nodes",
617149703c7Sjruoho AcpiGbl_CurrentNodeCount,
618149703c7Sjruoho ROUND_UP_TO_1K (AcpiGbl_CurrentNodeSize)));
619149703c7Sjruoho
620149703c7Sjruoho ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
621149703c7Sjruoho ("%30s: %4d (%3d Kb)\n", "Max Nodes",
622149703c7Sjruoho AcpiGbl_MaxConcurrentNodeCount,
623149703c7Sjruoho ROUND_UP_TO_1K ((AcpiGbl_MaxConcurrentNodeCount *
624149703c7Sjruoho sizeof (ACPI_NAMESPACE_NODE)))));
625149703c7Sjruoho */
626149703c7Sjruoho return_VOID;
627149703c7Sjruoho }
628149703c7Sjruoho
629149703c7Sjruoho
630149703c7Sjruoho /*******************************************************************************
631149703c7Sjruoho *
632149703c7Sjruoho * FUNCTION: AcpiUtDumpAllocations
633149703c7Sjruoho *
634149703c7Sjruoho * PARAMETERS: Component - Component(s) to dump info for.
635149703c7Sjruoho * Module - Module to dump info for. NULL means all.
636149703c7Sjruoho *
637149703c7Sjruoho * RETURN: None
638149703c7Sjruoho *
639149703c7Sjruoho * DESCRIPTION: Print a list of all outstanding allocations.
640149703c7Sjruoho *
641149703c7Sjruoho ******************************************************************************/
642149703c7Sjruoho
643149703c7Sjruoho void
AcpiUtDumpAllocations(UINT32 Component,const char * Module)644149703c7Sjruoho AcpiUtDumpAllocations (
645149703c7Sjruoho UINT32 Component,
646149703c7Sjruoho const char *Module)
647149703c7Sjruoho {
648149703c7Sjruoho ACPI_DEBUG_MEM_BLOCK *Element;
649149703c7Sjruoho ACPI_DESCRIPTOR *Descriptor;
650149703c7Sjruoho UINT32 NumOutstanding = 0;
651149703c7Sjruoho UINT8 DescriptorType;
652149703c7Sjruoho
653149703c7Sjruoho
654149703c7Sjruoho ACPI_FUNCTION_TRACE (UtDumpAllocations);
655149703c7Sjruoho
656149703c7Sjruoho
657149703c7Sjruoho if (AcpiGbl_DisableMemTracking)
658149703c7Sjruoho {
65933841f6dSchristos return_VOID;
660149703c7Sjruoho }
661149703c7Sjruoho
662149703c7Sjruoho /*
663149703c7Sjruoho * Walk the allocation list.
664149703c7Sjruoho */
665149703c7Sjruoho if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY)))
666149703c7Sjruoho {
66733841f6dSchristos return_VOID;
668149703c7Sjruoho }
669149703c7Sjruoho
67035a687ffSchristos if (!AcpiGbl_GlobalList)
67135a687ffSchristos {
67235a687ffSchristos goto Exit;
67335a687ffSchristos }
67435a687ffSchristos
675149703c7Sjruoho Element = AcpiGbl_GlobalList->ListHead;
676149703c7Sjruoho while (Element)
677149703c7Sjruoho {
678149703c7Sjruoho if ((Element->Component & Component) &&
679e34402d4Schristos ((Module == NULL) || (0 == strcmp (Module, Element->Module))))
680149703c7Sjruoho {
68194e0d463Schristos Descriptor = ACPI_CAST_PTR (
68294e0d463Schristos ACPI_DESCRIPTOR, &Element->UserSpace);
683149703c7Sjruoho
684149703c7Sjruoho if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR))
685149703c7Sjruoho {
68635a687ffSchristos AcpiOsPrintf ("%p Length 0x%04X %9.9s-%4.4u "
687149703c7Sjruoho "[Not a Descriptor - too small]\n",
688149703c7Sjruoho Descriptor, Element->Size, Element->Module,
689149703c7Sjruoho Element->Line);
690149703c7Sjruoho }
691149703c7Sjruoho else
692149703c7Sjruoho {
693149703c7Sjruoho /* Ignore allocated objects that are in a cache */
694149703c7Sjruoho
69594e0d463Schristos if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) !=
69694e0d463Schristos ACPI_DESC_TYPE_CACHED)
697149703c7Sjruoho {
69835a687ffSchristos AcpiOsPrintf ("%p Length 0x%04X %9.9s-%4.4u [%s] ",
699149703c7Sjruoho Descriptor, Element->Size, Element->Module,
700149703c7Sjruoho Element->Line, AcpiUtGetDescriptorName (Descriptor));
701149703c7Sjruoho
702f5a85da7Schristos /* Optional object hex dump */
703f5a85da7Schristos
704f5a85da7Schristos if (AcpiGbl_VerboseLeakDump)
705f5a85da7Schristos {
706f5a85da7Schristos AcpiOsPrintf ("\n");
707f5a85da7Schristos AcpiUtDumpBuffer ((UINT8 *) Descriptor, Element->Size,
708f5a85da7Schristos DB_BYTE_DISPLAY, 0);
709f5a85da7Schristos }
710f5a85da7Schristos
711149703c7Sjruoho /* Validate the descriptor type using Type field and length */
712149703c7Sjruoho
713149703c7Sjruoho DescriptorType = 0; /* Not a valid descriptor type */
714149703c7Sjruoho
715149703c7Sjruoho switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor))
716149703c7Sjruoho {
717149703c7Sjruoho case ACPI_DESC_TYPE_OPERAND:
71833841f6dSchristos
71933841f6dSchristos if (Element->Size == sizeof (ACPI_OPERAND_OBJECT))
720149703c7Sjruoho {
721149703c7Sjruoho DescriptorType = ACPI_DESC_TYPE_OPERAND;
722149703c7Sjruoho }
723149703c7Sjruoho break;
724149703c7Sjruoho
725149703c7Sjruoho case ACPI_DESC_TYPE_PARSER:
72633841f6dSchristos
72733841f6dSchristos if (Element->Size == sizeof (ACPI_PARSE_OBJECT))
728149703c7Sjruoho {
729149703c7Sjruoho DescriptorType = ACPI_DESC_TYPE_PARSER;
730149703c7Sjruoho }
731149703c7Sjruoho break;
732149703c7Sjruoho
733149703c7Sjruoho case ACPI_DESC_TYPE_NAMED:
73433841f6dSchristos
73533841f6dSchristos if (Element->Size == sizeof (ACPI_NAMESPACE_NODE))
736149703c7Sjruoho {
737149703c7Sjruoho DescriptorType = ACPI_DESC_TYPE_NAMED;
738149703c7Sjruoho }
739149703c7Sjruoho break;
740149703c7Sjruoho
741149703c7Sjruoho default:
74233841f6dSchristos
743149703c7Sjruoho break;
744149703c7Sjruoho }
745149703c7Sjruoho
746149703c7Sjruoho /* Display additional info for the major descriptor types */
747149703c7Sjruoho
748149703c7Sjruoho switch (DescriptorType)
749149703c7Sjruoho {
750149703c7Sjruoho case ACPI_DESC_TYPE_OPERAND:
75133841f6dSchristos
752149703c7Sjruoho AcpiOsPrintf ("%12.12s RefCount 0x%04X\n",
753149703c7Sjruoho AcpiUtGetTypeName (Descriptor->Object.Common.Type),
754149703c7Sjruoho Descriptor->Object.Common.ReferenceCount);
755149703c7Sjruoho break;
756149703c7Sjruoho
757149703c7Sjruoho case ACPI_DESC_TYPE_PARSER:
75833841f6dSchristos
7595fc006f0Schristos AcpiOsPrintf ("AmlOpcode 0x%04X\n",
760149703c7Sjruoho Descriptor->Op.Asl.AmlOpcode);
761149703c7Sjruoho break;
762149703c7Sjruoho
763149703c7Sjruoho case ACPI_DESC_TYPE_NAMED:
76433841f6dSchristos
765149703c7Sjruoho AcpiOsPrintf ("%4.4s\n",
766149703c7Sjruoho AcpiUtGetNodeName (&Descriptor->Node));
767149703c7Sjruoho break;
768149703c7Sjruoho
769149703c7Sjruoho default:
77033841f6dSchristos
771149703c7Sjruoho AcpiOsPrintf ( "\n");
772149703c7Sjruoho break;
773149703c7Sjruoho }
774149703c7Sjruoho }
775149703c7Sjruoho }
776149703c7Sjruoho
777149703c7Sjruoho NumOutstanding++;
778149703c7Sjruoho }
779149703c7Sjruoho
780149703c7Sjruoho Element = Element->Next;
781149703c7Sjruoho }
782149703c7Sjruoho
78335a687ffSchristos Exit:
784149703c7Sjruoho (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
785149703c7Sjruoho
786149703c7Sjruoho /* Print summary */
787149703c7Sjruoho
788149703c7Sjruoho if (!NumOutstanding)
789149703c7Sjruoho {
790dc79220aSchristos ACPI_INFO (("No outstanding allocations"));
791149703c7Sjruoho }
792149703c7Sjruoho else
793149703c7Sjruoho {
794232afe62Schristos ACPI_ERROR ((AE_INFO, "%u (0x%X) Outstanding cache allocations",
795149703c7Sjruoho NumOutstanding, NumOutstanding));
796149703c7Sjruoho }
797149703c7Sjruoho
798149703c7Sjruoho return_VOID;
799149703c7Sjruoho }
800149703c7Sjruoho
801149703c7Sjruoho #endif /* ACPI_DBG_TRACK_ALLOCATIONS */
802