1 /******************************************************************************
   2  *
   3  * Module Name: uttrack - Memory allocation tracking routines (debug only)
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 (block %p)\n",
 311         Allocation, DebugBlock));
 312     return_VOID;
 313 }
 314 
 315 
 316 /*******************************************************************************
 317  *
 318  * FUNCTION:    AcpiUtFindAllocation
 319  *
 320  * PARAMETERS:  Allocation              - Address of allocated memory
 321  *
 322  * RETURN:      Three cases:
 323  *              1) List is empty, NULL is returned.
 324  *              2) Element was found. Returns Allocation parameter.
 325  *              3) Element was not found. Returns position where it should be
 326  *                  inserted into the list.
 327  *
 328  * DESCRIPTION: Searches for an element in the global allocation tracking list.
 329  *              If the element is not found, returns the location within the
 330  *              list where the element should be inserted.
 331  *
 332  *              Note: The list is ordered by larger-to-smaller addresses.
 333  *
 334  *              This global list is used to detect memory leaks in ACPICA as
 335  *              well as other issues such as an attempt to release the same
 336  *              internal object more than once. Although expensive as far
 337  *              as cpu time, this list is much more helpful for finding these
 338  *              types of issues than using memory leak detectors outside of
 339  *              the ACPICA code.
 340  *
 341  ******************************************************************************/
 342 
 343 static ACPI_DEBUG_MEM_BLOCK *
 344 AcpiUtFindAllocation (
 345     ACPI_DEBUG_MEM_BLOCK    *Allocation)
 346 {
 347     ACPI_DEBUG_MEM_BLOCK    *Element;
 348 
 349 
 350     Element = AcpiGbl_GlobalList->ListHead;
 351     if (!Element)
 352     {
 353         return (NULL);
 354     }
 355 
 356     /*
 357      * Search for the address.
 358      *
 359      * Note: List is ordered by larger-to-smaller addresses, on the
 360      * assumption that a new allocation usually has a larger address
 361      * than previous allocations.
 362      */
 363     while (Element > Allocation)
 364     {
 365         /* Check for end-of-list */
 366 
 367         if (!Element->Next)
 368         {
 369             return (Element);
 370         }
 371 
 372         Element = Element->Next;
 373     }
 374 
 375     if (Element == Allocation)
 376     {
 377         return (Element);
 378     }
 379 
 380     return (Element->Previous);
 381 }
 382 
 383 
 384 /*******************************************************************************
 385  *
 386  * FUNCTION:    AcpiUtTrackAllocation
 387  *
 388  * PARAMETERS:  Allocation          - Address of allocated memory
 389  *              Size                - Size of the allocation
 390  *              AllocType           - MEM_MALLOC or MEM_CALLOC
 391  *              Component           - Component type of caller
 392  *              Module              - Source file name of caller
 393  *              Line                - Line number of caller
 394  *
 395  * RETURN:      Status
 396  *
 397  * DESCRIPTION: Inserts an element into the global allocation tracking list.
 398  *
 399  ******************************************************************************/
 400 
 401 static ACPI_STATUS
 402 AcpiUtTrackAllocation (
 403     ACPI_DEBUG_MEM_BLOCK    *Allocation,
 404     ACPI_SIZE               Size,
 405     UINT8                   AllocType,
 406     UINT32                  Component,
 407     const char              *Module,
 408     UINT32                  Line)
 409 {
 410     ACPI_MEMORY_LIST        *MemList;
 411     ACPI_DEBUG_MEM_BLOCK    *Element;
 412     ACPI_STATUS             Status = AE_OK;
 413 
 414 
 415     ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation);
 416 
 417 
 418     if (AcpiGbl_DisableMemTracking)
 419     {
 420         return_ACPI_STATUS (AE_OK);
 421     }
 422 
 423     MemList = AcpiGbl_GlobalList;
 424     Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
 425     if (ACPI_FAILURE (Status))
 426     {
 427         return_ACPI_STATUS (Status);
 428     }
 429 
 430     /*
 431      * Search the global list for this address to make sure it is not
 432      * already present. This will catch several kinds of problems.
 433      */
 434     Element = AcpiUtFindAllocation (Allocation);
 435     if (Element == Allocation)
 436     {
 437         ACPI_ERROR ((AE_INFO,
 438             "UtTrackAllocation: Allocation (%p) already present in global list!",
 439             Allocation));
 440         goto UnlockAndExit;
 441     }
 442 
 443     /* Fill in the instance data */
 444 
 445     Allocation->Size      = (UINT32) Size;
 446     Allocation->AllocType = AllocType;
 447     Allocation->Component = Component;
 448     Allocation->Line      = Line;
 449 
 450     ACPI_STRNCPY (Allocation->Module, Module, ACPI_MAX_MODULE_NAME);
 451     Allocation->Module[ACPI_MAX_MODULE_NAME-1] = 0;
 452 
 453     if (!Element)
 454     {
 455         /* Insert at list head */
 456 
 457         if (MemList->ListHead)
 458         {
 459             ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous = Allocation;
 460         }
 461 
 462         Allocation->Next = MemList->ListHead;
 463         Allocation->Previous = NULL;
 464 
 465         MemList->ListHead = Allocation;
 466     }
 467     else
 468     {
 469         /* Insert after element */
 470 
 471         Allocation->Next = Element->Next;
 472         Allocation->Previous = Element;
 473 
 474         if (Element->Next)
 475         {
 476             (Element->Next)->Previous = Allocation;
 477         }
 478 
 479         Element->Next = Allocation;
 480     }
 481 
 482 
 483 UnlockAndExit:
 484     Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
 485     return_ACPI_STATUS (Status);
 486 }
 487 
 488 
 489 /*******************************************************************************
 490  *
 491  * FUNCTION:    AcpiUtRemoveAllocation
 492  *
 493  * PARAMETERS:  Allocation          - Address of allocated memory
 494  *              Component           - Component type of caller
 495  *              Module              - Source file name of caller
 496  *              Line                - Line number of caller
 497  *
 498  * RETURN:      Status
 499  *
 500  * DESCRIPTION: Deletes an element from the global allocation tracking list.
 501  *
 502  ******************************************************************************/
 503 
 504 static ACPI_STATUS
 505 AcpiUtRemoveAllocation (
 506     ACPI_DEBUG_MEM_BLOCK    *Allocation,
 507     UINT32                  Component,
 508     const char              *Module,
 509     UINT32                  Line)
 510 {
 511     ACPI_MEMORY_LIST        *MemList;
 512     ACPI_STATUS             Status;
 513 
 514 
 515     ACPI_FUNCTION_NAME (UtRemoveAllocation);
 516 
 517 
 518     if (AcpiGbl_DisableMemTracking)
 519     {
 520         return (AE_OK);
 521     }
 522 
 523     MemList = AcpiGbl_GlobalList;
 524     if (NULL == MemList->ListHead)
 525     {
 526         /* No allocations! */
 527 
 528         ACPI_ERROR ((Module, Line,
 529             "Empty allocation list, nothing to free!"));
 530 
 531         return (AE_OK);
 532     }
 533 
 534     Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
 535     if (ACPI_FAILURE (Status))
 536     {
 537         return (Status);
 538     }
 539 
 540     /* Unlink */
 541 
 542     if (Allocation->Previous)
 543     {
 544         (Allocation->Previous)->Next = Allocation->Next;
 545     }
 546     else
 547     {
 548         MemList->ListHead = Allocation->Next;
 549     }
 550 
 551     if (Allocation->Next)
 552     {
 553         (Allocation->Next)->Previous = Allocation->Previous;
 554     }
 555 
 556     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
 557         &Allocation->UserSpace, Allocation->Size));
 558 
 559     /* Mark the segment as deleted */
 560 
 561     ACPI_MEMSET (&Allocation->UserSpace, 0xEA, Allocation->Size);
 562 
 563     Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
 564     return (Status);
 565 }
 566 
 567 
 568 /*******************************************************************************
 569  *
 570  * FUNCTION:    AcpiUtDumpAllocationInfo
 571  *
 572  * PARAMETERS:  None
 573  *
 574  * RETURN:      None
 575  *
 576  * DESCRIPTION: Print some info about the outstanding allocations.
 577  *
 578  ******************************************************************************/
 579 
 580 void
 581 AcpiUtDumpAllocationInfo (
 582     void)
 583 {
 584 /*
 585     ACPI_MEMORY_LIST        *MemList;
 586 */
 587 
 588     ACPI_FUNCTION_TRACE (UtDumpAllocationInfo);
 589 
 590 /*
 591     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
 592                     ("%30s: %4d (%3d Kb)\n", "Current allocations",
 593                     MemList->CurrentCount,
 594                     ROUND_UP_TO_1K (MemList->CurrentSize)));
 595 
 596     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
 597                     ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
 598                     MemList->MaxConcurrentCount,
 599                     ROUND_UP_TO_1K (MemList->MaxConcurrentSize)));
 600 
 601 
 602     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
 603                     ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
 604                     RunningObjectCount,
 605                     ROUND_UP_TO_1K (RunningObjectSize)));
 606 
 607     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
 608                     ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
 609                     RunningAllocCount,
 610                     ROUND_UP_TO_1K (RunningAllocSize)));
 611 
 612 
 613     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
 614                     ("%30s: %4d (%3d Kb)\n", "Current Nodes",
 615                     AcpiGbl_CurrentNodeCount,
 616                     ROUND_UP_TO_1K (AcpiGbl_CurrentNodeSize)));
 617 
 618     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
 619                     ("%30s: %4d (%3d Kb)\n", "Max Nodes",
 620                     AcpiGbl_MaxConcurrentNodeCount,
 621                     ROUND_UP_TO_1K ((AcpiGbl_MaxConcurrentNodeCount *
 622                         sizeof (ACPI_NAMESPACE_NODE)))));
 623 */
 624     return_VOID;
 625 }
 626 
 627 
 628 /*******************************************************************************
 629  *
 630  * FUNCTION:    AcpiUtDumpAllocations
 631  *
 632  * PARAMETERS:  Component           - Component(s) to dump info for.
 633  *              Module              - Module to dump info for. NULL means all.
 634  *
 635  * RETURN:      None
 636  *
 637  * DESCRIPTION: Print a list of all outstanding allocations.
 638  *
 639  ******************************************************************************/
 640 
 641 void
 642 AcpiUtDumpAllocations (
 643     UINT32                  Component,
 644     const char              *Module)
 645 {
 646     ACPI_DEBUG_MEM_BLOCK    *Element;
 647     ACPI_DESCRIPTOR         *Descriptor;
 648     UINT32                  NumOutstanding = 0;
 649     UINT8                   DescriptorType;
 650 
 651 
 652     ACPI_FUNCTION_TRACE (UtDumpAllocations);
 653 
 654 
 655     if (AcpiGbl_DisableMemTracking)
 656     {
 657         return_VOID;
 658     }
 659 
 660     /*
 661      * Walk the allocation list.
 662      */
 663     if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY)))
 664     {
 665         return_VOID;
 666     }
 667 
 668     Element = AcpiGbl_GlobalList->ListHead;
 669     while (Element)
 670     {
 671         if ((Element->Component & Component) &&
 672             ((Module == NULL) || (0 == ACPI_STRCMP (Module, Element->Module))))
 673         {
 674             Descriptor = ACPI_CAST_PTR (ACPI_DESCRIPTOR, &Element->UserSpace);
 675 
 676             if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR))
 677             {
 678                 AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u "
 679                     "[Not a Descriptor - too small]\n",
 680                     Descriptor, Element->Size, Element->Module,
 681                     Element->Line);
 682             }
 683             else
 684             {
 685                 /* Ignore allocated objects that are in a cache */
 686 
 687                 if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != ACPI_DESC_TYPE_CACHED)
 688                 {
 689                     AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u [%s] ",
 690                         Descriptor, Element->Size, Element->Module,
 691                         Element->Line, AcpiUtGetDescriptorName (Descriptor));
 692 
 693                     /* Validate the descriptor type using Type field and length */
 694 
 695                     DescriptorType = 0; /* Not a valid descriptor type */
 696 
 697                     switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor))
 698                     {
 699                     case ACPI_DESC_TYPE_OPERAND:
 700 
 701                         if (Element->Size == sizeof (ACPI_OPERAND_OBJECT))
 702                         {
 703                             DescriptorType = ACPI_DESC_TYPE_OPERAND;
 704                         }
 705                         break;
 706 
 707                     case ACPI_DESC_TYPE_PARSER:
 708 
 709                         if (Element->Size == sizeof (ACPI_PARSE_OBJECT))
 710                         {
 711                             DescriptorType = ACPI_DESC_TYPE_PARSER;
 712                         }
 713                         break;
 714 
 715                     case ACPI_DESC_TYPE_NAMED:
 716 
 717                         if (Element->Size == sizeof (ACPI_NAMESPACE_NODE))
 718                         {
 719                             DescriptorType = ACPI_DESC_TYPE_NAMED;
 720                         }
 721                         break;
 722 
 723                     default:
 724 
 725                         break;
 726                     }
 727 
 728                     /* Display additional info for the major descriptor types */
 729 
 730                     switch (DescriptorType)
 731                     {
 732                     case ACPI_DESC_TYPE_OPERAND:
 733 
 734                         AcpiOsPrintf ("%12.12s  RefCount 0x%04X\n",
 735                             AcpiUtGetTypeName (Descriptor->Object.Common.Type),
 736                             Descriptor->Object.Common.ReferenceCount);
 737                         break;
 738 
 739                     case ACPI_DESC_TYPE_PARSER:
 740 
 741                         AcpiOsPrintf ("AmlOpcode 0x%04hX\n",
 742                             Descriptor->Op.Asl.AmlOpcode);
 743                         break;
 744 
 745                     case ACPI_DESC_TYPE_NAMED:
 746 
 747                         AcpiOsPrintf ("%4.4s\n",
 748                             AcpiUtGetNodeName (&Descriptor->Node));
 749                         break;
 750 
 751                     default:
 752 
 753                         AcpiOsPrintf ( "\n");
 754                         break;
 755                     }
 756                 }
 757             }
 758 
 759             NumOutstanding++;
 760         }
 761 
 762         Element = Element->Next;
 763     }
 764 
 765     (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
 766 
 767     /* Print summary */
 768 
 769     if (!NumOutstanding)
 770     {
 771         ACPI_INFO ((AE_INFO, "No outstanding allocations"));
 772     }
 773     else
 774     {
 775         ACPI_ERROR ((AE_INFO, "%u(0x%X) Outstanding allocations",
 776             NumOutstanding, NumOutstanding));
 777     }
 778 
 779     return_VOID;
 780 }
 781 
 782 #endif  /* ACPI_DBG_TRACK_ALLOCATIONS */