1ae115bc7Smrj /******************************************************************************
2ae115bc7Smrj *
3ae115bc7Smrj * Module Name: uttrack - Memory allocation tracking routines (debug only)
4ae115bc7Smrj *
5ae115bc7Smrj *****************************************************************************/
6ae115bc7Smrj
726f3cdf0SGordon Ross /*
8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp.
9ae115bc7Smrj * All rights reserved.
10ae115bc7Smrj *
1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross * are met:
1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross * without modification.
1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross * binary redistribution.
2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross * from this software without specific prior written permission.
25ae115bc7Smrj *
2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross * Software Foundation.
29ae115bc7Smrj *
3026f3cdf0SGordon Ross * NO WARRANTY
3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross */
43ae115bc7Smrj
44ae115bc7Smrj /*
45ae115bc7Smrj * These procedures are used for tracking memory leaks in the subsystem, and
46ae115bc7Smrj * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
47ae115bc7Smrj *
48ae115bc7Smrj * Each memory allocation is tracked via a doubly linked list. Each
49ae115bc7Smrj * element contains the caller's component, module name, function name, and
50ae115bc7Smrj * line number. AcpiUtAllocate and AcpiUtAllocateZeroed call
51ae115bc7Smrj * AcpiUtTrackAllocation to add an element to the list; deletion
52ae115bc7Smrj * occurs in the body of AcpiUtFree.
53ae115bc7Smrj */
54ae115bc7Smrj
55ae115bc7Smrj #include "acpi.h"
56aa2aa9a6SDana Myers #include "accommon.h"
57ae115bc7Smrj
58ae115bc7Smrj #ifdef ACPI_DBG_TRACK_ALLOCATIONS
59ae115bc7Smrj
60ae115bc7Smrj #define _COMPONENT ACPI_UTILITIES
61ae115bc7Smrj ACPI_MODULE_NAME ("uttrack")
62ae115bc7Smrj
63*385cc6b4SJerry Jelinek
64ae115bc7Smrj /* Local prototypes */
65ae115bc7Smrj
66ae115bc7Smrj static ACPI_DEBUG_MEM_BLOCK *
67ae115bc7Smrj AcpiUtFindAllocation (
68*385cc6b4SJerry Jelinek ACPI_DEBUG_MEM_BLOCK *Allocation);
69ae115bc7Smrj
70ae115bc7Smrj static ACPI_STATUS
71ae115bc7Smrj AcpiUtTrackAllocation (
72ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Address,
73ae115bc7Smrj ACPI_SIZE Size,
74ae115bc7Smrj UINT8 AllocType,
75ae115bc7Smrj UINT32 Component,
76db2bae30SDana Myers const char *Module,
77ae115bc7Smrj UINT32 Line);
78ae115bc7Smrj
79ae115bc7Smrj static ACPI_STATUS
80ae115bc7Smrj AcpiUtRemoveAllocation (
81ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Address,
82ae115bc7Smrj UINT32 Component,
83db2bae30SDana Myers const char *Module,
84ae115bc7Smrj UINT32 Line);
85ae115bc7Smrj
86ae115bc7Smrj
87ae115bc7Smrj /*******************************************************************************
88ae115bc7Smrj *
89ae115bc7Smrj * FUNCTION: AcpiUtCreateList
90ae115bc7Smrj *
91ae115bc7Smrj * PARAMETERS: CacheName - Ascii name for the cache
92ae115bc7Smrj * ObjectSize - Size of each cached object
93ae115bc7Smrj * ReturnCache - Where the new cache object is returned
94ae115bc7Smrj *
95ae115bc7Smrj * RETURN: Status
96ae115bc7Smrj *
97ae115bc7Smrj * DESCRIPTION: Create a local memory list for tracking purposed
98ae115bc7Smrj *
99ae115bc7Smrj ******************************************************************************/
100ae115bc7Smrj
101ae115bc7Smrj ACPI_STATUS
AcpiUtCreateList(const char * ListName,UINT16 ObjectSize,ACPI_MEMORY_LIST ** ReturnCache)102ae115bc7Smrj AcpiUtCreateList (
103*385cc6b4SJerry Jelinek const char *ListName,
104ae115bc7Smrj UINT16 ObjectSize,
105ae115bc7Smrj ACPI_MEMORY_LIST **ReturnCache)
106ae115bc7Smrj {
107ae115bc7Smrj ACPI_MEMORY_LIST *Cache;
108ae115bc7Smrj
109ae115bc7Smrj
110ae115bc7Smrj Cache = AcpiOsAllocate (sizeof (ACPI_MEMORY_LIST));
111ae115bc7Smrj if (!Cache)
112ae115bc7Smrj {
113ae115bc7Smrj return (AE_NO_MEMORY);
114ae115bc7Smrj }
115ae115bc7Smrj
116*385cc6b4SJerry Jelinek memset (Cache, 0, sizeof (ACPI_MEMORY_LIST));
117ae115bc7Smrj
118ae115bc7Smrj Cache->ListName = ListName;
119ae115bc7Smrj Cache->ObjectSize = ObjectSize;
120ae115bc7Smrj
121ae115bc7Smrj *ReturnCache = Cache;
122ae115bc7Smrj return (AE_OK);
123ae115bc7Smrj }
124ae115bc7Smrj
125ae115bc7Smrj
126ae115bc7Smrj /*******************************************************************************
127ae115bc7Smrj *
128ae115bc7Smrj * FUNCTION: AcpiUtAllocateAndTrack
129ae115bc7Smrj *
130ae115bc7Smrj * PARAMETERS: Size - Size of the allocation
131ae115bc7Smrj * Component - Component type of caller
132ae115bc7Smrj * Module - Source file name of caller
133ae115bc7Smrj * Line - Line number of caller
134ae115bc7Smrj *
135ae115bc7Smrj * RETURN: Address of the allocated memory on success, NULL on failure.
136ae115bc7Smrj *
137ae115bc7Smrj * DESCRIPTION: The subsystem's equivalent of malloc.
138ae115bc7Smrj *
139ae115bc7Smrj ******************************************************************************/
140ae115bc7Smrj
141ae115bc7Smrj void *
AcpiUtAllocateAndTrack(ACPI_SIZE Size,UINT32 Component,const char * Module,UINT32 Line)142ae115bc7Smrj AcpiUtAllocateAndTrack (
143ae115bc7Smrj ACPI_SIZE Size,
144ae115bc7Smrj UINT32 Component,
145db2bae30SDana Myers const char *Module,
146ae115bc7Smrj UINT32 Line)
147ae115bc7Smrj {
148ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Allocation;
149ae115bc7Smrj ACPI_STATUS Status;
150ae115bc7Smrj
151ae115bc7Smrj
152*385cc6b4SJerry Jelinek /* Check for an inadvertent size of zero bytes */
153*385cc6b4SJerry Jelinek
154*385cc6b4SJerry Jelinek if (!Size)
155*385cc6b4SJerry Jelinek {
156*385cc6b4SJerry Jelinek ACPI_WARNING ((Module, Line,
157*385cc6b4SJerry Jelinek "Attempt to allocate zero bytes, allocating 1 byte"));
158*385cc6b4SJerry Jelinek Size = 1;
159*385cc6b4SJerry Jelinek }
160*385cc6b4SJerry Jelinek
161*385cc6b4SJerry Jelinek Allocation = AcpiOsAllocate (Size + sizeof (ACPI_DEBUG_MEM_HEADER));
162ae115bc7Smrj if (!Allocation)
163ae115bc7Smrj {
164*385cc6b4SJerry Jelinek /* Report allocation error */
165*385cc6b4SJerry Jelinek
166*385cc6b4SJerry Jelinek ACPI_WARNING ((Module, Line,
167*385cc6b4SJerry Jelinek "Could not allocate size %u", (UINT32) Size));
168*385cc6b4SJerry Jelinek
169ae115bc7Smrj return (NULL);
170ae115bc7Smrj }
171ae115bc7Smrj
172*385cc6b4SJerry Jelinek Status = AcpiUtTrackAllocation (
173*385cc6b4SJerry Jelinek Allocation, Size, ACPI_MEM_MALLOC, Component, Module, Line);
174ae115bc7Smrj if (ACPI_FAILURE (Status))
175ae115bc7Smrj {
176ae115bc7Smrj AcpiOsFree (Allocation);
177ae115bc7Smrj return (NULL);
178ae115bc7Smrj }
179ae115bc7Smrj
180ae115bc7Smrj AcpiGbl_GlobalList->TotalAllocated++;
181db2bae30SDana Myers AcpiGbl_GlobalList->TotalSize += (UINT32) Size;
182ae115bc7Smrj AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
183*385cc6b4SJerry Jelinek
184*385cc6b4SJerry Jelinek if (AcpiGbl_GlobalList->CurrentTotalSize >
185*385cc6b4SJerry Jelinek AcpiGbl_GlobalList->MaxOccupied)
186db2bae30SDana Myers {
187*385cc6b4SJerry Jelinek AcpiGbl_GlobalList->MaxOccupied =
188*385cc6b4SJerry Jelinek AcpiGbl_GlobalList->CurrentTotalSize;
189db2bae30SDana Myers }
190ae115bc7Smrj
191ae115bc7Smrj return ((void *) &Allocation->UserSpace);
192ae115bc7Smrj }
193ae115bc7Smrj
194ae115bc7Smrj
195ae115bc7Smrj /*******************************************************************************
196ae115bc7Smrj *
197ae115bc7Smrj * FUNCTION: AcpiUtAllocateZeroedAndTrack
198ae115bc7Smrj *
199ae115bc7Smrj * PARAMETERS: Size - Size of the allocation
200ae115bc7Smrj * Component - Component type of caller
201ae115bc7Smrj * Module - Source file name of caller
202ae115bc7Smrj * Line - Line number of caller
203ae115bc7Smrj *
204ae115bc7Smrj * RETURN: Address of the allocated memory on success, NULL on failure.
205ae115bc7Smrj *
206ae115bc7Smrj * DESCRIPTION: Subsystem equivalent of calloc.
207ae115bc7Smrj *
208ae115bc7Smrj ******************************************************************************/
209ae115bc7Smrj
210ae115bc7Smrj void *
AcpiUtAllocateZeroedAndTrack(ACPI_SIZE Size,UINT32 Component,const char * Module,UINT32 Line)211ae115bc7Smrj AcpiUtAllocateZeroedAndTrack (
212ae115bc7Smrj ACPI_SIZE Size,
213ae115bc7Smrj UINT32 Component,
214db2bae30SDana Myers const char *Module,
215ae115bc7Smrj UINT32 Line)
216ae115bc7Smrj {
217ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Allocation;
218ae115bc7Smrj ACPI_STATUS Status;
219ae115bc7Smrj
220ae115bc7Smrj
221*385cc6b4SJerry Jelinek /* Check for an inadvertent size of zero bytes */
222*385cc6b4SJerry Jelinek
223*385cc6b4SJerry Jelinek if (!Size)
224*385cc6b4SJerry Jelinek {
225*385cc6b4SJerry Jelinek ACPI_WARNING ((Module, Line,
226*385cc6b4SJerry Jelinek "Attempt to allocate zero bytes, allocating 1 byte"));
227*385cc6b4SJerry Jelinek Size = 1;
228*385cc6b4SJerry Jelinek }
229*385cc6b4SJerry Jelinek
230*385cc6b4SJerry Jelinek Allocation = AcpiOsAllocateZeroed (
231*385cc6b4SJerry Jelinek Size + sizeof (ACPI_DEBUG_MEM_HEADER));
232ae115bc7Smrj if (!Allocation)
233ae115bc7Smrj {
234ae115bc7Smrj /* Report allocation error */
235ae115bc7Smrj
236ae115bc7Smrj ACPI_ERROR ((Module, Line,
23726f3cdf0SGordon Ross "Could not allocate size %u", (UINT32) Size));
238ae115bc7Smrj return (NULL);
239ae115bc7Smrj }
240ae115bc7Smrj
241ae115bc7Smrj Status = AcpiUtTrackAllocation (Allocation, Size,
242ae115bc7Smrj ACPI_MEM_CALLOC, Component, Module, Line);
243ae115bc7Smrj if (ACPI_FAILURE (Status))
244ae115bc7Smrj {
245ae115bc7Smrj AcpiOsFree (Allocation);
246ae115bc7Smrj return (NULL);
247ae115bc7Smrj }
248ae115bc7Smrj
249ae115bc7Smrj AcpiGbl_GlobalList->TotalAllocated++;
250db2bae30SDana Myers AcpiGbl_GlobalList->TotalSize += (UINT32) Size;
251ae115bc7Smrj AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
252*385cc6b4SJerry Jelinek
253*385cc6b4SJerry Jelinek if (AcpiGbl_GlobalList->CurrentTotalSize >
254*385cc6b4SJerry Jelinek AcpiGbl_GlobalList->MaxOccupied)
255db2bae30SDana Myers {
256*385cc6b4SJerry Jelinek AcpiGbl_GlobalList->MaxOccupied =
257*385cc6b4SJerry Jelinek AcpiGbl_GlobalList->CurrentTotalSize;
258db2bae30SDana Myers }
259ae115bc7Smrj
260ae115bc7Smrj return ((void *) &Allocation->UserSpace);
261ae115bc7Smrj }
262ae115bc7Smrj
263ae115bc7Smrj
264ae115bc7Smrj /*******************************************************************************
265ae115bc7Smrj *
266ae115bc7Smrj * FUNCTION: AcpiUtFreeAndTrack
267ae115bc7Smrj *
268ae115bc7Smrj * PARAMETERS: Allocation - Address of the memory to deallocate
269ae115bc7Smrj * Component - Component type of caller
270ae115bc7Smrj * Module - Source file name of caller
271ae115bc7Smrj * Line - Line number of caller
272ae115bc7Smrj *
273ae115bc7Smrj * RETURN: None
274ae115bc7Smrj *
275ae115bc7Smrj * DESCRIPTION: Frees the memory at Allocation
276ae115bc7Smrj *
277ae115bc7Smrj ******************************************************************************/
278ae115bc7Smrj
279ae115bc7Smrj void
AcpiUtFreeAndTrack(void * Allocation,UINT32 Component,const char * Module,UINT32 Line)280ae115bc7Smrj AcpiUtFreeAndTrack (
281ae115bc7Smrj void *Allocation,
282ae115bc7Smrj UINT32 Component,
283db2bae30SDana Myers const char *Module,
284ae115bc7Smrj UINT32 Line)
285ae115bc7Smrj {
286ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *DebugBlock;
287ae115bc7Smrj ACPI_STATUS Status;
288ae115bc7Smrj
289ae115bc7Smrj
290ae115bc7Smrj ACPI_FUNCTION_TRACE_PTR (UtFree, Allocation);
291ae115bc7Smrj
292ae115bc7Smrj
293ae115bc7Smrj if (NULL == Allocation)
294ae115bc7Smrj {
295ae115bc7Smrj ACPI_ERROR ((Module, Line,
296ae115bc7Smrj "Attempt to delete a NULL address"));
297ae115bc7Smrj
298ae115bc7Smrj return_VOID;
299ae115bc7Smrj }
300ae115bc7Smrj
301ae115bc7Smrj DebugBlock = ACPI_CAST_PTR (ACPI_DEBUG_MEM_BLOCK,
302ae115bc7Smrj (((char *) Allocation) - sizeof (ACPI_DEBUG_MEM_HEADER)));
303ae115bc7Smrj
304ae115bc7Smrj AcpiGbl_GlobalList->TotalFreed++;
305ae115bc7Smrj AcpiGbl_GlobalList->CurrentTotalSize -= DebugBlock->Size;
306ae115bc7Smrj
307*385cc6b4SJerry Jelinek Status = AcpiUtRemoveAllocation (DebugBlock, Component, Module, Line);
308ae115bc7Smrj if (ACPI_FAILURE (Status))
309ae115bc7Smrj {
310ae115bc7Smrj ACPI_EXCEPTION ((AE_INFO, Status, "Could not free memory"));
311ae115bc7Smrj }
312ae115bc7Smrj
313ae115bc7Smrj AcpiOsFree (DebugBlock);
314*385cc6b4SJerry Jelinek ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n",
315*385cc6b4SJerry Jelinek Allocation, DebugBlock));
316ae115bc7Smrj return_VOID;
317ae115bc7Smrj }
318ae115bc7Smrj
319ae115bc7Smrj
320ae115bc7Smrj /*******************************************************************************
321ae115bc7Smrj *
322ae115bc7Smrj * FUNCTION: AcpiUtFindAllocation
323ae115bc7Smrj *
324ae115bc7Smrj * PARAMETERS: Allocation - Address of allocated memory
325ae115bc7Smrj *
326*385cc6b4SJerry Jelinek * RETURN: Three cases:
327*385cc6b4SJerry Jelinek * 1) List is empty, NULL is returned.
328*385cc6b4SJerry Jelinek * 2) Element was found. Returns Allocation parameter.
329*385cc6b4SJerry Jelinek * 3) Element was not found. Returns position where it should be
330*385cc6b4SJerry Jelinek * inserted into the list.
331ae115bc7Smrj *
332ae115bc7Smrj * DESCRIPTION: Searches for an element in the global allocation tracking list.
333*385cc6b4SJerry Jelinek * If the element is not found, returns the location within the
334*385cc6b4SJerry Jelinek * list where the element should be inserted.
335*385cc6b4SJerry Jelinek *
336*385cc6b4SJerry Jelinek * Note: The list is ordered by larger-to-smaller addresses.
337*385cc6b4SJerry Jelinek *
338*385cc6b4SJerry Jelinek * This global list is used to detect memory leaks in ACPICA as
339*385cc6b4SJerry Jelinek * well as other issues such as an attempt to release the same
340*385cc6b4SJerry Jelinek * internal object more than once. Although expensive as far
341*385cc6b4SJerry Jelinek * as cpu time, this list is much more helpful for finding these
342*385cc6b4SJerry Jelinek * types of issues than using memory leak detectors outside of
343*385cc6b4SJerry Jelinek * the ACPICA code.
344ae115bc7Smrj *
345ae115bc7Smrj ******************************************************************************/
346ae115bc7Smrj
347ae115bc7Smrj static ACPI_DEBUG_MEM_BLOCK *
AcpiUtFindAllocation(ACPI_DEBUG_MEM_BLOCK * Allocation)348ae115bc7Smrj AcpiUtFindAllocation (
349*385cc6b4SJerry Jelinek ACPI_DEBUG_MEM_BLOCK *Allocation)
350ae115bc7Smrj {
351ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Element;
352ae115bc7Smrj
353ae115bc7Smrj
354ae115bc7Smrj Element = AcpiGbl_GlobalList->ListHead;
355*385cc6b4SJerry Jelinek if (!Element)
356ae115bc7Smrj {
357*385cc6b4SJerry Jelinek return (NULL);
358*385cc6b4SJerry Jelinek }
359*385cc6b4SJerry Jelinek
360*385cc6b4SJerry Jelinek /*
361*385cc6b4SJerry Jelinek * Search for the address.
362*385cc6b4SJerry Jelinek *
363*385cc6b4SJerry Jelinek * Note: List is ordered by larger-to-smaller addresses, on the
364*385cc6b4SJerry Jelinek * assumption that a new allocation usually has a larger address
365*385cc6b4SJerry Jelinek * than previous allocations.
366*385cc6b4SJerry Jelinek */
367*385cc6b4SJerry Jelinek while (Element > Allocation)
368*385cc6b4SJerry Jelinek {
369*385cc6b4SJerry Jelinek /* Check for end-of-list */
370*385cc6b4SJerry Jelinek
371*385cc6b4SJerry Jelinek if (!Element->Next)
372ae115bc7Smrj {
373ae115bc7Smrj return (Element);
374ae115bc7Smrj }
375ae115bc7Smrj
376ae115bc7Smrj Element = Element->Next;
377ae115bc7Smrj }
378ae115bc7Smrj
379*385cc6b4SJerry Jelinek if (Element == Allocation)
380*385cc6b4SJerry Jelinek {
381*385cc6b4SJerry Jelinek return (Element);
382*385cc6b4SJerry Jelinek }
383*385cc6b4SJerry Jelinek
384*385cc6b4SJerry Jelinek return (Element->Previous);
385ae115bc7Smrj }
386ae115bc7Smrj
387ae115bc7Smrj
388ae115bc7Smrj /*******************************************************************************
389ae115bc7Smrj *
390ae115bc7Smrj * FUNCTION: AcpiUtTrackAllocation
391ae115bc7Smrj *
392ae115bc7Smrj * PARAMETERS: Allocation - Address of allocated memory
393ae115bc7Smrj * Size - Size of the allocation
394ae115bc7Smrj * AllocType - MEM_MALLOC or MEM_CALLOC
395ae115bc7Smrj * Component - Component type of caller
396ae115bc7Smrj * Module - Source file name of caller
397ae115bc7Smrj * Line - Line number of caller
398ae115bc7Smrj *
399*385cc6b4SJerry Jelinek * RETURN: Status
400ae115bc7Smrj *
401ae115bc7Smrj * DESCRIPTION: Inserts an element into the global allocation tracking list.
402ae115bc7Smrj *
403ae115bc7Smrj ******************************************************************************/
404ae115bc7Smrj
405ae115bc7Smrj static ACPI_STATUS
AcpiUtTrackAllocation(ACPI_DEBUG_MEM_BLOCK * Allocation,ACPI_SIZE Size,UINT8 AllocType,UINT32 Component,const char * Module,UINT32 Line)406ae115bc7Smrj AcpiUtTrackAllocation (
407ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Allocation,
408ae115bc7Smrj ACPI_SIZE Size,
409ae115bc7Smrj UINT8 AllocType,
410ae115bc7Smrj UINT32 Component,
411db2bae30SDana Myers const char *Module,
412ae115bc7Smrj UINT32 Line)
413ae115bc7Smrj {
414ae115bc7Smrj ACPI_MEMORY_LIST *MemList;
415ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Element;
416ae115bc7Smrj ACPI_STATUS Status = AE_OK;
417ae115bc7Smrj
418ae115bc7Smrj
419ae115bc7Smrj ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation);
420ae115bc7Smrj
421ae115bc7Smrj
42226f3cdf0SGordon Ross if (AcpiGbl_DisableMemTracking)
42326f3cdf0SGordon Ross {
42426f3cdf0SGordon Ross return_ACPI_STATUS (AE_OK);
42526f3cdf0SGordon Ross }
42626f3cdf0SGordon Ross
427ae115bc7Smrj MemList = AcpiGbl_GlobalList;
428ae115bc7Smrj Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
429ae115bc7Smrj if (ACPI_FAILURE (Status))
430ae115bc7Smrj {
431ae115bc7Smrj return_ACPI_STATUS (Status);
432ae115bc7Smrj }
433ae115bc7Smrj
434ae115bc7Smrj /*
435*385cc6b4SJerry Jelinek * Search the global list for this address to make sure it is not
436*385cc6b4SJerry Jelinek * already present. This will catch several kinds of problems.
437ae115bc7Smrj */
438ae115bc7Smrj Element = AcpiUtFindAllocation (Allocation);
439*385cc6b4SJerry Jelinek if (Element == Allocation)
440ae115bc7Smrj {
441ae115bc7Smrj ACPI_ERROR ((AE_INFO,
442*385cc6b4SJerry Jelinek "UtTrackAllocation: Allocation (%p) already present in global list!",
443ae115bc7Smrj Allocation));
444ae115bc7Smrj goto UnlockAndExit;
445ae115bc7Smrj }
446ae115bc7Smrj
447*385cc6b4SJerry Jelinek /* Fill in the instance data */
448ae115bc7Smrj
449ae115bc7Smrj Allocation->Size = (UINT32) Size;
450ae115bc7Smrj Allocation->AllocType = AllocType;
451ae115bc7Smrj Allocation->Component = Component;
452ae115bc7Smrj Allocation->Line = Line;
453ae115bc7Smrj
454*385cc6b4SJerry Jelinek strncpy (Allocation->Module, Module, ACPI_MAX_MODULE_NAME);
455ae115bc7Smrj Allocation->Module[ACPI_MAX_MODULE_NAME-1] = 0;
456ae115bc7Smrj
457*385cc6b4SJerry Jelinek if (!Element)
458*385cc6b4SJerry Jelinek {
459ae115bc7Smrj /* Insert at list head */
460ae115bc7Smrj
461ae115bc7Smrj if (MemList->ListHead)
462ae115bc7Smrj {
463*385cc6b4SJerry Jelinek ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous =
464*385cc6b4SJerry Jelinek Allocation;
465ae115bc7Smrj }
466ae115bc7Smrj
467ae115bc7Smrj Allocation->Next = MemList->ListHead;
468ae115bc7Smrj Allocation->Previous = NULL;
469ae115bc7Smrj
470ae115bc7Smrj MemList->ListHead = Allocation;
471*385cc6b4SJerry Jelinek }
472*385cc6b4SJerry Jelinek else
473*385cc6b4SJerry Jelinek {
474*385cc6b4SJerry Jelinek /* Insert after element */
475*385cc6b4SJerry Jelinek
476*385cc6b4SJerry Jelinek Allocation->Next = Element->Next;
477*385cc6b4SJerry Jelinek Allocation->Previous = Element;
478*385cc6b4SJerry Jelinek
479*385cc6b4SJerry Jelinek if (Element->Next)
480*385cc6b4SJerry Jelinek {
481*385cc6b4SJerry Jelinek (Element->Next)->Previous = Allocation;
482*385cc6b4SJerry Jelinek }
483*385cc6b4SJerry Jelinek
484*385cc6b4SJerry Jelinek Element->Next = Allocation;
485*385cc6b4SJerry Jelinek }
486ae115bc7Smrj
487ae115bc7Smrj
488ae115bc7Smrj UnlockAndExit:
489ae115bc7Smrj Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
490ae115bc7Smrj return_ACPI_STATUS (Status);
491ae115bc7Smrj }
492ae115bc7Smrj
493ae115bc7Smrj
494ae115bc7Smrj /*******************************************************************************
495ae115bc7Smrj *
496ae115bc7Smrj * FUNCTION: AcpiUtRemoveAllocation
497ae115bc7Smrj *
498ae115bc7Smrj * PARAMETERS: Allocation - Address of allocated memory
499ae115bc7Smrj * Component - Component type of caller
500ae115bc7Smrj * Module - Source file name of caller
501ae115bc7Smrj * Line - Line number of caller
502ae115bc7Smrj *
503*385cc6b4SJerry Jelinek * RETURN: Status
504ae115bc7Smrj *
505ae115bc7Smrj * DESCRIPTION: Deletes an element from the global allocation tracking list.
506ae115bc7Smrj *
507ae115bc7Smrj ******************************************************************************/
508ae115bc7Smrj
509ae115bc7Smrj static ACPI_STATUS
AcpiUtRemoveAllocation(ACPI_DEBUG_MEM_BLOCK * Allocation,UINT32 Component,const char * Module,UINT32 Line)510ae115bc7Smrj AcpiUtRemoveAllocation (
511ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Allocation,
512ae115bc7Smrj UINT32 Component,
513db2bae30SDana Myers const char *Module,
514ae115bc7Smrj UINT32 Line)
515ae115bc7Smrj {
516ae115bc7Smrj ACPI_MEMORY_LIST *MemList;
517ae115bc7Smrj ACPI_STATUS Status;
518ae115bc7Smrj
519ae115bc7Smrj
520*385cc6b4SJerry Jelinek ACPI_FUNCTION_NAME (UtRemoveAllocation);
521ae115bc7Smrj
522ae115bc7Smrj
52326f3cdf0SGordon Ross if (AcpiGbl_DisableMemTracking)
52426f3cdf0SGordon Ross {
525*385cc6b4SJerry Jelinek return (AE_OK);
52626f3cdf0SGordon Ross }
52726f3cdf0SGordon Ross
528ae115bc7Smrj MemList = AcpiGbl_GlobalList;
529ae115bc7Smrj if (NULL == MemList->ListHead)
530ae115bc7Smrj {
531ae115bc7Smrj /* No allocations! */
532ae115bc7Smrj
533ae115bc7Smrj ACPI_ERROR ((Module, Line,
534ae115bc7Smrj "Empty allocation list, nothing to free!"));
535ae115bc7Smrj
536*385cc6b4SJerry Jelinek return (AE_OK);
537ae115bc7Smrj }
538ae115bc7Smrj
539ae115bc7Smrj Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
540ae115bc7Smrj if (ACPI_FAILURE (Status))
541ae115bc7Smrj {
542*385cc6b4SJerry Jelinek return (Status);
543ae115bc7Smrj }
544ae115bc7Smrj
545ae115bc7Smrj /* Unlink */
546ae115bc7Smrj
547ae115bc7Smrj if (Allocation->Previous)
548ae115bc7Smrj {
549ae115bc7Smrj (Allocation->Previous)->Next = Allocation->Next;
550ae115bc7Smrj }
551ae115bc7Smrj else
552ae115bc7Smrj {
553ae115bc7Smrj MemList->ListHead = Allocation->Next;
554ae115bc7Smrj }
555ae115bc7Smrj
556ae115bc7Smrj if (Allocation->Next)
557ae115bc7Smrj {
558ae115bc7Smrj (Allocation->Next)->Previous = Allocation->Previous;
559ae115bc7Smrj }
560ae115bc7Smrj
561*385cc6b4SJerry Jelinek ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
562*385cc6b4SJerry Jelinek &Allocation->UserSpace, Allocation->Size));
563*385cc6b4SJerry Jelinek
564ae115bc7Smrj /* Mark the segment as deleted */
565ae115bc7Smrj
566*385cc6b4SJerry Jelinek memset (&Allocation->UserSpace, 0xEA, Allocation->Size);
567ae115bc7Smrj
568ae115bc7Smrj Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
569*385cc6b4SJerry Jelinek return (Status);
570ae115bc7Smrj }
571ae115bc7Smrj
572ae115bc7Smrj
573ae115bc7Smrj /*******************************************************************************
574ae115bc7Smrj *
575ae115bc7Smrj * FUNCTION: AcpiUtDumpAllocationInfo
576ae115bc7Smrj *
577*385cc6b4SJerry Jelinek * PARAMETERS: None
578ae115bc7Smrj *
579ae115bc7Smrj * RETURN: None
580ae115bc7Smrj *
581ae115bc7Smrj * DESCRIPTION: Print some info about the outstanding allocations.
582ae115bc7Smrj *
583ae115bc7Smrj ******************************************************************************/
584ae115bc7Smrj
585ae115bc7Smrj void
AcpiUtDumpAllocationInfo(void)586ae115bc7Smrj AcpiUtDumpAllocationInfo (
587ae115bc7Smrj void)
588ae115bc7Smrj {
589ae115bc7Smrj /*
590ae115bc7Smrj ACPI_MEMORY_LIST *MemList;
591ae115bc7Smrj */
592ae115bc7Smrj
593ae115bc7Smrj ACPI_FUNCTION_TRACE (UtDumpAllocationInfo);
594ae115bc7Smrj
595ae115bc7Smrj /*
596ae115bc7Smrj ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
597ae115bc7Smrj ("%30s: %4d (%3d Kb)\n", "Current allocations",
598ae115bc7Smrj MemList->CurrentCount,
599ae115bc7Smrj ROUND_UP_TO_1K (MemList->CurrentSize)));
600ae115bc7Smrj
601ae115bc7Smrj ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
602ae115bc7Smrj ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
603ae115bc7Smrj MemList->MaxConcurrentCount,
604ae115bc7Smrj ROUND_UP_TO_1K (MemList->MaxConcurrentSize)));
605ae115bc7Smrj
606ae115bc7Smrj
607ae115bc7Smrj ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
608ae115bc7Smrj ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
609ae115bc7Smrj RunningObjectCount,
610ae115bc7Smrj ROUND_UP_TO_1K (RunningObjectSize)));
611ae115bc7Smrj
612ae115bc7Smrj ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
613ae115bc7Smrj ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
614ae115bc7Smrj RunningAllocCount,
615ae115bc7Smrj ROUND_UP_TO_1K (RunningAllocSize)));
616ae115bc7Smrj
617ae115bc7Smrj
618ae115bc7Smrj ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
619ae115bc7Smrj ("%30s: %4d (%3d Kb)\n", "Current Nodes",
620ae115bc7Smrj AcpiGbl_CurrentNodeCount,
621ae115bc7Smrj ROUND_UP_TO_1K (AcpiGbl_CurrentNodeSize)));
622ae115bc7Smrj
623ae115bc7Smrj ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
624ae115bc7Smrj ("%30s: %4d (%3d Kb)\n", "Max Nodes",
625ae115bc7Smrj AcpiGbl_MaxConcurrentNodeCount,
626ae115bc7Smrj ROUND_UP_TO_1K ((AcpiGbl_MaxConcurrentNodeCount *
627ae115bc7Smrj sizeof (ACPI_NAMESPACE_NODE)))));
628ae115bc7Smrj */
629ae115bc7Smrj return_VOID;
630ae115bc7Smrj }
631ae115bc7Smrj
632ae115bc7Smrj
633ae115bc7Smrj /*******************************************************************************
634ae115bc7Smrj *
635ae115bc7Smrj * FUNCTION: AcpiUtDumpAllocations
636ae115bc7Smrj *
637ae115bc7Smrj * PARAMETERS: Component - Component(s) to dump info for.
638ae115bc7Smrj * Module - Module to dump info for. NULL means all.
639ae115bc7Smrj *
640ae115bc7Smrj * RETURN: None
641ae115bc7Smrj *
642ae115bc7Smrj * DESCRIPTION: Print a list of all outstanding allocations.
643ae115bc7Smrj *
644ae115bc7Smrj ******************************************************************************/
645ae115bc7Smrj
646ae115bc7Smrj void
AcpiUtDumpAllocations(UINT32 Component,const char * Module)647ae115bc7Smrj AcpiUtDumpAllocations (
648ae115bc7Smrj UINT32 Component,
649db2bae30SDana Myers const char *Module)
650ae115bc7Smrj {
651ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Element;
652ae115bc7Smrj ACPI_DESCRIPTOR *Descriptor;
653ae115bc7Smrj UINT32 NumOutstanding = 0;
65426f3cdf0SGordon Ross UINT8 DescriptorType;
655ae115bc7Smrj
656ae115bc7Smrj
657ae115bc7Smrj ACPI_FUNCTION_TRACE (UtDumpAllocations);
658ae115bc7Smrj
659ae115bc7Smrj
66026f3cdf0SGordon Ross if (AcpiGbl_DisableMemTracking)
66126f3cdf0SGordon Ross {
662*385cc6b4SJerry Jelinek return_VOID;
66326f3cdf0SGordon Ross }
66426f3cdf0SGordon Ross
665ae115bc7Smrj /*
666ae115bc7Smrj * Walk the allocation list.
667ae115bc7Smrj */
668ae115bc7Smrj if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY)))
669ae115bc7Smrj {
670*385cc6b4SJerry Jelinek return_VOID;
671ae115bc7Smrj }
672ae115bc7Smrj
673ae115bc7Smrj Element = AcpiGbl_GlobalList->ListHead;
674ae115bc7Smrj while (Element)
675ae115bc7Smrj {
676ae115bc7Smrj if ((Element->Component & Component) &&
677*385cc6b4SJerry Jelinek ((Module == NULL) || (0 == strcmp (Module, Element->Module))))
678ae115bc7Smrj {
679*385cc6b4SJerry Jelinek Descriptor = ACPI_CAST_PTR (
680*385cc6b4SJerry Jelinek ACPI_DESCRIPTOR, &Element->UserSpace);
68126f3cdf0SGordon Ross
68226f3cdf0SGordon Ross if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR))
68326f3cdf0SGordon Ross {
68426f3cdf0SGordon Ross AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u "
68526f3cdf0SGordon Ross "[Not a Descriptor - too small]\n",
68626f3cdf0SGordon Ross Descriptor, Element->Size, Element->Module,
68726f3cdf0SGordon Ross Element->Line);
68826f3cdf0SGordon Ross }
68926f3cdf0SGordon Ross else
69026f3cdf0SGordon Ross {
691ae115bc7Smrj /* Ignore allocated objects that are in a cache */
692ae115bc7Smrj
693*385cc6b4SJerry Jelinek if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) !=
694*385cc6b4SJerry Jelinek ACPI_DESC_TYPE_CACHED)
695ae115bc7Smrj {
69626f3cdf0SGordon Ross AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u [%s] ",
697ae115bc7Smrj Descriptor, Element->Size, Element->Module,
698ae115bc7Smrj Element->Line, AcpiUtGetDescriptorName (Descriptor));
699ae115bc7Smrj
70026f3cdf0SGordon Ross /* Validate the descriptor type using Type field and length */
70126f3cdf0SGordon Ross
70226f3cdf0SGordon Ross DescriptorType = 0; /* Not a valid descriptor type */
703ae115bc7Smrj
704ae115bc7Smrj switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor))
705ae115bc7Smrj {
706ae115bc7Smrj case ACPI_DESC_TYPE_OPERAND:
707*385cc6b4SJerry Jelinek
708*385cc6b4SJerry Jelinek if (Element->Size == sizeof (ACPI_OPERAND_OBJECT))
70926f3cdf0SGordon Ross {
71026f3cdf0SGordon Ross DescriptorType = ACPI_DESC_TYPE_OPERAND;
71126f3cdf0SGordon Ross }
712ae115bc7Smrj break;
713ae115bc7Smrj
714ae115bc7Smrj case ACPI_DESC_TYPE_PARSER:
715*385cc6b4SJerry Jelinek
716*385cc6b4SJerry Jelinek if (Element->Size == sizeof (ACPI_PARSE_OBJECT))
71726f3cdf0SGordon Ross {
71826f3cdf0SGordon Ross DescriptorType = ACPI_DESC_TYPE_PARSER;
71926f3cdf0SGordon Ross }
720ae115bc7Smrj break;
721ae115bc7Smrj
722ae115bc7Smrj case ACPI_DESC_TYPE_NAMED:
723*385cc6b4SJerry Jelinek
724*385cc6b4SJerry Jelinek if (Element->Size == sizeof (ACPI_NAMESPACE_NODE))
72526f3cdf0SGordon Ross {
72626f3cdf0SGordon Ross DescriptorType = ACPI_DESC_TYPE_NAMED;
72726f3cdf0SGordon Ross }
728ae115bc7Smrj break;
729ae115bc7Smrj
730ae115bc7Smrj default:
731*385cc6b4SJerry Jelinek
732ae115bc7Smrj break;
733ae115bc7Smrj }
734ae115bc7Smrj
73526f3cdf0SGordon Ross /* Display additional info for the major descriptor types */
73626f3cdf0SGordon Ross
73726f3cdf0SGordon Ross switch (DescriptorType)
73826f3cdf0SGordon Ross {
73926f3cdf0SGordon Ross case ACPI_DESC_TYPE_OPERAND:
740*385cc6b4SJerry Jelinek
74126f3cdf0SGordon Ross AcpiOsPrintf ("%12.12s RefCount 0x%04X\n",
74226f3cdf0SGordon Ross AcpiUtGetTypeName (Descriptor->Object.Common.Type),
74326f3cdf0SGordon Ross Descriptor->Object.Common.ReferenceCount);
74426f3cdf0SGordon Ross break;
74526f3cdf0SGordon Ross
74626f3cdf0SGordon Ross case ACPI_DESC_TYPE_PARSER:
747*385cc6b4SJerry Jelinek
74826f3cdf0SGordon Ross AcpiOsPrintf ("AmlOpcode 0x%04hX\n",
74926f3cdf0SGordon Ross Descriptor->Op.Asl.AmlOpcode);
75026f3cdf0SGordon Ross break;
75126f3cdf0SGordon Ross
75226f3cdf0SGordon Ross case ACPI_DESC_TYPE_NAMED:
753*385cc6b4SJerry Jelinek
75426f3cdf0SGordon Ross AcpiOsPrintf ("%4.4s\n",
75526f3cdf0SGordon Ross AcpiUtGetNodeName (&Descriptor->Node));
75626f3cdf0SGordon Ross break;
75726f3cdf0SGordon Ross
75826f3cdf0SGordon Ross default:
759*385cc6b4SJerry Jelinek
760ae115bc7Smrj AcpiOsPrintf ( "\n");
76126f3cdf0SGordon Ross break;
76226f3cdf0SGordon Ross }
76326f3cdf0SGordon Ross }
76426f3cdf0SGordon Ross }
76526f3cdf0SGordon Ross
766ae115bc7Smrj NumOutstanding++;
767ae115bc7Smrj }
76826f3cdf0SGordon Ross
769ae115bc7Smrj Element = Element->Next;
770ae115bc7Smrj }
771ae115bc7Smrj
772ae115bc7Smrj (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
773ae115bc7Smrj
774ae115bc7Smrj /* Print summary */
775ae115bc7Smrj
776ae115bc7Smrj if (!NumOutstanding)
777ae115bc7Smrj {
778*385cc6b4SJerry Jelinek ACPI_INFO (("No outstanding allocations"));
779ae115bc7Smrj }
780ae115bc7Smrj else
781ae115bc7Smrj {
78226f3cdf0SGordon Ross ACPI_ERROR ((AE_INFO, "%u(0x%X) Outstanding allocations",
783ae115bc7Smrj NumOutstanding, NumOutstanding));
784ae115bc7Smrj }
785ae115bc7Smrj
786ae115bc7Smrj return_VOID;
787ae115bc7Smrj }
788ae115bc7Smrj
789ae115bc7Smrj #endif /* ACPI_DBG_TRACK_ALLOCATIONS */
790