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