1 /******************************************************************************
2  *
3  * Module Name: uttrack - Memory allocation tracking routines (debug only)
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2023, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 /*
153  * These procedures are used for tracking memory leaks in the subsystem, and
154  * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
155  *
156  * Each memory allocation is tracked via a doubly linked list. Each
157  * element contains the caller's component, module name, function name, and
158  * line number. AcpiUtAllocate and AcpiUtAllocateZeroed call
159  * AcpiUtTrackAllocation to add an element to the list; deletion
160  * occurs in the body of AcpiUtFree.
161  */
162 
163 #include "acpi.h"
164 #include "accommon.h"
165 
166 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
167 
168 #define _COMPONENT          ACPI_UTILITIES
169         ACPI_MODULE_NAME    ("uttrack")
170 
171 
172 /* Local prototypes */
173 
174 static ACPI_DEBUG_MEM_BLOCK *
175 AcpiUtFindAllocation (
176     ACPI_DEBUG_MEM_BLOCK    *Allocation);
177 
178 static ACPI_STATUS
179 AcpiUtTrackAllocation (
180     ACPI_DEBUG_MEM_BLOCK    *Address,
181     ACPI_SIZE               Size,
182     UINT8                   AllocType,
183     UINT32                  Component,
184     const char              *Module,
185     UINT32                  Line);
186 
187 static ACPI_STATUS
188 AcpiUtRemoveAllocation (
189     ACPI_DEBUG_MEM_BLOCK    *Address,
190     UINT32                  Component,
191     const char              *Module,
192     UINT32                  Line);
193 
194 
195 /*******************************************************************************
196  *
197  * FUNCTION:    AcpiUtCreateList
198  *
199  * PARAMETERS:  CacheName       - Ascii name for the cache
200  *              ObjectSize      - Size of each cached object
201  *              ReturnCache     - Where the new cache object is returned
202  *
203  * RETURN:      Status
204  *
205  * DESCRIPTION: Create a local memory list for tracking purposed
206  *
207  ******************************************************************************/
208 
209 ACPI_STATUS
AcpiUtCreateList(const char * ListName,UINT16 ObjectSize,ACPI_MEMORY_LIST ** ReturnCache)210 AcpiUtCreateList (
211     const char              *ListName,
212     UINT16                  ObjectSize,
213     ACPI_MEMORY_LIST        **ReturnCache)
214 {
215     ACPI_MEMORY_LIST        *Cache;
216 
217 
218     Cache = AcpiOsAllocateZeroed (sizeof (ACPI_MEMORY_LIST));
219     if (!Cache)
220     {
221         return (AE_NO_MEMORY);
222     }
223 
224     Cache->ListName = ListName;
225     Cache->ObjectSize = ObjectSize;
226 
227     *ReturnCache = Cache;
228     return (AE_OK);
229 }
230 
231 
232 /*******************************************************************************
233  *
234  * FUNCTION:    AcpiUtAllocateAndTrack
235  *
236  * PARAMETERS:  Size                - Size of the allocation
237  *              Component           - Component type of caller
238  *              Module              - Source file name of caller
239  *              Line                - Line number of caller
240  *
241  * RETURN:      Address of the allocated memory on success, NULL on failure.
242  *
243  * DESCRIPTION: The subsystem's equivalent of malloc.
244  *
245  ******************************************************************************/
246 
247 void *
AcpiUtAllocateAndTrack(ACPI_SIZE Size,UINT32 Component,const char * Module,UINT32 Line)248 AcpiUtAllocateAndTrack (
249     ACPI_SIZE               Size,
250     UINT32                  Component,
251     const char              *Module,
252     UINT32                  Line)
253 {
254     ACPI_DEBUG_MEM_BLOCK    *Allocation;
255     ACPI_STATUS             Status;
256 
257 
258     /* Check for an inadvertent size of zero bytes */
259 
260     if (!Size)
261     {
262         ACPI_WARNING ((Module, Line,
263             "Attempt to allocate zero bytes, allocating 1 byte"));
264         Size = 1;
265     }
266 
267     Allocation = AcpiOsAllocate (Size + sizeof (ACPI_DEBUG_MEM_HEADER));
268     if (!Allocation)
269     {
270         /* Report allocation error */
271 
272         ACPI_WARNING ((Module, Line,
273             "Could not allocate size %u", (UINT32) Size));
274 
275         return (NULL);
276     }
277 
278     Status = AcpiUtTrackAllocation (
279         Allocation, Size, ACPI_MEM_MALLOC, Component, Module, Line);
280     if (ACPI_FAILURE (Status))
281     {
282         AcpiOsFree (Allocation);
283         return (NULL);
284     }
285 
286     AcpiGbl_GlobalList->TotalAllocated++;
287     AcpiGbl_GlobalList->TotalSize += (UINT32) Size;
288     AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
289 
290     if (AcpiGbl_GlobalList->CurrentTotalSize >
291         AcpiGbl_GlobalList->MaxOccupied)
292     {
293         AcpiGbl_GlobalList->MaxOccupied =
294             AcpiGbl_GlobalList->CurrentTotalSize;
295     }
296 
297     return ((void *) &Allocation->UserSpace);
298 }
299 
300 
301 /*******************************************************************************
302  *
303  * FUNCTION:    AcpiUtAllocateZeroedAndTrack
304  *
305  * PARAMETERS:  Size                - Size of the allocation
306  *              Component           - Component type of caller
307  *              Module              - Source file name of caller
308  *              Line                - Line number of caller
309  *
310  * RETURN:      Address of the allocated memory on success, NULL on failure.
311  *
312  * DESCRIPTION: Subsystem equivalent of calloc.
313  *
314  ******************************************************************************/
315 
316 void *
AcpiUtAllocateZeroedAndTrack(ACPI_SIZE Size,UINT32 Component,const char * Module,UINT32 Line)317 AcpiUtAllocateZeroedAndTrack (
318     ACPI_SIZE               Size,
319     UINT32                  Component,
320     const char              *Module,
321     UINT32                  Line)
322 {
323     ACPI_DEBUG_MEM_BLOCK    *Allocation;
324     ACPI_STATUS             Status;
325 
326 
327     /* Check for an inadvertent size of zero bytes */
328 
329     if (!Size)
330     {
331         ACPI_WARNING ((Module, Line,
332             "Attempt to allocate zero bytes, allocating 1 byte"));
333         Size = 1;
334     }
335 
336     Allocation = AcpiOsAllocateZeroed (
337         Size + sizeof (ACPI_DEBUG_MEM_HEADER));
338     if (!Allocation)
339     {
340         /* Report allocation error */
341 
342         ACPI_ERROR ((Module, Line,
343             "Could not allocate size %u", (UINT32) Size));
344         return (NULL);
345     }
346 
347     Status = AcpiUtTrackAllocation (Allocation, Size,
348         ACPI_MEM_CALLOC, Component, Module, Line);
349     if (ACPI_FAILURE (Status))
350     {
351         AcpiOsFree (Allocation);
352         return (NULL);
353     }
354 
355     AcpiGbl_GlobalList->TotalAllocated++;
356     AcpiGbl_GlobalList->TotalSize += (UINT32) Size;
357     AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
358 
359     if (AcpiGbl_GlobalList->CurrentTotalSize >
360         AcpiGbl_GlobalList->MaxOccupied)
361     {
362         AcpiGbl_GlobalList->MaxOccupied =
363             AcpiGbl_GlobalList->CurrentTotalSize;
364     }
365 
366     return ((void *) &Allocation->UserSpace);
367 }
368 
369 
370 /*******************************************************************************
371  *
372  * FUNCTION:    AcpiUtFreeAndTrack
373  *
374  * PARAMETERS:  Allocation          - Address of the memory to deallocate
375  *              Component           - Component type of caller
376  *              Module              - Source file name of caller
377  *              Line                - Line number of caller
378  *
379  * RETURN:      None
380  *
381  * DESCRIPTION: Frees the memory at Allocation
382  *
383  ******************************************************************************/
384 
385 void
AcpiUtFreeAndTrack(void * Allocation,UINT32 Component,const char * Module,UINT32 Line)386 AcpiUtFreeAndTrack (
387     void                    *Allocation,
388     UINT32                  Component,
389     const char              *Module,
390     UINT32                  Line)
391 {
392     ACPI_DEBUG_MEM_BLOCK    *DebugBlock;
393     ACPI_STATUS             Status;
394 
395 
396     ACPI_FUNCTION_TRACE_PTR (UtFree, Allocation);
397 
398 
399     if (NULL == Allocation)
400     {
401         ACPI_ERROR ((Module, Line,
402             "Attempt to delete a NULL address"));
403 
404         return_VOID;
405     }
406 
407     DebugBlock = ACPI_CAST_PTR (ACPI_DEBUG_MEM_BLOCK,
408         (((char *) Allocation) - sizeof (ACPI_DEBUG_MEM_HEADER)));
409 
410     AcpiGbl_GlobalList->TotalFreed++;
411     AcpiGbl_GlobalList->CurrentTotalSize -= DebugBlock->Size;
412 
413     Status = AcpiUtRemoveAllocation (DebugBlock, Component, Module, Line);
414     if (ACPI_FAILURE (Status))
415     {
416         ACPI_EXCEPTION ((AE_INFO, Status, "Could not free memory"));
417     }
418 
419     AcpiOsFree (DebugBlock);
420     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n",
421         Allocation, DebugBlock));
422     return_VOID;
423 }
424 
425 
426 /*******************************************************************************
427  *
428  * FUNCTION:    AcpiUtFindAllocation
429  *
430  * PARAMETERS:  Allocation              - Address of allocated memory
431  *
432  * RETURN:      Three cases:
433  *              1) List is empty, NULL is returned.
434  *              2) Element was found. Returns Allocation parameter.
435  *              3) Element was not found. Returns position where it should be
436  *                  inserted into the list.
437  *
438  * DESCRIPTION: Searches for an element in the global allocation tracking list.
439  *              If the element is not found, returns the location within the
440  *              list where the element should be inserted.
441  *
442  *              Note: The list is ordered by larger-to-smaller addresses.
443  *
444  *              This global list is used to detect memory leaks in ACPICA as
445  *              well as other issues such as an attempt to release the same
446  *              internal object more than once. Although expensive as far
447  *              as cpu time, this list is much more helpful for finding these
448  *              types of issues than using memory leak detectors outside of
449  *              the ACPICA code.
450  *
451  ******************************************************************************/
452 
453 static ACPI_DEBUG_MEM_BLOCK *
AcpiUtFindAllocation(ACPI_DEBUG_MEM_BLOCK * Allocation)454 AcpiUtFindAllocation (
455     ACPI_DEBUG_MEM_BLOCK    *Allocation)
456 {
457     ACPI_DEBUG_MEM_BLOCK    *Element;
458 
459 
460     Element = AcpiGbl_GlobalList->ListHead;
461     if (!Element)
462     {
463         return (NULL);
464     }
465 
466     /*
467      * Search for the address.
468      *
469      * Note: List is ordered by larger-to-smaller addresses, on the
470      * assumption that a new allocation usually has a larger address
471      * than previous allocations.
472      */
473     while (Element > Allocation)
474     {
475         /* Check for end-of-list */
476 
477         if (!Element->Next)
478         {
479             return (Element);
480         }
481 
482         Element = Element->Next;
483     }
484 
485     if (Element == Allocation)
486     {
487         return (Element);
488     }
489 
490     return (Element->Previous);
491 }
492 
493 
494 /*******************************************************************************
495  *
496  * FUNCTION:    AcpiUtTrackAllocation
497  *
498  * PARAMETERS:  Allocation          - Address of allocated memory
499  *              Size                - Size of the allocation
500  *              AllocType           - MEM_MALLOC or MEM_CALLOC
501  *              Component           - Component type of caller
502  *              Module              - Source file name of caller
503  *              Line                - Line number of caller
504  *
505  * RETURN:      Status
506  *
507  * DESCRIPTION: Inserts an element into the global allocation tracking list.
508  *
509  ******************************************************************************/
510 
511 static ACPI_STATUS
AcpiUtTrackAllocation(ACPI_DEBUG_MEM_BLOCK * Allocation,ACPI_SIZE Size,UINT8 AllocType,UINT32 Component,const char * Module,UINT32 Line)512 AcpiUtTrackAllocation (
513     ACPI_DEBUG_MEM_BLOCK    *Allocation,
514     ACPI_SIZE               Size,
515     UINT8                   AllocType,
516     UINT32                  Component,
517     const char              *Module,
518     UINT32                  Line)
519 {
520     ACPI_MEMORY_LIST        *MemList;
521     ACPI_DEBUG_MEM_BLOCK    *Element;
522     ACPI_STATUS             Status = AE_OK;
523 
524 
525     ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation);
526 
527 
528     if (AcpiGbl_DisableMemTracking)
529     {
530         return_ACPI_STATUS (AE_OK);
531     }
532 
533     MemList = AcpiGbl_GlobalList;
534     Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
535     if (ACPI_FAILURE (Status))
536     {
537         return_ACPI_STATUS (Status);
538     }
539 
540     /*
541      * Search the global list for this address to make sure it is not
542      * already present. This will catch several kinds of problems.
543      */
544     Element = AcpiUtFindAllocation (Allocation);
545     if (Element == Allocation)
546     {
547         ACPI_ERROR ((AE_INFO,
548             "UtTrackAllocation: Allocation (%p) already present in global list!",
549             Allocation));
550         goto UnlockAndExit;
551     }
552 
553     /* Fill in the instance data */
554 
555     Allocation->Size = (UINT32) Size;
556     Allocation->AllocType = AllocType;
557     Allocation->Component = Component;
558     Allocation->Line = Line;
559 
560     AcpiUtSafeStrncpy (Allocation->Module, (char *) Module, ACPI_MAX_MODULE_NAME);
561 
562     if (!Element)
563     {
564         /* Insert at list head */
565 
566         if (MemList->ListHead)
567         {
568             ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous =
569                 Allocation;
570         }
571 
572         Allocation->Next = MemList->ListHead;
573         Allocation->Previous = NULL;
574 
575         MemList->ListHead = Allocation;
576     }
577     else
578     {
579         /* Insert after element */
580 
581         Allocation->Next = Element->Next;
582         Allocation->Previous = Element;
583 
584         if (Element->Next)
585         {
586             (Element->Next)->Previous = Allocation;
587         }
588 
589         Element->Next = Allocation;
590     }
591 
592 
593 UnlockAndExit:
594     Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
595     return_ACPI_STATUS (Status);
596 }
597 
598 
599 /*******************************************************************************
600  *
601  * FUNCTION:    AcpiUtRemoveAllocation
602  *
603  * PARAMETERS:  Allocation          - Address of allocated memory
604  *              Component           - Component type of caller
605  *              Module              - Source file name of caller
606  *              Line                - Line number of caller
607  *
608  * RETURN:      Status
609  *
610  * DESCRIPTION: Deletes an element from the global allocation tracking list.
611  *
612  ******************************************************************************/
613 
614 static ACPI_STATUS
AcpiUtRemoveAllocation(ACPI_DEBUG_MEM_BLOCK * Allocation,UINT32 Component,const char * Module,UINT32 Line)615 AcpiUtRemoveAllocation (
616     ACPI_DEBUG_MEM_BLOCK    *Allocation,
617     UINT32                  Component,
618     const char              *Module,
619     UINT32                  Line)
620 {
621     ACPI_MEMORY_LIST        *MemList;
622     ACPI_STATUS             Status;
623 
624 
625     ACPI_FUNCTION_NAME (UtRemoveAllocation);
626 
627 
628     if (AcpiGbl_DisableMemTracking)
629     {
630         return (AE_OK);
631     }
632 
633     MemList = AcpiGbl_GlobalList;
634     if (NULL == MemList->ListHead)
635     {
636         /* No allocations! */
637 
638         ACPI_ERROR ((Module, Line,
639             "Empty allocation list, nothing to free!"));
640 
641         return (AE_OK);
642     }
643 
644     Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
645     if (ACPI_FAILURE (Status))
646     {
647         return (Status);
648     }
649 
650     /* Unlink */
651 
652     if (Allocation->Previous)
653     {
654         (Allocation->Previous)->Next = Allocation->Next;
655     }
656     else
657     {
658         MemList->ListHead = Allocation->Next;
659     }
660 
661     if (Allocation->Next)
662     {
663         (Allocation->Next)->Previous = Allocation->Previous;
664     }
665 
666     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
667         &Allocation->UserSpace, Allocation->Size));
668 
669     /* Mark the segment as deleted */
670 
671     memset (&Allocation->UserSpace, 0xEA, Allocation->Size);
672 
673     Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
674     return (Status);
675 }
676 
677 
678 /*******************************************************************************
679  *
680  * FUNCTION:    AcpiUtDumpAllocationInfo
681  *
682  * PARAMETERS:  None
683  *
684  * RETURN:      None
685  *
686  * DESCRIPTION: Print some info about the outstanding allocations.
687  *
688  ******************************************************************************/
689 
690 void
AcpiUtDumpAllocationInfo(void)691 AcpiUtDumpAllocationInfo (
692     void)
693 {
694 /*
695     ACPI_MEMORY_LIST        *MemList;
696 */
697 
698     ACPI_FUNCTION_TRACE (UtDumpAllocationInfo);
699 
700 /*
701     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
702         ("%30s: %4d (%3d Kb)\n", "Current allocations",
703         MemList->CurrentCount,
704         ROUND_UP_TO_1K (MemList->CurrentSize)));
705 
706     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
707         ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
708         MemList->MaxConcurrentCount,
709         ROUND_UP_TO_1K (MemList->MaxConcurrentSize)));
710 
711 
712     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
713         ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
714         RunningObjectCount,
715         ROUND_UP_TO_1K (RunningObjectSize)));
716 
717     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
718         ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
719         RunningAllocCount,
720         ROUND_UP_TO_1K (RunningAllocSize)));
721 
722 
723     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
724         ("%30s: %4d (%3d Kb)\n", "Current Nodes",
725         AcpiGbl_CurrentNodeCount,
726         ROUND_UP_TO_1K (AcpiGbl_CurrentNodeSize)));
727 
728     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
729         ("%30s: %4d (%3d Kb)\n", "Max Nodes",
730         AcpiGbl_MaxConcurrentNodeCount,
731         ROUND_UP_TO_1K ((AcpiGbl_MaxConcurrentNodeCount *
732             sizeof (ACPI_NAMESPACE_NODE)))));
733 */
734     return_VOID;
735 }
736 
737 
738 /*******************************************************************************
739  *
740  * FUNCTION:    AcpiUtDumpAllocations
741  *
742  * PARAMETERS:  Component           - Component(s) to dump info for.
743  *              Module              - Module to dump info for. NULL means all.
744  *
745  * RETURN:      None
746  *
747  * DESCRIPTION: Print a list of all outstanding allocations.
748  *
749  ******************************************************************************/
750 
751 void
AcpiUtDumpAllocations(UINT32 Component,const char * Module)752 AcpiUtDumpAllocations (
753     UINT32                  Component,
754     const char              *Module)
755 {
756     ACPI_DEBUG_MEM_BLOCK    *Element;
757     ACPI_DESCRIPTOR         *Descriptor;
758     UINT32                  NumOutstanding = 0;
759     UINT8                   DescriptorType;
760 
761 
762     ACPI_FUNCTION_TRACE (UtDumpAllocations);
763 
764 
765     if (AcpiGbl_DisableMemTracking)
766     {
767         return_VOID;
768     }
769 
770     /*
771      * Walk the allocation list.
772      */
773     if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY)))
774     {
775         return_VOID;
776     }
777 
778     if (!AcpiGbl_GlobalList)
779     {
780         goto Exit;
781     }
782 
783     Element = AcpiGbl_GlobalList->ListHead;
784     while (Element)
785     {
786         if ((Element->Component & Component) &&
787             ((Module == NULL) || (0 == strcmp (Module, Element->Module))))
788         {
789             Descriptor = ACPI_CAST_PTR (
790                 ACPI_DESCRIPTOR, &Element->UserSpace);
791 
792             if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR))
793             {
794                 AcpiOsPrintf ("%p Length 0x%04X %9.9s-%4.4u "
795                     "[Not a Descriptor - too small]\n",
796                     Descriptor, Element->Size, Element->Module,
797                     Element->Line);
798             }
799             else
800             {
801                 /* Ignore allocated objects that are in a cache */
802 
803                 if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) !=
804                     ACPI_DESC_TYPE_CACHED)
805                 {
806                     AcpiOsPrintf ("%p Length 0x%04X %9.9s-%4.4u [%s] ",
807                         Descriptor, Element->Size, Element->Module,
808                         Element->Line, AcpiUtGetDescriptorName (Descriptor));
809 
810                     /* Optional object hex dump */
811 
812                     if (AcpiGbl_VerboseLeakDump)
813                     {
814                         AcpiOsPrintf ("\n");
815                         AcpiUtDumpBuffer ((UINT8 *) Descriptor, Element->Size,
816                             DB_BYTE_DISPLAY, 0);
817                     }
818 
819                     /* Validate the descriptor type using Type field and length */
820 
821                     DescriptorType = 0; /* Not a valid descriptor type */
822 
823                     switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor))
824                     {
825                     case ACPI_DESC_TYPE_OPERAND:
826 
827                         if (Element->Size == sizeof (ACPI_OPERAND_OBJECT))
828                         {
829                             DescriptorType = ACPI_DESC_TYPE_OPERAND;
830                         }
831                         break;
832 
833                     case ACPI_DESC_TYPE_PARSER:
834 
835                         if (Element->Size == sizeof (ACPI_PARSE_OBJECT))
836                         {
837                             DescriptorType = ACPI_DESC_TYPE_PARSER;
838                         }
839                         break;
840 
841                     case ACPI_DESC_TYPE_NAMED:
842 
843                         if (Element->Size == sizeof (ACPI_NAMESPACE_NODE))
844                         {
845                             DescriptorType = ACPI_DESC_TYPE_NAMED;
846                         }
847                         break;
848 
849                     default:
850 
851                         break;
852                     }
853 
854                     /* Display additional info for the major descriptor types */
855 
856                     switch (DescriptorType)
857                     {
858                     case ACPI_DESC_TYPE_OPERAND:
859 
860                         AcpiOsPrintf ("%12.12s  RefCount 0x%04X\n",
861                             AcpiUtGetTypeName (Descriptor->Object.Common.Type),
862                             Descriptor->Object.Common.ReferenceCount);
863                         break;
864 
865                     case ACPI_DESC_TYPE_PARSER:
866 
867                         AcpiOsPrintf ("AmlOpcode 0x%04X\n",
868                             Descriptor->Op.Asl.AmlOpcode);
869                         break;
870 
871                     case ACPI_DESC_TYPE_NAMED:
872 
873                         AcpiOsPrintf ("%4.4s\n",
874                             AcpiUtGetNodeName (&Descriptor->Node));
875                         break;
876 
877                     default:
878 
879                         AcpiOsPrintf ( "\n");
880                         break;
881                     }
882                 }
883             }
884 
885             NumOutstanding++;
886         }
887 
888         Element = Element->Next;
889     }
890 
891 Exit:
892     (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
893 
894     /* Print summary */
895 
896     if (!NumOutstanding)
897     {
898         ACPI_INFO (("No outstanding allocations"));
899     }
900     else
901     {
902         ACPI_ERROR ((AE_INFO, "%u (0x%X) Outstanding cache allocations",
903             NumOutstanding, NumOutstanding));
904     }
905 
906     return_VOID;
907 }
908 
909 #endif  /* ACPI_DBG_TRACK_ALLOCATIONS */
910