1ae115bc7Smrj /****************************************************************************** 2ae115bc7Smrj * 3ae115bc7Smrj * Module Name: uttrack - Memory allocation tracking routines (debug only) 4ae115bc7Smrj * 5ae115bc7Smrj *****************************************************************************/ 6ae115bc7Smrj 726f3cdf0SGordon Ross /* 8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp. 9ae115bc7Smrj * All rights reserved. 10ae115bc7Smrj * 1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without 1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions 1326f3cdf0SGordon Ross * are met: 1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright 1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer, 1626f3cdf0SGordon Ross * without modification. 1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below 1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon 2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further 2126f3cdf0SGordon Ross * binary redistribution. 2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names 2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived 2426f3cdf0SGordon Ross * from this software without specific prior written permission. 25ae115bc7Smrj * 2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the 2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free 2826f3cdf0SGordon Ross * Software Foundation. 29ae115bc7Smrj * 3026f3cdf0SGordon Ross * NO WARRANTY 3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES. 4226f3cdf0SGordon Ross */ 43ae115bc7Smrj 44ae115bc7Smrj /* 45ae115bc7Smrj * These procedures are used for tracking memory leaks in the subsystem, and 46ae115bc7Smrj * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set. 47ae115bc7Smrj * 48ae115bc7Smrj * Each memory allocation is tracked via a doubly linked list. Each 49ae115bc7Smrj * element contains the caller's component, module name, function name, and 50ae115bc7Smrj * line number. AcpiUtAllocate and AcpiUtAllocateZeroed call 51ae115bc7Smrj * AcpiUtTrackAllocation to add an element to the list; deletion 52ae115bc7Smrj * occurs in the body of AcpiUtFree. 53ae115bc7Smrj */ 54ae115bc7Smrj 55ae115bc7Smrj #include "acpi.h" 56aa2aa9a6SDana Myers #include "accommon.h" 57ae115bc7Smrj 58ae115bc7Smrj #ifdef ACPI_DBG_TRACK_ALLOCATIONS 59ae115bc7Smrj 60ae115bc7Smrj #define _COMPONENT ACPI_UTILITIES 61ae115bc7Smrj ACPI_MODULE_NAME ("uttrack") 62ae115bc7Smrj 63*385cc6b4SJerry Jelinek 64ae115bc7Smrj /* Local prototypes */ 65ae115bc7Smrj 66ae115bc7Smrj static ACPI_DEBUG_MEM_BLOCK * 67ae115bc7Smrj AcpiUtFindAllocation ( 68*385cc6b4SJerry Jelinek ACPI_DEBUG_MEM_BLOCK *Allocation); 69ae115bc7Smrj 70ae115bc7Smrj static ACPI_STATUS 71ae115bc7Smrj AcpiUtTrackAllocation ( 72ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Address, 73ae115bc7Smrj ACPI_SIZE Size, 74ae115bc7Smrj UINT8 AllocType, 75ae115bc7Smrj UINT32 Component, 76db2bae30SDana Myers const char *Module, 77ae115bc7Smrj UINT32 Line); 78ae115bc7Smrj 79ae115bc7Smrj static ACPI_STATUS 80ae115bc7Smrj AcpiUtRemoveAllocation ( 81ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Address, 82ae115bc7Smrj UINT32 Component, 83db2bae30SDana Myers const char *Module, 84ae115bc7Smrj UINT32 Line); 85ae115bc7Smrj 86ae115bc7Smrj 87ae115bc7Smrj /******************************************************************************* 88ae115bc7Smrj * 89ae115bc7Smrj * FUNCTION: AcpiUtCreateList 90ae115bc7Smrj * 91ae115bc7Smrj * PARAMETERS: CacheName - Ascii name for the cache 92ae115bc7Smrj * ObjectSize - Size of each cached object 93ae115bc7Smrj * ReturnCache - Where the new cache object is returned 94ae115bc7Smrj * 95ae115bc7Smrj * RETURN: Status 96ae115bc7Smrj * 97ae115bc7Smrj * DESCRIPTION: Create a local memory list for tracking purposed 98ae115bc7Smrj * 99ae115bc7Smrj ******************************************************************************/ 100ae115bc7Smrj 101ae115bc7Smrj ACPI_STATUS 102ae115bc7Smrj AcpiUtCreateList ( 103*385cc6b4SJerry Jelinek const char *ListName, 104ae115bc7Smrj UINT16 ObjectSize, 105ae115bc7Smrj ACPI_MEMORY_LIST **ReturnCache) 106ae115bc7Smrj { 107ae115bc7Smrj ACPI_MEMORY_LIST *Cache; 108ae115bc7Smrj 109ae115bc7Smrj 110ae115bc7Smrj Cache = AcpiOsAllocate (sizeof (ACPI_MEMORY_LIST)); 111ae115bc7Smrj if (!Cache) 112ae115bc7Smrj { 113ae115bc7Smrj return (AE_NO_MEMORY); 114ae115bc7Smrj } 115ae115bc7Smrj 116*385cc6b4SJerry Jelinek memset (Cache, 0, sizeof (ACPI_MEMORY_LIST)); 117ae115bc7Smrj 118ae115bc7Smrj Cache->ListName = ListName; 119ae115bc7Smrj Cache->ObjectSize = ObjectSize; 120ae115bc7Smrj 121ae115bc7Smrj *ReturnCache = Cache; 122ae115bc7Smrj return (AE_OK); 123ae115bc7Smrj } 124ae115bc7Smrj 125ae115bc7Smrj 126ae115bc7Smrj /******************************************************************************* 127ae115bc7Smrj * 128ae115bc7Smrj * FUNCTION: AcpiUtAllocateAndTrack 129ae115bc7Smrj * 130ae115bc7Smrj * PARAMETERS: Size - Size of the allocation 131ae115bc7Smrj * Component - Component type of caller 132ae115bc7Smrj * Module - Source file name of caller 133ae115bc7Smrj * Line - Line number of caller 134ae115bc7Smrj * 135ae115bc7Smrj * RETURN: Address of the allocated memory on success, NULL on failure. 136ae115bc7Smrj * 137ae115bc7Smrj * DESCRIPTION: The subsystem's equivalent of malloc. 138ae115bc7Smrj * 139ae115bc7Smrj ******************************************************************************/ 140ae115bc7Smrj 141ae115bc7Smrj void * 142ae115bc7Smrj AcpiUtAllocateAndTrack ( 143ae115bc7Smrj ACPI_SIZE Size, 144ae115bc7Smrj UINT32 Component, 145db2bae30SDana Myers const char *Module, 146ae115bc7Smrj UINT32 Line) 147ae115bc7Smrj { 148ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Allocation; 149ae115bc7Smrj ACPI_STATUS Status; 150ae115bc7Smrj 151ae115bc7Smrj 152*385cc6b4SJerry Jelinek /* Check for an inadvertent size of zero bytes */ 153*385cc6b4SJerry Jelinek 154*385cc6b4SJerry Jelinek if (!Size) 155*385cc6b4SJerry Jelinek { 156*385cc6b4SJerry Jelinek ACPI_WARNING ((Module, Line, 157*385cc6b4SJerry Jelinek "Attempt to allocate zero bytes, allocating 1 byte")); 158*385cc6b4SJerry Jelinek Size = 1; 159*385cc6b4SJerry Jelinek } 160*385cc6b4SJerry Jelinek 161*385cc6b4SJerry Jelinek Allocation = AcpiOsAllocate (Size + sizeof (ACPI_DEBUG_MEM_HEADER)); 162ae115bc7Smrj if (!Allocation) 163ae115bc7Smrj { 164*385cc6b4SJerry Jelinek /* Report allocation error */ 165*385cc6b4SJerry Jelinek 166*385cc6b4SJerry Jelinek ACPI_WARNING ((Module, Line, 167*385cc6b4SJerry Jelinek "Could not allocate size %u", (UINT32) Size)); 168*385cc6b4SJerry Jelinek 169ae115bc7Smrj return (NULL); 170ae115bc7Smrj } 171ae115bc7Smrj 172*385cc6b4SJerry Jelinek Status = AcpiUtTrackAllocation ( 173*385cc6b4SJerry Jelinek Allocation, Size, ACPI_MEM_MALLOC, Component, Module, Line); 174ae115bc7Smrj if (ACPI_FAILURE (Status)) 175ae115bc7Smrj { 176ae115bc7Smrj AcpiOsFree (Allocation); 177ae115bc7Smrj return (NULL); 178ae115bc7Smrj } 179ae115bc7Smrj 180ae115bc7Smrj AcpiGbl_GlobalList->TotalAllocated++; 181db2bae30SDana Myers AcpiGbl_GlobalList->TotalSize += (UINT32) Size; 182ae115bc7Smrj AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size; 183*385cc6b4SJerry Jelinek 184*385cc6b4SJerry Jelinek if (AcpiGbl_GlobalList->CurrentTotalSize > 185*385cc6b4SJerry Jelinek AcpiGbl_GlobalList->MaxOccupied) 186db2bae30SDana Myers { 187*385cc6b4SJerry Jelinek AcpiGbl_GlobalList->MaxOccupied = 188*385cc6b4SJerry Jelinek AcpiGbl_GlobalList->CurrentTotalSize; 189db2bae30SDana Myers } 190ae115bc7Smrj 191ae115bc7Smrj return ((void *) &Allocation->UserSpace); 192ae115bc7Smrj } 193ae115bc7Smrj 194ae115bc7Smrj 195ae115bc7Smrj /******************************************************************************* 196ae115bc7Smrj * 197ae115bc7Smrj * FUNCTION: AcpiUtAllocateZeroedAndTrack 198ae115bc7Smrj * 199ae115bc7Smrj * PARAMETERS: Size - Size of the allocation 200ae115bc7Smrj * Component - Component type of caller 201ae115bc7Smrj * Module - Source file name of caller 202ae115bc7Smrj * Line - Line number of caller 203ae115bc7Smrj * 204ae115bc7Smrj * RETURN: Address of the allocated memory on success, NULL on failure. 205ae115bc7Smrj * 206ae115bc7Smrj * DESCRIPTION: Subsystem equivalent of calloc. 207ae115bc7Smrj * 208ae115bc7Smrj ******************************************************************************/ 209ae115bc7Smrj 210ae115bc7Smrj void * 211ae115bc7Smrj AcpiUtAllocateZeroedAndTrack ( 212ae115bc7Smrj ACPI_SIZE Size, 213ae115bc7Smrj UINT32 Component, 214db2bae30SDana Myers const char *Module, 215ae115bc7Smrj UINT32 Line) 216ae115bc7Smrj { 217ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Allocation; 218ae115bc7Smrj ACPI_STATUS Status; 219ae115bc7Smrj 220ae115bc7Smrj 221*385cc6b4SJerry Jelinek /* Check for an inadvertent size of zero bytes */ 222*385cc6b4SJerry Jelinek 223*385cc6b4SJerry Jelinek if (!Size) 224*385cc6b4SJerry Jelinek { 225*385cc6b4SJerry Jelinek ACPI_WARNING ((Module, Line, 226*385cc6b4SJerry Jelinek "Attempt to allocate zero bytes, allocating 1 byte")); 227*385cc6b4SJerry Jelinek Size = 1; 228*385cc6b4SJerry Jelinek } 229*385cc6b4SJerry Jelinek 230*385cc6b4SJerry Jelinek Allocation = AcpiOsAllocateZeroed ( 231*385cc6b4SJerry Jelinek Size + sizeof (ACPI_DEBUG_MEM_HEADER)); 232ae115bc7Smrj if (!Allocation) 233ae115bc7Smrj { 234ae115bc7Smrj /* Report allocation error */ 235ae115bc7Smrj 236ae115bc7Smrj ACPI_ERROR ((Module, Line, 23726f3cdf0SGordon Ross "Could not allocate size %u", (UINT32) Size)); 238ae115bc7Smrj return (NULL); 239ae115bc7Smrj } 240ae115bc7Smrj 241ae115bc7Smrj Status = AcpiUtTrackAllocation (Allocation, Size, 242ae115bc7Smrj ACPI_MEM_CALLOC, Component, Module, Line); 243ae115bc7Smrj if (ACPI_FAILURE (Status)) 244ae115bc7Smrj { 245ae115bc7Smrj AcpiOsFree (Allocation); 246ae115bc7Smrj return (NULL); 247ae115bc7Smrj } 248ae115bc7Smrj 249ae115bc7Smrj AcpiGbl_GlobalList->TotalAllocated++; 250db2bae30SDana Myers AcpiGbl_GlobalList->TotalSize += (UINT32) Size; 251ae115bc7Smrj AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size; 252*385cc6b4SJerry Jelinek 253*385cc6b4SJerry Jelinek if (AcpiGbl_GlobalList->CurrentTotalSize > 254*385cc6b4SJerry Jelinek AcpiGbl_GlobalList->MaxOccupied) 255db2bae30SDana Myers { 256*385cc6b4SJerry Jelinek AcpiGbl_GlobalList->MaxOccupied = 257*385cc6b4SJerry Jelinek AcpiGbl_GlobalList->CurrentTotalSize; 258db2bae30SDana Myers } 259ae115bc7Smrj 260ae115bc7Smrj return ((void *) &Allocation->UserSpace); 261ae115bc7Smrj } 262ae115bc7Smrj 263ae115bc7Smrj 264ae115bc7Smrj /******************************************************************************* 265ae115bc7Smrj * 266ae115bc7Smrj * FUNCTION: AcpiUtFreeAndTrack 267ae115bc7Smrj * 268ae115bc7Smrj * PARAMETERS: Allocation - Address of the memory to deallocate 269ae115bc7Smrj * Component - Component type of caller 270ae115bc7Smrj * Module - Source file name of caller 271ae115bc7Smrj * Line - Line number of caller 272ae115bc7Smrj * 273ae115bc7Smrj * RETURN: None 274ae115bc7Smrj * 275ae115bc7Smrj * DESCRIPTION: Frees the memory at Allocation 276ae115bc7Smrj * 277ae115bc7Smrj ******************************************************************************/ 278ae115bc7Smrj 279ae115bc7Smrj void 280ae115bc7Smrj AcpiUtFreeAndTrack ( 281ae115bc7Smrj void *Allocation, 282ae115bc7Smrj UINT32 Component, 283db2bae30SDana Myers const char *Module, 284ae115bc7Smrj UINT32 Line) 285ae115bc7Smrj { 286ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *DebugBlock; 287ae115bc7Smrj ACPI_STATUS Status; 288ae115bc7Smrj 289ae115bc7Smrj 290ae115bc7Smrj ACPI_FUNCTION_TRACE_PTR (UtFree, Allocation); 291ae115bc7Smrj 292ae115bc7Smrj 293ae115bc7Smrj if (NULL == Allocation) 294ae115bc7Smrj { 295ae115bc7Smrj ACPI_ERROR ((Module, Line, 296ae115bc7Smrj "Attempt to delete a NULL address")); 297ae115bc7Smrj 298ae115bc7Smrj return_VOID; 299ae115bc7Smrj } 300ae115bc7Smrj 301ae115bc7Smrj DebugBlock = ACPI_CAST_PTR (ACPI_DEBUG_MEM_BLOCK, 302ae115bc7Smrj (((char *) Allocation) - sizeof (ACPI_DEBUG_MEM_HEADER))); 303ae115bc7Smrj 304ae115bc7Smrj AcpiGbl_GlobalList->TotalFreed++; 305ae115bc7Smrj AcpiGbl_GlobalList->CurrentTotalSize -= DebugBlock->Size; 306ae115bc7Smrj 307*385cc6b4SJerry Jelinek Status = AcpiUtRemoveAllocation (DebugBlock, Component, Module, Line); 308ae115bc7Smrj if (ACPI_FAILURE (Status)) 309ae115bc7Smrj { 310ae115bc7Smrj ACPI_EXCEPTION ((AE_INFO, Status, "Could not free memory")); 311ae115bc7Smrj } 312ae115bc7Smrj 313ae115bc7Smrj AcpiOsFree (DebugBlock); 314*385cc6b4SJerry Jelinek ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n", 315*385cc6b4SJerry Jelinek Allocation, DebugBlock)); 316ae115bc7Smrj return_VOID; 317ae115bc7Smrj } 318ae115bc7Smrj 319ae115bc7Smrj 320ae115bc7Smrj /******************************************************************************* 321ae115bc7Smrj * 322ae115bc7Smrj * FUNCTION: AcpiUtFindAllocation 323ae115bc7Smrj * 324ae115bc7Smrj * PARAMETERS: Allocation - Address of allocated memory 325ae115bc7Smrj * 326*385cc6b4SJerry Jelinek * RETURN: Three cases: 327*385cc6b4SJerry Jelinek * 1) List is empty, NULL is returned. 328*385cc6b4SJerry Jelinek * 2) Element was found. Returns Allocation parameter. 329*385cc6b4SJerry Jelinek * 3) Element was not found. Returns position where it should be 330*385cc6b4SJerry Jelinek * inserted into the list. 331ae115bc7Smrj * 332ae115bc7Smrj * DESCRIPTION: Searches for an element in the global allocation tracking list. 333*385cc6b4SJerry Jelinek * If the element is not found, returns the location within the 334*385cc6b4SJerry Jelinek * list where the element should be inserted. 335*385cc6b4SJerry Jelinek * 336*385cc6b4SJerry Jelinek * Note: The list is ordered by larger-to-smaller addresses. 337*385cc6b4SJerry Jelinek * 338*385cc6b4SJerry Jelinek * This global list is used to detect memory leaks in ACPICA as 339*385cc6b4SJerry Jelinek * well as other issues such as an attempt to release the same 340*385cc6b4SJerry Jelinek * internal object more than once. Although expensive as far 341*385cc6b4SJerry Jelinek * as cpu time, this list is much more helpful for finding these 342*385cc6b4SJerry Jelinek * types of issues than using memory leak detectors outside of 343*385cc6b4SJerry Jelinek * the ACPICA code. 344ae115bc7Smrj * 345ae115bc7Smrj ******************************************************************************/ 346ae115bc7Smrj 347ae115bc7Smrj static ACPI_DEBUG_MEM_BLOCK * 348ae115bc7Smrj AcpiUtFindAllocation ( 349*385cc6b4SJerry Jelinek ACPI_DEBUG_MEM_BLOCK *Allocation) 350ae115bc7Smrj { 351ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Element; 352ae115bc7Smrj 353ae115bc7Smrj 354ae115bc7Smrj Element = AcpiGbl_GlobalList->ListHead; 355*385cc6b4SJerry Jelinek if (!Element) 356ae115bc7Smrj { 357*385cc6b4SJerry Jelinek return (NULL); 358*385cc6b4SJerry Jelinek } 359*385cc6b4SJerry Jelinek 360*385cc6b4SJerry Jelinek /* 361*385cc6b4SJerry Jelinek * Search for the address. 362*385cc6b4SJerry Jelinek * 363*385cc6b4SJerry Jelinek * Note: List is ordered by larger-to-smaller addresses, on the 364*385cc6b4SJerry Jelinek * assumption that a new allocation usually has a larger address 365*385cc6b4SJerry Jelinek * than previous allocations. 366*385cc6b4SJerry Jelinek */ 367*385cc6b4SJerry Jelinek while (Element > Allocation) 368*385cc6b4SJerry Jelinek { 369*385cc6b4SJerry Jelinek /* Check for end-of-list */ 370*385cc6b4SJerry Jelinek 371*385cc6b4SJerry Jelinek if (!Element->Next) 372ae115bc7Smrj { 373ae115bc7Smrj return (Element); 374ae115bc7Smrj } 375ae115bc7Smrj 376ae115bc7Smrj Element = Element->Next; 377ae115bc7Smrj } 378ae115bc7Smrj 379*385cc6b4SJerry Jelinek if (Element == Allocation) 380*385cc6b4SJerry Jelinek { 381*385cc6b4SJerry Jelinek return (Element); 382*385cc6b4SJerry Jelinek } 383*385cc6b4SJerry Jelinek 384*385cc6b4SJerry Jelinek return (Element->Previous); 385ae115bc7Smrj } 386ae115bc7Smrj 387ae115bc7Smrj 388ae115bc7Smrj /******************************************************************************* 389ae115bc7Smrj * 390ae115bc7Smrj * FUNCTION: AcpiUtTrackAllocation 391ae115bc7Smrj * 392ae115bc7Smrj * PARAMETERS: Allocation - Address of allocated memory 393ae115bc7Smrj * Size - Size of the allocation 394ae115bc7Smrj * AllocType - MEM_MALLOC or MEM_CALLOC 395ae115bc7Smrj * Component - Component type of caller 396ae115bc7Smrj * Module - Source file name of caller 397ae115bc7Smrj * Line - Line number of caller 398ae115bc7Smrj * 399*385cc6b4SJerry Jelinek * RETURN: Status 400ae115bc7Smrj * 401ae115bc7Smrj * DESCRIPTION: Inserts an element into the global allocation tracking list. 402ae115bc7Smrj * 403ae115bc7Smrj ******************************************************************************/ 404ae115bc7Smrj 405ae115bc7Smrj static ACPI_STATUS 406ae115bc7Smrj AcpiUtTrackAllocation ( 407ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Allocation, 408ae115bc7Smrj ACPI_SIZE Size, 409ae115bc7Smrj UINT8 AllocType, 410ae115bc7Smrj UINT32 Component, 411db2bae30SDana Myers const char *Module, 412ae115bc7Smrj UINT32 Line) 413ae115bc7Smrj { 414ae115bc7Smrj ACPI_MEMORY_LIST *MemList; 415ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Element; 416ae115bc7Smrj ACPI_STATUS Status = AE_OK; 417ae115bc7Smrj 418ae115bc7Smrj 419ae115bc7Smrj ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation); 420ae115bc7Smrj 421ae115bc7Smrj 42226f3cdf0SGordon Ross if (AcpiGbl_DisableMemTracking) 42326f3cdf0SGordon Ross { 42426f3cdf0SGordon Ross return_ACPI_STATUS (AE_OK); 42526f3cdf0SGordon Ross } 42626f3cdf0SGordon Ross 427ae115bc7Smrj MemList = AcpiGbl_GlobalList; 428ae115bc7Smrj Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY); 429ae115bc7Smrj if (ACPI_FAILURE (Status)) 430ae115bc7Smrj { 431ae115bc7Smrj return_ACPI_STATUS (Status); 432ae115bc7Smrj } 433ae115bc7Smrj 434ae115bc7Smrj /* 435*385cc6b4SJerry Jelinek * Search the global list for this address to make sure it is not 436*385cc6b4SJerry Jelinek * already present. This will catch several kinds of problems. 437ae115bc7Smrj */ 438ae115bc7Smrj Element = AcpiUtFindAllocation (Allocation); 439*385cc6b4SJerry Jelinek if (Element == Allocation) 440ae115bc7Smrj { 441ae115bc7Smrj ACPI_ERROR ((AE_INFO, 442*385cc6b4SJerry Jelinek "UtTrackAllocation: Allocation (%p) already present in global list!", 443ae115bc7Smrj Allocation)); 444ae115bc7Smrj goto UnlockAndExit; 445ae115bc7Smrj } 446ae115bc7Smrj 447*385cc6b4SJerry Jelinek /* Fill in the instance data */ 448ae115bc7Smrj 449ae115bc7Smrj Allocation->Size = (UINT32) Size; 450ae115bc7Smrj Allocation->AllocType = AllocType; 451ae115bc7Smrj Allocation->Component = Component; 452ae115bc7Smrj Allocation->Line = Line; 453ae115bc7Smrj 454*385cc6b4SJerry Jelinek strncpy (Allocation->Module, Module, ACPI_MAX_MODULE_NAME); 455ae115bc7Smrj Allocation->Module[ACPI_MAX_MODULE_NAME-1] = 0; 456ae115bc7Smrj 457*385cc6b4SJerry Jelinek if (!Element) 458*385cc6b4SJerry Jelinek { 459ae115bc7Smrj /* Insert at list head */ 460ae115bc7Smrj 461ae115bc7Smrj if (MemList->ListHead) 462ae115bc7Smrj { 463*385cc6b4SJerry Jelinek ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous = 464*385cc6b4SJerry Jelinek Allocation; 465ae115bc7Smrj } 466ae115bc7Smrj 467ae115bc7Smrj Allocation->Next = MemList->ListHead; 468ae115bc7Smrj Allocation->Previous = NULL; 469ae115bc7Smrj 470ae115bc7Smrj MemList->ListHead = Allocation; 471*385cc6b4SJerry Jelinek } 472*385cc6b4SJerry Jelinek else 473*385cc6b4SJerry Jelinek { 474*385cc6b4SJerry Jelinek /* Insert after element */ 475*385cc6b4SJerry Jelinek 476*385cc6b4SJerry Jelinek Allocation->Next = Element->Next; 477*385cc6b4SJerry Jelinek Allocation->Previous = Element; 478*385cc6b4SJerry Jelinek 479*385cc6b4SJerry Jelinek if (Element->Next) 480*385cc6b4SJerry Jelinek { 481*385cc6b4SJerry Jelinek (Element->Next)->Previous = Allocation; 482*385cc6b4SJerry Jelinek } 483*385cc6b4SJerry Jelinek 484*385cc6b4SJerry Jelinek Element->Next = Allocation; 485*385cc6b4SJerry Jelinek } 486ae115bc7Smrj 487ae115bc7Smrj 488ae115bc7Smrj UnlockAndExit: 489ae115bc7Smrj Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); 490ae115bc7Smrj return_ACPI_STATUS (Status); 491ae115bc7Smrj } 492ae115bc7Smrj 493ae115bc7Smrj 494ae115bc7Smrj /******************************************************************************* 495ae115bc7Smrj * 496ae115bc7Smrj * FUNCTION: AcpiUtRemoveAllocation 497ae115bc7Smrj * 498ae115bc7Smrj * PARAMETERS: Allocation - Address of allocated memory 499ae115bc7Smrj * Component - Component type of caller 500ae115bc7Smrj * Module - Source file name of caller 501ae115bc7Smrj * Line - Line number of caller 502ae115bc7Smrj * 503*385cc6b4SJerry Jelinek * RETURN: Status 504ae115bc7Smrj * 505ae115bc7Smrj * DESCRIPTION: Deletes an element from the global allocation tracking list. 506ae115bc7Smrj * 507ae115bc7Smrj ******************************************************************************/ 508ae115bc7Smrj 509ae115bc7Smrj static ACPI_STATUS 510ae115bc7Smrj AcpiUtRemoveAllocation ( 511ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Allocation, 512ae115bc7Smrj UINT32 Component, 513db2bae30SDana Myers const char *Module, 514ae115bc7Smrj UINT32 Line) 515ae115bc7Smrj { 516ae115bc7Smrj ACPI_MEMORY_LIST *MemList; 517ae115bc7Smrj ACPI_STATUS Status; 518ae115bc7Smrj 519ae115bc7Smrj 520*385cc6b4SJerry Jelinek ACPI_FUNCTION_NAME (UtRemoveAllocation); 521ae115bc7Smrj 522ae115bc7Smrj 52326f3cdf0SGordon Ross if (AcpiGbl_DisableMemTracking) 52426f3cdf0SGordon Ross { 525*385cc6b4SJerry Jelinek return (AE_OK); 52626f3cdf0SGordon Ross } 52726f3cdf0SGordon Ross 528ae115bc7Smrj MemList = AcpiGbl_GlobalList; 529ae115bc7Smrj if (NULL == MemList->ListHead) 530ae115bc7Smrj { 531ae115bc7Smrj /* No allocations! */ 532ae115bc7Smrj 533ae115bc7Smrj ACPI_ERROR ((Module, Line, 534ae115bc7Smrj "Empty allocation list, nothing to free!")); 535ae115bc7Smrj 536*385cc6b4SJerry Jelinek return (AE_OK); 537ae115bc7Smrj } 538ae115bc7Smrj 539ae115bc7Smrj Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY); 540ae115bc7Smrj if (ACPI_FAILURE (Status)) 541ae115bc7Smrj { 542*385cc6b4SJerry Jelinek return (Status); 543ae115bc7Smrj } 544ae115bc7Smrj 545ae115bc7Smrj /* Unlink */ 546ae115bc7Smrj 547ae115bc7Smrj if (Allocation->Previous) 548ae115bc7Smrj { 549ae115bc7Smrj (Allocation->Previous)->Next = Allocation->Next; 550ae115bc7Smrj } 551ae115bc7Smrj else 552ae115bc7Smrj { 553ae115bc7Smrj MemList->ListHead = Allocation->Next; 554ae115bc7Smrj } 555ae115bc7Smrj 556ae115bc7Smrj if (Allocation->Next) 557ae115bc7Smrj { 558ae115bc7Smrj (Allocation->Next)->Previous = Allocation->Previous; 559ae115bc7Smrj } 560ae115bc7Smrj 561*385cc6b4SJerry Jelinek ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n", 562*385cc6b4SJerry Jelinek &Allocation->UserSpace, Allocation->Size)); 563*385cc6b4SJerry Jelinek 564ae115bc7Smrj /* Mark the segment as deleted */ 565ae115bc7Smrj 566*385cc6b4SJerry Jelinek memset (&Allocation->UserSpace, 0xEA, Allocation->Size); 567ae115bc7Smrj 568ae115bc7Smrj Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); 569*385cc6b4SJerry Jelinek return (Status); 570ae115bc7Smrj } 571ae115bc7Smrj 572ae115bc7Smrj 573ae115bc7Smrj /******************************************************************************* 574ae115bc7Smrj * 575ae115bc7Smrj * FUNCTION: AcpiUtDumpAllocationInfo 576ae115bc7Smrj * 577*385cc6b4SJerry Jelinek * PARAMETERS: None 578ae115bc7Smrj * 579ae115bc7Smrj * RETURN: None 580ae115bc7Smrj * 581ae115bc7Smrj * DESCRIPTION: Print some info about the outstanding allocations. 582ae115bc7Smrj * 583ae115bc7Smrj ******************************************************************************/ 584ae115bc7Smrj 585ae115bc7Smrj void 586ae115bc7Smrj AcpiUtDumpAllocationInfo ( 587ae115bc7Smrj void) 588ae115bc7Smrj { 589ae115bc7Smrj /* 590ae115bc7Smrj ACPI_MEMORY_LIST *MemList; 591ae115bc7Smrj */ 592ae115bc7Smrj 593ae115bc7Smrj ACPI_FUNCTION_TRACE (UtDumpAllocationInfo); 594ae115bc7Smrj 595ae115bc7Smrj /* 596ae115bc7Smrj ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 597ae115bc7Smrj ("%30s: %4d (%3d Kb)\n", "Current allocations", 598ae115bc7Smrj MemList->CurrentCount, 599ae115bc7Smrj ROUND_UP_TO_1K (MemList->CurrentSize))); 600ae115bc7Smrj 601ae115bc7Smrj ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 602ae115bc7Smrj ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations", 603ae115bc7Smrj MemList->MaxConcurrentCount, 604ae115bc7Smrj ROUND_UP_TO_1K (MemList->MaxConcurrentSize))); 605ae115bc7Smrj 606ae115bc7Smrj 607ae115bc7Smrj ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 608ae115bc7Smrj ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects", 609ae115bc7Smrj RunningObjectCount, 610ae115bc7Smrj ROUND_UP_TO_1K (RunningObjectSize))); 611ae115bc7Smrj 612ae115bc7Smrj ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 613ae115bc7Smrj ("%30s: %4d (%3d Kb)\n", "Total (all) allocations", 614ae115bc7Smrj RunningAllocCount, 615ae115bc7Smrj ROUND_UP_TO_1K (RunningAllocSize))); 616ae115bc7Smrj 617ae115bc7Smrj 618ae115bc7Smrj ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 619ae115bc7Smrj ("%30s: %4d (%3d Kb)\n", "Current Nodes", 620ae115bc7Smrj AcpiGbl_CurrentNodeCount, 621ae115bc7Smrj ROUND_UP_TO_1K (AcpiGbl_CurrentNodeSize))); 622ae115bc7Smrj 623ae115bc7Smrj ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 624ae115bc7Smrj ("%30s: %4d (%3d Kb)\n", "Max Nodes", 625ae115bc7Smrj AcpiGbl_MaxConcurrentNodeCount, 626ae115bc7Smrj ROUND_UP_TO_1K ((AcpiGbl_MaxConcurrentNodeCount * 627ae115bc7Smrj sizeof (ACPI_NAMESPACE_NODE))))); 628ae115bc7Smrj */ 629ae115bc7Smrj return_VOID; 630ae115bc7Smrj } 631ae115bc7Smrj 632ae115bc7Smrj 633ae115bc7Smrj /******************************************************************************* 634ae115bc7Smrj * 635ae115bc7Smrj * FUNCTION: AcpiUtDumpAllocations 636ae115bc7Smrj * 637ae115bc7Smrj * PARAMETERS: Component - Component(s) to dump info for. 638ae115bc7Smrj * Module - Module to dump info for. NULL means all. 639ae115bc7Smrj * 640ae115bc7Smrj * RETURN: None 641ae115bc7Smrj * 642ae115bc7Smrj * DESCRIPTION: Print a list of all outstanding allocations. 643ae115bc7Smrj * 644ae115bc7Smrj ******************************************************************************/ 645ae115bc7Smrj 646ae115bc7Smrj void 647ae115bc7Smrj AcpiUtDumpAllocations ( 648ae115bc7Smrj UINT32 Component, 649db2bae30SDana Myers const char *Module) 650ae115bc7Smrj { 651ae115bc7Smrj ACPI_DEBUG_MEM_BLOCK *Element; 652ae115bc7Smrj ACPI_DESCRIPTOR *Descriptor; 653ae115bc7Smrj UINT32 NumOutstanding = 0; 65426f3cdf0SGordon Ross UINT8 DescriptorType; 655ae115bc7Smrj 656ae115bc7Smrj 657ae115bc7Smrj ACPI_FUNCTION_TRACE (UtDumpAllocations); 658ae115bc7Smrj 659ae115bc7Smrj 66026f3cdf0SGordon Ross if (AcpiGbl_DisableMemTracking) 66126f3cdf0SGordon Ross { 662*385cc6b4SJerry Jelinek return_VOID; 66326f3cdf0SGordon Ross } 66426f3cdf0SGordon Ross 665ae115bc7Smrj /* 666ae115bc7Smrj * Walk the allocation list. 667ae115bc7Smrj */ 668ae115bc7Smrj if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY))) 669ae115bc7Smrj { 670*385cc6b4SJerry Jelinek return_VOID; 671ae115bc7Smrj } 672ae115bc7Smrj 673ae115bc7Smrj Element = AcpiGbl_GlobalList->ListHead; 674ae115bc7Smrj while (Element) 675ae115bc7Smrj { 676ae115bc7Smrj if ((Element->Component & Component) && 677*385cc6b4SJerry Jelinek ((Module == NULL) || (0 == strcmp (Module, Element->Module)))) 678ae115bc7Smrj { 679*385cc6b4SJerry Jelinek Descriptor = ACPI_CAST_PTR ( 680*385cc6b4SJerry Jelinek ACPI_DESCRIPTOR, &Element->UserSpace); 68126f3cdf0SGordon Ross 68226f3cdf0SGordon Ross if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR)) 68326f3cdf0SGordon Ross { 68426f3cdf0SGordon Ross AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u " 68526f3cdf0SGordon Ross "[Not a Descriptor - too small]\n", 68626f3cdf0SGordon Ross Descriptor, Element->Size, Element->Module, 68726f3cdf0SGordon Ross Element->Line); 68826f3cdf0SGordon Ross } 68926f3cdf0SGordon Ross else 69026f3cdf0SGordon Ross { 691ae115bc7Smrj /* Ignore allocated objects that are in a cache */ 692ae115bc7Smrj 693*385cc6b4SJerry Jelinek if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != 694*385cc6b4SJerry Jelinek ACPI_DESC_TYPE_CACHED) 695ae115bc7Smrj { 69626f3cdf0SGordon Ross AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u [%s] ", 697ae115bc7Smrj Descriptor, Element->Size, Element->Module, 698ae115bc7Smrj Element->Line, AcpiUtGetDescriptorName (Descriptor)); 699ae115bc7Smrj 70026f3cdf0SGordon Ross /* Validate the descriptor type using Type field and length */ 70126f3cdf0SGordon Ross 70226f3cdf0SGordon Ross DescriptorType = 0; /* Not a valid descriptor type */ 703ae115bc7Smrj 704ae115bc7Smrj switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor)) 705ae115bc7Smrj { 706ae115bc7Smrj case ACPI_DESC_TYPE_OPERAND: 707*385cc6b4SJerry Jelinek 708*385cc6b4SJerry Jelinek if (Element->Size == sizeof (ACPI_OPERAND_OBJECT)) 70926f3cdf0SGordon Ross { 71026f3cdf0SGordon Ross DescriptorType = ACPI_DESC_TYPE_OPERAND; 71126f3cdf0SGordon Ross } 712ae115bc7Smrj break; 713ae115bc7Smrj 714ae115bc7Smrj case ACPI_DESC_TYPE_PARSER: 715*385cc6b4SJerry Jelinek 716*385cc6b4SJerry Jelinek if (Element->Size == sizeof (ACPI_PARSE_OBJECT)) 71726f3cdf0SGordon Ross { 71826f3cdf0SGordon Ross DescriptorType = ACPI_DESC_TYPE_PARSER; 71926f3cdf0SGordon Ross } 720ae115bc7Smrj break; 721ae115bc7Smrj 722ae115bc7Smrj case ACPI_DESC_TYPE_NAMED: 723*385cc6b4SJerry Jelinek 724*385cc6b4SJerry Jelinek if (Element->Size == sizeof (ACPI_NAMESPACE_NODE)) 72526f3cdf0SGordon Ross { 72626f3cdf0SGordon Ross DescriptorType = ACPI_DESC_TYPE_NAMED; 72726f3cdf0SGordon Ross } 728ae115bc7Smrj break; 729ae115bc7Smrj 730ae115bc7Smrj default: 731*385cc6b4SJerry Jelinek 732ae115bc7Smrj break; 733ae115bc7Smrj } 734ae115bc7Smrj 73526f3cdf0SGordon Ross /* Display additional info for the major descriptor types */ 73626f3cdf0SGordon Ross 73726f3cdf0SGordon Ross switch (DescriptorType) 73826f3cdf0SGordon Ross { 73926f3cdf0SGordon Ross case ACPI_DESC_TYPE_OPERAND: 740*385cc6b4SJerry Jelinek 74126f3cdf0SGordon Ross AcpiOsPrintf ("%12.12s RefCount 0x%04X\n", 74226f3cdf0SGordon Ross AcpiUtGetTypeName (Descriptor->Object.Common.Type), 74326f3cdf0SGordon Ross Descriptor->Object.Common.ReferenceCount); 74426f3cdf0SGordon Ross break; 74526f3cdf0SGordon Ross 74626f3cdf0SGordon Ross case ACPI_DESC_TYPE_PARSER: 747*385cc6b4SJerry Jelinek 74826f3cdf0SGordon Ross AcpiOsPrintf ("AmlOpcode 0x%04hX\n", 74926f3cdf0SGordon Ross Descriptor->Op.Asl.AmlOpcode); 75026f3cdf0SGordon Ross break; 75126f3cdf0SGordon Ross 75226f3cdf0SGordon Ross case ACPI_DESC_TYPE_NAMED: 753*385cc6b4SJerry Jelinek 75426f3cdf0SGordon Ross AcpiOsPrintf ("%4.4s\n", 75526f3cdf0SGordon Ross AcpiUtGetNodeName (&Descriptor->Node)); 75626f3cdf0SGordon Ross break; 75726f3cdf0SGordon Ross 75826f3cdf0SGordon Ross default: 759*385cc6b4SJerry Jelinek 760ae115bc7Smrj AcpiOsPrintf ( "\n"); 76126f3cdf0SGordon Ross break; 76226f3cdf0SGordon Ross } 76326f3cdf0SGordon Ross } 76426f3cdf0SGordon Ross } 76526f3cdf0SGordon Ross 766ae115bc7Smrj NumOutstanding++; 767ae115bc7Smrj } 76826f3cdf0SGordon Ross 769ae115bc7Smrj Element = Element->Next; 770ae115bc7Smrj } 771ae115bc7Smrj 772ae115bc7Smrj (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY); 773ae115bc7Smrj 774ae115bc7Smrj /* Print summary */ 775ae115bc7Smrj 776ae115bc7Smrj if (!NumOutstanding) 777ae115bc7Smrj { 778*385cc6b4SJerry Jelinek ACPI_INFO (("No outstanding allocations")); 779ae115bc7Smrj } 780ae115bc7Smrj else 781ae115bc7Smrj { 78226f3cdf0SGordon Ross ACPI_ERROR ((AE_INFO, "%u(0x%X) Outstanding allocations", 783ae115bc7Smrj NumOutstanding, NumOutstanding)); 784ae115bc7Smrj } 785ae115bc7Smrj 786ae115bc7Smrj return_VOID; 787ae115bc7Smrj } 788ae115bc7Smrj 789ae115bc7Smrj #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ 790