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