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