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