Print this page
update to acpica-unix2-20130927
acpica-unix2-20130823
PANKOVs restructure
   1 /******************************************************************************
   2  *
   3  * Module Name: uttrack - Memory allocation tracking routines (debug only)
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2011, 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.


  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 /* Local prototypes */
  66 
  67 static ACPI_DEBUG_MEM_BLOCK *
  68 AcpiUtFindAllocation (
  69     void                    *Allocation);
  70 
  71 static ACPI_STATUS
  72 AcpiUtTrackAllocation (
  73     ACPI_DEBUG_MEM_BLOCK    *Address,
  74     ACPI_SIZE               Size,
  75     UINT8                   AllocType,
  76     UINT32                  Component,
  77     const char              *Module,
  78     UINT32                  Line);
  79 
  80 static ACPI_STATUS
  81 AcpiUtRemoveAllocation (
  82     ACPI_DEBUG_MEM_BLOCK    *Address,
  83     UINT32                  Component,
  84     const char              *Module,
  85     UINT32                  Line);
  86 
  87 
  88 /*******************************************************************************
  89  *


 133  *              Module              - Source file name of caller
 134  *              Line                - Line number of caller
 135  *
 136  * RETURN:      Address of the allocated memory on success, NULL on failure.
 137  *
 138  * DESCRIPTION: The subsystem's equivalent of malloc.
 139  *
 140  ******************************************************************************/
 141 
 142 void *
 143 AcpiUtAllocateAndTrack (
 144     ACPI_SIZE               Size,
 145     UINT32                  Component,
 146     const char              *Module,
 147     UINT32                  Line)
 148 {
 149     ACPI_DEBUG_MEM_BLOCK    *Allocation;
 150     ACPI_STATUS             Status;
 151 
 152 
 153     Allocation = AcpiUtAllocate (Size + sizeof (ACPI_DEBUG_MEM_HEADER),
 154                     Component, Module, Line);








 155     if (!Allocation)
 156     {





 157         return (NULL);
 158     }
 159 
 160     Status = AcpiUtTrackAllocation (Allocation, Size,
 161                     ACPI_MEM_MALLOC, Component, Module, Line);
 162     if (ACPI_FAILURE (Status))
 163     {
 164         AcpiOsFree (Allocation);
 165         return (NULL);
 166     }
 167 
 168     AcpiGbl_GlobalList->TotalAllocated++;
 169     AcpiGbl_GlobalList->TotalSize += (UINT32) Size;
 170     AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
 171     if (AcpiGbl_GlobalList->CurrentTotalSize > AcpiGbl_GlobalList->MaxOccupied)
 172     {
 173         AcpiGbl_GlobalList->MaxOccupied = AcpiGbl_GlobalList->CurrentTotalSize;
 174     }
 175 
 176     return ((void *) &Allocation->UserSpace);


 186  *              Module              - Source file name of caller
 187  *              Line                - Line number of caller
 188  *
 189  * RETURN:      Address of the allocated memory on success, NULL on failure.
 190  *
 191  * DESCRIPTION: Subsystem equivalent of calloc.
 192  *
 193  ******************************************************************************/
 194 
 195 void *
 196 AcpiUtAllocateZeroedAndTrack (
 197     ACPI_SIZE               Size,
 198     UINT32                  Component,
 199     const char              *Module,
 200     UINT32                  Line)
 201 {
 202     ACPI_DEBUG_MEM_BLOCK    *Allocation;
 203     ACPI_STATUS             Status;
 204 
 205 
 206     Allocation = AcpiUtAllocateZeroed (Size + sizeof (ACPI_DEBUG_MEM_HEADER),
 207                     Component, Module, Line);








 208     if (!Allocation)
 209     {
 210         /* Report allocation error */
 211 
 212         ACPI_ERROR ((Module, Line,
 213             "Could not allocate size %u", (UINT32) Size));
 214         return (NULL);
 215     }
 216 
 217     Status = AcpiUtTrackAllocation (Allocation, Size,
 218                 ACPI_MEM_CALLOC, Component, Module, Line);
 219     if (ACPI_FAILURE (Status))
 220     {
 221         AcpiOsFree (Allocation);
 222         return (NULL);
 223     }
 224 
 225     AcpiGbl_GlobalList->TotalAllocated++;
 226     AcpiGbl_GlobalList->TotalSize += (UINT32) Size;
 227     AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;


 279 
 280     Status = AcpiUtRemoveAllocation (DebugBlock,
 281                     Component, Module, Line);
 282     if (ACPI_FAILURE (Status))
 283     {
 284         ACPI_EXCEPTION ((AE_INFO, Status, "Could not free memory"));
 285     }
 286 
 287     AcpiOsFree (DebugBlock);
 288     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed\n", Allocation));
 289     return_VOID;
 290 }
 291 
 292 
 293 /*******************************************************************************
 294  *
 295  * FUNCTION:    AcpiUtFindAllocation
 296  *
 297  * PARAMETERS:  Allocation              - Address of allocated memory
 298  *
 299  * RETURN:      A list element if found; NULL otherwise.




 300  *
 301  * DESCRIPTION: Searches for an element in the global allocation tracking list.


 302  *









 303  ******************************************************************************/
 304 
 305 static ACPI_DEBUG_MEM_BLOCK *
 306 AcpiUtFindAllocation (
 307     void                    *Allocation)
 308 {
 309     ACPI_DEBUG_MEM_BLOCK    *Element;
 310 
 311 
 312     ACPI_FUNCTION_ENTRY ();
 313 
 314 
 315     Element = AcpiGbl_GlobalList->ListHead;




 316 
 317     /* Search for the address. */









 318 
 319     while (Element)
 320     {
 321         if (Element == Allocation)
 322         {
 323             return (Element);
 324         }
 325 
 326         Element = Element->Next;
 327     }
 328 
 329     return (NULL);





 330 }
 331 
 332 
 333 /*******************************************************************************
 334  *
 335  * FUNCTION:    AcpiUtTrackAllocation
 336  *
 337  * PARAMETERS:  Allocation          - Address of allocated memory
 338  *              Size                - Size of the allocation
 339  *              AllocType           - MEM_MALLOC or MEM_CALLOC
 340  *              Component           - Component type of caller
 341  *              Module              - Source file name of caller
 342  *              Line                - Line number of caller
 343  *
 344  * RETURN:      None.
 345  *
 346  * DESCRIPTION: Inserts an element into the global allocation tracking list.
 347  *
 348  ******************************************************************************/
 349 
 350 static ACPI_STATUS
 351 AcpiUtTrackAllocation (
 352     ACPI_DEBUG_MEM_BLOCK    *Allocation,
 353     ACPI_SIZE               Size,
 354     UINT8                   AllocType,
 355     UINT32                  Component,
 356     const char              *Module,
 357     UINT32                  Line)
 358 {
 359     ACPI_MEMORY_LIST        *MemList;
 360     ACPI_DEBUG_MEM_BLOCK    *Element;
 361     ACPI_STATUS             Status = AE_OK;
 362 
 363 
 364     ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation);
 365 
 366 
 367     if (AcpiGbl_DisableMemTracking)
 368     {
 369         return_ACPI_STATUS (AE_OK);
 370     }
 371 
 372     MemList = AcpiGbl_GlobalList;
 373     Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
 374     if (ACPI_FAILURE (Status))
 375     {
 376         return_ACPI_STATUS (Status);
 377     }
 378 
 379     /*
 380      * Search list for this address to make sure it is not already on the list.
 381      * This will catch several kinds of problems.
 382      */
 383     Element = AcpiUtFindAllocation (Allocation);
 384     if (Element)
 385     {
 386         ACPI_ERROR ((AE_INFO,
 387             "UtTrackAllocation: Allocation already present in list! (%p)",
 388             Allocation));
 389 
 390         ACPI_ERROR ((AE_INFO, "Element %p Address %p",
 391             Element, Allocation));
 392 
 393         goto UnlockAndExit;
 394     }
 395 
 396     /* Fill in the instance data. */
 397 
 398     Allocation->Size      = (UINT32) Size;
 399     Allocation->AllocType = AllocType;
 400     Allocation->Component = Component;
 401     Allocation->Line      = Line;
 402 
 403     ACPI_STRNCPY (Allocation->Module, Module, ACPI_MAX_MODULE_NAME);
 404     Allocation->Module[ACPI_MAX_MODULE_NAME-1] = 0;
 405 


 406     /* Insert at list head */
 407 
 408     if (MemList->ListHead)
 409     {
 410         ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous = Allocation;
 411     }
 412 
 413     Allocation->Next = MemList->ListHead;
 414     Allocation->Previous = NULL;
 415 
 416     MemList->ListHead = Allocation;




 417 


 418 









 419 UnlockAndExit:
 420     Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
 421     return_ACPI_STATUS (Status);
 422 }
 423 
 424 
 425 /*******************************************************************************
 426  *
 427  * FUNCTION:    AcpiUtRemoveAllocation
 428  *
 429  * PARAMETERS:  Allocation          - Address of allocated memory
 430  *              Component           - Component type of caller
 431  *              Module              - Source file name of caller
 432  *              Line                - Line number of caller
 433  *
 434  * RETURN:
 435  *
 436  * DESCRIPTION: Deletes an element from the global allocation tracking list.
 437  *
 438  ******************************************************************************/
 439 
 440 static ACPI_STATUS
 441 AcpiUtRemoveAllocation (
 442     ACPI_DEBUG_MEM_BLOCK    *Allocation,
 443     UINT32                  Component,
 444     const char              *Module,
 445     UINT32                  Line)
 446 {
 447     ACPI_MEMORY_LIST        *MemList;
 448     ACPI_STATUS             Status;
 449 
 450 
 451     ACPI_FUNCTION_TRACE (UtRemoveAllocation);
 452 
 453 
 454     if (AcpiGbl_DisableMemTracking)
 455     {
 456         return_ACPI_STATUS (AE_OK);
 457     }
 458 
 459     MemList = AcpiGbl_GlobalList;
 460     if (NULL == MemList->ListHead)
 461     {
 462         /* No allocations! */
 463 
 464         ACPI_ERROR ((Module, Line,
 465             "Empty allocation list, nothing to free!"));
 466 
 467         return_ACPI_STATUS (AE_OK);
 468     }
 469 
 470     Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
 471     if (ACPI_FAILURE (Status))
 472     {
 473         return_ACPI_STATUS (Status);
 474     }
 475 
 476     /* Unlink */
 477 
 478     if (Allocation->Previous)
 479     {
 480         (Allocation->Previous)->Next = Allocation->Next;
 481     }
 482     else
 483     {
 484         MemList->ListHead = Allocation->Next;
 485     }
 486 
 487     if (Allocation->Next)
 488     {
 489         (Allocation->Next)->Previous = Allocation->Previous;
 490     }
 491 



 492     /* Mark the segment as deleted */
 493 
 494     ACPI_MEMSET (&Allocation->UserSpace, 0xEA, Allocation->Size);
 495 
 496     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n",
 497         Allocation->Size));
 498 
 499     Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
 500     return_ACPI_STATUS (Status);
 501 }
 502 
 503 
 504 /*******************************************************************************
 505  *
 506  * FUNCTION:    AcpiUtDumpAllocationInfo
 507  *
 508  * PARAMETERS:
 509  *
 510  * RETURN:      None
 511  *
 512  * DESCRIPTION: Print some info about the outstanding allocations.
 513  *
 514  ******************************************************************************/
 515 
 516 void
 517 AcpiUtDumpAllocationInfo (
 518     void)
 519 {
 520 /*
 521     ACPI_MEMORY_LIST        *MemList;
 522 */
 523 
 524     ACPI_FUNCTION_TRACE (UtDumpAllocationInfo);
 525 
 526 /*
 527     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
 528                     ("%30s: %4d (%3d Kb)\n", "Current allocations",


 573  * DESCRIPTION: Print a list of all outstanding allocations.
 574  *
 575  ******************************************************************************/
 576 
 577 void
 578 AcpiUtDumpAllocations (
 579     UINT32                  Component,
 580     const char              *Module)
 581 {
 582     ACPI_DEBUG_MEM_BLOCK    *Element;
 583     ACPI_DESCRIPTOR         *Descriptor;
 584     UINT32                  NumOutstanding = 0;
 585     UINT8                   DescriptorType;
 586 
 587 
 588     ACPI_FUNCTION_TRACE (UtDumpAllocations);
 589 
 590 
 591     if (AcpiGbl_DisableMemTracking)
 592     {
 593         return;
 594     }
 595 
 596     /*
 597      * Walk the allocation list.
 598      */
 599     if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY)))
 600     {
 601         return;
 602     }
 603 
 604     Element = AcpiGbl_GlobalList->ListHead;
 605     while (Element)
 606     {
 607         if ((Element->Component & Component) &&
 608             ((Module == NULL) || (0 == ACPI_STRCMP (Module, Element->Module))))
 609         {
 610             Descriptor = ACPI_CAST_PTR (ACPI_DESCRIPTOR, &Element->UserSpace);
 611 
 612             if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR))
 613             {
 614                 AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u "
 615                     "[Not a Descriptor - too small]\n",
 616                     Descriptor, Element->Size, Element->Module,
 617                     Element->Line);
 618             }
 619             else
 620             {
 621                 /* Ignore allocated objects that are in a cache */
 622 
 623                 if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != ACPI_DESC_TYPE_CACHED)
 624                 {
 625                     AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u [%s] ",
 626                         Descriptor, Element->Size, Element->Module,
 627                         Element->Line, AcpiUtGetDescriptorName (Descriptor));
 628 
 629                     /* Validate the descriptor type using Type field and length */
 630 
 631                     DescriptorType = 0; /* Not a valid descriptor type */
 632 
 633                     switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor))
 634                     {
 635                     case ACPI_DESC_TYPE_OPERAND:
 636                         if (Element->Size == sizeof (ACPI_DESC_TYPE_OPERAND))

 637                         {
 638                             DescriptorType = ACPI_DESC_TYPE_OPERAND;
 639                         }
 640                         break;
 641 
 642                     case ACPI_DESC_TYPE_PARSER:
 643                         if (Element->Size == sizeof (ACPI_DESC_TYPE_PARSER))

 644                         {
 645                             DescriptorType = ACPI_DESC_TYPE_PARSER;
 646                         }
 647                         break;
 648 
 649                     case ACPI_DESC_TYPE_NAMED:
 650                         if (Element->Size == sizeof (ACPI_DESC_TYPE_NAMED))

 651                         {
 652                             DescriptorType = ACPI_DESC_TYPE_NAMED;
 653                         }
 654                         break;
 655 
 656                     default:

 657                         break;
 658                     }
 659 
 660                     /* Display additional info for the major descriptor types */
 661 
 662                     switch (DescriptorType)
 663                     {
 664                     case ACPI_DESC_TYPE_OPERAND:

 665                         AcpiOsPrintf ("%12.12s  RefCount 0x%04X\n",
 666                             AcpiUtGetTypeName (Descriptor->Object.Common.Type),
 667                             Descriptor->Object.Common.ReferenceCount);
 668                         break;
 669 
 670                     case ACPI_DESC_TYPE_PARSER:

 671                         AcpiOsPrintf ("AmlOpcode 0x%04hX\n",
 672                             Descriptor->Op.Asl.AmlOpcode);
 673                         break;
 674 
 675                     case ACPI_DESC_TYPE_NAMED:

 676                         AcpiOsPrintf ("%4.4s\n",
 677                             AcpiUtGetNodeName (&Descriptor->Node));
 678                         break;
 679 
 680                     default:

 681                         AcpiOsPrintf ( "\n");
 682                         break;
 683                     }
 684                 }
 685             }
 686 
 687             NumOutstanding++;
 688         }
 689 
 690         Element = Element->Next;
 691     }
 692 
 693     (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
 694 
 695     /* Print summary */
 696 
 697     if (!NumOutstanding)
 698     {
 699         ACPI_INFO ((AE_INFO, "No outstanding allocations"));
 700     }
 701     else
 702     {
 703         ACPI_ERROR ((AE_INFO, "%u(0x%X) Outstanding allocations",
 704             NumOutstanding, NumOutstanding));
 705     }
 706 
 707     return_VOID;
 708 }
 709 
 710 #endif  /* ACPI_DBG_TRACK_ALLOCATIONS */
 711 
   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.


  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  *


 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);


 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;


 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",


 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 */