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 - 2017, 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
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 *
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 *
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
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 *
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
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     strncpy (Allocation->Module, Module, ACPI_MAX_MODULE_NAME);
561     Allocation->Module[ACPI_MAX_MODULE_NAME-1] = 0;
562 
563     if (!Element)
564     {
565         /* Insert at list head */
566 
567         if (MemList->ListHead)
568         {
569             ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous =
570                 Allocation;
571         }
572 
573         Allocation->Next = MemList->ListHead;
574         Allocation->Previous = NULL;
575 
576         MemList->ListHead = Allocation;
577     }
578     else
579     {
580         /* Insert after element */
581 
582         Allocation->Next = Element->Next;
583         Allocation->Previous = Element;
584 
585         if (Element->Next)
586         {
587             (Element->Next)->Previous = Allocation;
588         }
589 
590         Element->Next = Allocation;
591     }
592 
593 
594 UnlockAndExit:
595     Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
596     return_ACPI_STATUS (Status);
597 }
598 
599 
600 /*******************************************************************************
601  *
602  * FUNCTION:    AcpiUtRemoveAllocation
603  *
604  * PARAMETERS:  Allocation          - Address of allocated memory
605  *              Component           - Component type of caller
606  *              Module              - Source file name of caller
607  *              Line                - Line number of caller
608  *
609  * RETURN:      Status
610  *
611  * DESCRIPTION: Deletes an element from the global allocation tracking list.
612  *
613  ******************************************************************************/
614 
615 static ACPI_STATUS
616 AcpiUtRemoveAllocation (
617     ACPI_DEBUG_MEM_BLOCK    *Allocation,
618     UINT32                  Component,
619     const char              *Module,
620     UINT32                  Line)
621 {
622     ACPI_MEMORY_LIST        *MemList;
623     ACPI_STATUS             Status;
624 
625 
626     ACPI_FUNCTION_NAME (UtRemoveAllocation);
627 
628 
629     if (AcpiGbl_DisableMemTracking)
630     {
631         return (AE_OK);
632     }
633 
634     MemList = AcpiGbl_GlobalList;
635     if (NULL == MemList->ListHead)
636     {
637         /* No allocations! */
638 
639         ACPI_ERROR ((Module, Line,
640             "Empty allocation list, nothing to free!"));
641 
642         return (AE_OK);
643     }
644 
645     Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
646     if (ACPI_FAILURE (Status))
647     {
648         return (Status);
649     }
650 
651     /* Unlink */
652 
653     if (Allocation->Previous)
654     {
655         (Allocation->Previous)->Next = Allocation->Next;
656     }
657     else
658     {
659         MemList->ListHead = Allocation->Next;
660     }
661 
662     if (Allocation->Next)
663     {
664         (Allocation->Next)->Previous = Allocation->Previous;
665     }
666 
667     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
668         &Allocation->UserSpace, Allocation->Size));
669 
670     /* Mark the segment as deleted */
671 
672     memset (&Allocation->UserSpace, 0xEA, Allocation->Size);
673 
674     Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
675     return (Status);
676 }
677 
678 
679 /*******************************************************************************
680  *
681  * FUNCTION:    AcpiUtDumpAllocationInfo
682  *
683  * PARAMETERS:  None
684  *
685  * RETURN:      None
686  *
687  * DESCRIPTION: Print some info about the outstanding allocations.
688  *
689  ******************************************************************************/
690 
691 void
692 AcpiUtDumpAllocationInfo (
693     void)
694 {
695 /*
696     ACPI_MEMORY_LIST        *MemList;
697 */
698 
699     ACPI_FUNCTION_TRACE (UtDumpAllocationInfo);
700 
701 /*
702     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
703         ("%30s: %4d (%3d Kb)\n", "Current allocations",
704         MemList->CurrentCount,
705         ROUND_UP_TO_1K (MemList->CurrentSize)));
706 
707     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
708         ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
709         MemList->MaxConcurrentCount,
710         ROUND_UP_TO_1K (MemList->MaxConcurrentSize)));
711 
712 
713     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
714         ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
715         RunningObjectCount,
716         ROUND_UP_TO_1K (RunningObjectSize)));
717 
718     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
719         ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
720         RunningAllocCount,
721         ROUND_UP_TO_1K (RunningAllocSize)));
722 
723 
724     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
725         ("%30s: %4d (%3d Kb)\n", "Current Nodes",
726         AcpiGbl_CurrentNodeCount,
727         ROUND_UP_TO_1K (AcpiGbl_CurrentNodeSize)));
728 
729     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
730         ("%30s: %4d (%3d Kb)\n", "Max Nodes",
731         AcpiGbl_MaxConcurrentNodeCount,
732         ROUND_UP_TO_1K ((AcpiGbl_MaxConcurrentNodeCount *
733             sizeof (ACPI_NAMESPACE_NODE)))));
734 */
735     return_VOID;
736 }
737 
738 
739 /*******************************************************************************
740  *
741  * FUNCTION:    AcpiUtDumpAllocations
742  *
743  * PARAMETERS:  Component           - Component(s) to dump info for.
744  *              Module              - Module to dump info for. NULL means all.
745  *
746  * RETURN:      None
747  *
748  * DESCRIPTION: Print a list of all outstanding allocations.
749  *
750  ******************************************************************************/
751 
752 void
753 AcpiUtDumpAllocations (
754     UINT32                  Component,
755     const char              *Module)
756 {
757     ACPI_DEBUG_MEM_BLOCK    *Element;
758     ACPI_DESCRIPTOR         *Descriptor;
759     UINT32                  NumOutstanding = 0;
760     UINT8                   DescriptorType;
761 
762 
763     ACPI_FUNCTION_TRACE (UtDumpAllocations);
764 
765 
766     if (AcpiGbl_DisableMemTracking)
767     {
768         return_VOID;
769     }
770 
771     /*
772      * Walk the allocation list.
773      */
774     if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY)))
775     {
776         return_VOID;
777     }
778 
779     if (!AcpiGbl_GlobalList)
780     {
781         goto Exit;
782     }
783 
784     Element = AcpiGbl_GlobalList->ListHead;
785     while (Element)
786     {
787         if ((Element->Component & Component) &&
788             ((Module == NULL) || (0 == strcmp (Module, Element->Module))))
789         {
790             Descriptor = ACPI_CAST_PTR (
791                 ACPI_DESCRIPTOR, &Element->UserSpace);
792 
793             if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR))
794             {
795                 AcpiOsPrintf ("%p Length 0x%04X %9.9s-%4.4u "
796                     "[Not a Descriptor - too small]\n",
797                     Descriptor, Element->Size, Element->Module,
798                     Element->Line);
799             }
800             else
801             {
802                 /* Ignore allocated objects that are in a cache */
803 
804                 if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) !=
805                     ACPI_DESC_TYPE_CACHED)
806                 {
807                     AcpiOsPrintf ("%p Length 0x%04X %9.9s-%4.4u [%s] ",
808                         Descriptor, Element->Size, Element->Module,
809                         Element->Line, AcpiUtGetDescriptorName (Descriptor));
810 
811                     /* Validate the descriptor type using Type field and length */
812 
813                     DescriptorType = 0; /* Not a valid descriptor type */
814 
815                     switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor))
816                     {
817                     case ACPI_DESC_TYPE_OPERAND:
818 
819                         if (Element->Size == sizeof (ACPI_OPERAND_OBJECT))
820                         {
821                             DescriptorType = ACPI_DESC_TYPE_OPERAND;
822                         }
823                         break;
824 
825                     case ACPI_DESC_TYPE_PARSER:
826 
827                         if (Element->Size == sizeof (ACPI_PARSE_OBJECT))
828                         {
829                             DescriptorType = ACPI_DESC_TYPE_PARSER;
830                         }
831                         break;
832 
833                     case ACPI_DESC_TYPE_NAMED:
834 
835                         if (Element->Size == sizeof (ACPI_NAMESPACE_NODE))
836                         {
837                             DescriptorType = ACPI_DESC_TYPE_NAMED;
838                         }
839                         break;
840 
841                     default:
842 
843                         break;
844                     }
845 
846                     /* Display additional info for the major descriptor types */
847 
848                     switch (DescriptorType)
849                     {
850                     case ACPI_DESC_TYPE_OPERAND:
851 
852                         AcpiOsPrintf ("%12.12s  RefCount 0x%04X\n",
853                             AcpiUtGetTypeName (Descriptor->Object.Common.Type),
854                             Descriptor->Object.Common.ReferenceCount);
855                         break;
856 
857                     case ACPI_DESC_TYPE_PARSER:
858 
859                         AcpiOsPrintf ("AmlOpcode 0x%04hX\n",
860                             Descriptor->Op.Asl.AmlOpcode);
861                         break;
862 
863                     case ACPI_DESC_TYPE_NAMED:
864 
865                         AcpiOsPrintf ("%4.4s\n",
866                             AcpiUtGetNodeName (&Descriptor->Node));
867                         break;
868 
869                     default:
870 
871                         AcpiOsPrintf ( "\n");
872                         break;
873                     }
874                 }
875             }
876 
877             NumOutstanding++;
878         }
879 
880         Element = Element->Next;
881     }
882 
883 Exit:
884     (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
885 
886     /* Print summary */
887 
888     if (!NumOutstanding)
889     {
890         ACPI_INFO (("No outstanding allocations"));
891     }
892     else
893     {
894         ACPI_ERROR ((AE_INFO, "%u(0x%X) Outstanding allocations",
895             NumOutstanding, NumOutstanding));
896     }
897 
898     return_VOID;
899 }
900 
901 #endif  /* ACPI_DBG_TRACK_ALLOCATIONS */
902