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