1/******************************************************************************
2 *
3 * Module Name: uttrack - Memory allocation tracking routines (debug only)
4 *
5 *****************************************************************************/
6
7/******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2016, Intel Corp.
12 * All rights reserved.
13 *
14 * 2. License
15 *
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
20 *
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
27 *
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code. No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
36 *
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
39 *
40 * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision. In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change. Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee. Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution. In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government. In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************/
115
116/*
117 * These procedures are used for tracking memory leaks in the subsystem, and
118 * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
119 *
120 * Each memory allocation is tracked via a doubly linked list. Each
121 * element contains the caller's component, module name, function name, and
122 * line number. AcpiUtAllocate and AcpiUtAllocateZeroed call
123 * AcpiUtTrackAllocation to add an element to the list; deletion
124 * occurs in the body of AcpiUtFree.
125 */
126
127#include "acpi.h"
128#include "accommon.h"
129
130#ifdef ACPI_DBG_TRACK_ALLOCATIONS
131
132#define _COMPONENT          ACPI_UTILITIES
133        ACPI_MODULE_NAME    ("uttrack")
134
135
136/* Local prototypes */
137
138static ACPI_DEBUG_MEM_BLOCK *
139AcpiUtFindAllocation (
140    ACPI_DEBUG_MEM_BLOCK    *Allocation);
141
142static ACPI_STATUS
143AcpiUtTrackAllocation (
144    ACPI_DEBUG_MEM_BLOCK    *Address,
145    ACPI_SIZE               Size,
146    UINT8                   AllocType,
147    UINT32                  Component,
148    const char              *Module,
149    UINT32                  Line);
150
151static ACPI_STATUS
152AcpiUtRemoveAllocation (
153    ACPI_DEBUG_MEM_BLOCK    *Address,
154    UINT32                  Component,
155    const char              *Module,
156    UINT32                  Line);
157
158
159/*******************************************************************************
160 *
161 * FUNCTION:    AcpiUtCreateList
162 *
163 * PARAMETERS:  CacheName       - Ascii name for the cache
164 *              ObjectSize      - Size of each cached object
165 *              ReturnCache     - Where the new cache object is returned
166 *
167 * RETURN:      Status
168 *
169 * DESCRIPTION: Create a local memory list for tracking purposed
170 *
171 ******************************************************************************/
172
173ACPI_STATUS
174AcpiUtCreateList (
175    const char              *ListName,
176    UINT16                  ObjectSize,
177    ACPI_MEMORY_LIST        **ReturnCache)
178{
179    ACPI_MEMORY_LIST        *Cache;
180
181
182    Cache = AcpiOsAllocateZeroed (sizeof (ACPI_MEMORY_LIST));
183    if (!Cache)
184    {
185        return (AE_NO_MEMORY);
186    }
187
188    Cache->ListName = ListName;
189    Cache->ObjectSize = ObjectSize;
190
191    *ReturnCache = Cache;
192    return (AE_OK);
193}
194
195
196/*******************************************************************************
197 *
198 * FUNCTION:    AcpiUtAllocateAndTrack
199 *
200 * PARAMETERS:  Size                - Size of the allocation
201 *              Component           - Component type of caller
202 *              Module              - Source file name of caller
203 *              Line                - Line number of caller
204 *
205 * RETURN:      Address of the allocated memory on success, NULL on failure.
206 *
207 * DESCRIPTION: The subsystem's equivalent of malloc.
208 *
209 ******************************************************************************/
210
211void *
212AcpiUtAllocateAndTrack (
213    ACPI_SIZE               Size,
214    UINT32                  Component,
215    const char              *Module,
216    UINT32                  Line)
217{
218    ACPI_DEBUG_MEM_BLOCK    *Allocation;
219    ACPI_STATUS             Status;
220
221
222    /* Check for an inadvertent size of zero bytes */
223
224    if (!Size)
225    {
226        ACPI_WARNING ((Module, Line,
227            "Attempt to allocate zero bytes, allocating 1 byte"));
228        Size = 1;
229    }
230
231    Allocation = AcpiOsAllocate (Size + sizeof (ACPI_DEBUG_MEM_HEADER));
232    if (!Allocation)
233    {
234        /* Report allocation error */
235
236        ACPI_WARNING ((Module, Line,
237            "Could not allocate size %u", (UINT32) Size));
238
239        return (NULL);
240    }
241
242    Status = AcpiUtTrackAllocation (
243        Allocation, Size, ACPI_MEM_MALLOC, Component, Module, Line);
244    if (ACPI_FAILURE (Status))
245    {
246        AcpiOsFree (Allocation);
247        return (NULL);
248    }
249
250    AcpiGbl_GlobalList->TotalAllocated++;
251    AcpiGbl_GlobalList->TotalSize += (UINT32) Size;
252    AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
253
254    if (AcpiGbl_GlobalList->CurrentTotalSize >
255        AcpiGbl_GlobalList->MaxOccupied)
256    {
257        AcpiGbl_GlobalList->MaxOccupied =
258            AcpiGbl_GlobalList->CurrentTotalSize;
259    }
260
261    return ((void *) &Allocation->UserSpace);
262}
263
264
265/*******************************************************************************
266 *
267 * FUNCTION:    AcpiUtAllocateZeroedAndTrack
268 *
269 * PARAMETERS:  Size                - Size of the allocation
270 *              Component           - Component type of caller
271 *              Module              - Source file name of caller
272 *              Line                - Line number of caller
273 *
274 * RETURN:      Address of the allocated memory on success, NULL on failure.
275 *
276 * DESCRIPTION: Subsystem equivalent of calloc.
277 *
278 ******************************************************************************/
279
280void *
281AcpiUtAllocateZeroedAndTrack (
282    ACPI_SIZE               Size,
283    UINT32                  Component,
284    const char              *Module,
285    UINT32                  Line)
286{
287    ACPI_DEBUG_MEM_BLOCK    *Allocation;
288    ACPI_STATUS             Status;
289
290
291    /* Check for an inadvertent size of zero bytes */
292
293    if (!Size)
294    {
295        ACPI_WARNING ((Module, Line,
296            "Attempt to allocate zero bytes, allocating 1 byte"));
297        Size = 1;
298    }
299
300    Allocation = AcpiOsAllocateZeroed (
301        Size + sizeof (ACPI_DEBUG_MEM_HEADER));
302    if (!Allocation)
303    {
304        /* Report allocation error */
305
306        ACPI_ERROR ((Module, Line,
307            "Could not allocate size %u", (UINT32) Size));
308        return (NULL);
309    }
310
311    Status = AcpiUtTrackAllocation (Allocation, Size,
312        ACPI_MEM_CALLOC, Component, Module, Line);
313    if (ACPI_FAILURE (Status))
314    {
315        AcpiOsFree (Allocation);
316        return (NULL);
317    }
318
319    AcpiGbl_GlobalList->TotalAllocated++;
320    AcpiGbl_GlobalList->TotalSize += (UINT32) Size;
321    AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
322
323    if (AcpiGbl_GlobalList->CurrentTotalSize >
324        AcpiGbl_GlobalList->MaxOccupied)
325    {
326        AcpiGbl_GlobalList->MaxOccupied =
327            AcpiGbl_GlobalList->CurrentTotalSize;
328    }
329
330    return ((void *) &Allocation->UserSpace);
331}
332
333
334/*******************************************************************************
335 *
336 * FUNCTION:    AcpiUtFreeAndTrack
337 *
338 * PARAMETERS:  Allocation          - Address of the memory to deallocate
339 *              Component           - Component type of caller
340 *              Module              - Source file name of caller
341 *              Line                - Line number of caller
342 *
343 * RETURN:      None
344 *
345 * DESCRIPTION: Frees the memory at Allocation
346 *
347 ******************************************************************************/
348
349void
350AcpiUtFreeAndTrack (
351    void                    *Allocation,
352    UINT32                  Component,
353    const char              *Module,
354    UINT32                  Line)
355{
356    ACPI_DEBUG_MEM_BLOCK    *DebugBlock;
357    ACPI_STATUS             Status;
358
359
360    ACPI_FUNCTION_TRACE_PTR (UtFree, Allocation);
361
362
363    if (NULL == Allocation)
364    {
365        ACPI_ERROR ((Module, Line,
366            "Attempt to delete a NULL address"));
367
368        return_VOID;
369    }
370
371    DebugBlock = ACPI_CAST_PTR (ACPI_DEBUG_MEM_BLOCK,
372        (((char *) Allocation) - sizeof (ACPI_DEBUG_MEM_HEADER)));
373
374    AcpiGbl_GlobalList->TotalFreed++;
375    AcpiGbl_GlobalList->CurrentTotalSize -= DebugBlock->Size;
376
377    Status = AcpiUtRemoveAllocation (DebugBlock, Component, Module, Line);
378    if (ACPI_FAILURE (Status))
379    {
380        ACPI_EXCEPTION ((AE_INFO, Status, "Could not free memory"));
381    }
382
383    AcpiOsFree (DebugBlock);
384    ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n",
385        Allocation, DebugBlock));
386    return_VOID;
387}
388
389
390/*******************************************************************************
391 *
392 * FUNCTION:    AcpiUtFindAllocation
393 *
394 * PARAMETERS:  Allocation              - Address of allocated memory
395 *
396 * RETURN:      Three cases:
397 *              1) List is empty, NULL is returned.
398 *              2) Element was found. Returns Allocation parameter.
399 *              3) Element was not found. Returns position where it should be
400 *                  inserted into the list.
401 *
402 * DESCRIPTION: Searches for an element in the global allocation tracking list.
403 *              If the element is not found, returns the location within the
404 *              list where the element should be inserted.
405 *
406 *              Note: The list is ordered by larger-to-smaller addresses.
407 *
408 *              This global list is used to detect memory leaks in ACPICA as
409 *              well as other issues such as an attempt to release the same
410 *              internal object more than once. Although expensive as far
411 *              as cpu time, this list is much more helpful for finding these
412 *              types of issues than using memory leak detectors outside of
413 *              the ACPICA code.
414 *
415 ******************************************************************************/
416
417static ACPI_DEBUG_MEM_BLOCK *
418AcpiUtFindAllocation (
419    ACPI_DEBUG_MEM_BLOCK    *Allocation)
420{
421    ACPI_DEBUG_MEM_BLOCK    *Element;
422
423
424    Element = AcpiGbl_GlobalList->ListHead;
425    if (!Element)
426    {
427        return (NULL);
428    }
429
430    /*
431     * Search for the address.
432     *
433     * Note: List is ordered by larger-to-smaller addresses, on the
434     * assumption that a new allocation usually has a larger address
435     * than previous allocations.
436     */
437    while (Element > Allocation)
438    {
439        /* Check for end-of-list */
440
441        if (!Element->Next)
442        {
443            return (Element);
444        }
445
446        Element = Element->Next;
447    }
448
449    if (Element == Allocation)
450    {
451        return (Element);
452    }
453
454    return (Element->Previous);
455}
456
457
458/*******************************************************************************
459 *
460 * FUNCTION:    AcpiUtTrackAllocation
461 *
462 * PARAMETERS:  Allocation          - Address of allocated memory
463 *              Size                - Size of the allocation
464 *              AllocType           - MEM_MALLOC or MEM_CALLOC
465 *              Component           - Component type of caller
466 *              Module              - Source file name of caller
467 *              Line                - Line number of caller
468 *
469 * RETURN:      Status
470 *
471 * DESCRIPTION: Inserts an element into the global allocation tracking list.
472 *
473 ******************************************************************************/
474
475static ACPI_STATUS
476AcpiUtTrackAllocation (
477    ACPI_DEBUG_MEM_BLOCK    *Allocation,
478    ACPI_SIZE               Size,
479    UINT8                   AllocType,
480    UINT32                  Component,
481    const char              *Module,
482    UINT32                  Line)
483{
484    ACPI_MEMORY_LIST        *MemList;
485    ACPI_DEBUG_MEM_BLOCK    *Element;
486    ACPI_STATUS             Status = AE_OK;
487
488
489    ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation);
490
491
492    if (AcpiGbl_DisableMemTracking)
493    {
494        return_ACPI_STATUS (AE_OK);
495    }
496
497    MemList = AcpiGbl_GlobalList;
498    Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
499    if (ACPI_FAILURE (Status))
500    {
501        return_ACPI_STATUS (Status);
502    }
503
504    /*
505     * Search the global list for this address to make sure it is not
506     * already present. This will catch several kinds of problems.
507     */
508    Element = AcpiUtFindAllocation (Allocation);
509    if (Element == Allocation)
510    {
511        ACPI_ERROR ((AE_INFO,
512            "UtTrackAllocation: Allocation (%p) already present in global list!",
513            Allocation));
514        goto UnlockAndExit;
515    }
516
517    /* Fill in the instance data */
518
519    Allocation->Size = (UINT32) Size;
520    Allocation->AllocType = AllocType;
521    Allocation->Component = Component;
522    Allocation->Line = Line;
523
524    strncpy (Allocation->Module, Module, ACPI_MAX_MODULE_NAME);
525    Allocation->Module[ACPI_MAX_MODULE_NAME-1] = 0;
526
527    if (!Element)
528    {
529        /* Insert at list head */
530
531        if (MemList->ListHead)
532        {
533            ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous =
534                Allocation;
535        }
536
537        Allocation->Next = MemList->ListHead;
538        Allocation->Previous = NULL;
539
540        MemList->ListHead = Allocation;
541    }
542    else
543    {
544        /* Insert after element */
545
546        Allocation->Next = Element->Next;
547        Allocation->Previous = Element;
548
549        if (Element->Next)
550        {
551            (Element->Next)->Previous = Allocation;
552        }
553
554        Element->Next = Allocation;
555    }
556
557
558UnlockAndExit:
559    Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
560    return_ACPI_STATUS (Status);
561}
562
563
564/*******************************************************************************
565 *
566 * FUNCTION:    AcpiUtRemoveAllocation
567 *
568 * PARAMETERS:  Allocation          - Address of allocated memory
569 *              Component           - Component type of caller
570 *              Module              - Source file name of caller
571 *              Line                - Line number of caller
572 *
573 * RETURN:      Status
574 *
575 * DESCRIPTION: Deletes an element from the global allocation tracking list.
576 *
577 ******************************************************************************/
578
579static ACPI_STATUS
580AcpiUtRemoveAllocation (
581    ACPI_DEBUG_MEM_BLOCK    *Allocation,
582    UINT32                  Component,
583    const char              *Module,
584    UINT32                  Line)
585{
586    ACPI_MEMORY_LIST        *MemList;
587    ACPI_STATUS             Status;
588
589
590    ACPI_FUNCTION_NAME (UtRemoveAllocation);
591
592
593    if (AcpiGbl_DisableMemTracking)
594    {
595        return (AE_OK);
596    }
597
598    MemList = AcpiGbl_GlobalList;
599    if (NULL == MemList->ListHead)
600    {
601        /* No allocations! */
602
603        ACPI_ERROR ((Module, Line,
604            "Empty allocation list, nothing to free!"));
605
606        return (AE_OK);
607    }
608
609    Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
610    if (ACPI_FAILURE (Status))
611    {
612        return (Status);
613    }
614
615    /* Unlink */
616
617    if (Allocation->Previous)
618    {
619        (Allocation->Previous)->Next = Allocation->Next;
620    }
621    else
622    {
623        MemList->ListHead = Allocation->Next;
624    }
625
626    if (Allocation->Next)
627    {
628        (Allocation->Next)->Previous = Allocation->Previous;
629    }
630
631    ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
632        &Allocation->UserSpace, Allocation->Size));
633
634    /* Mark the segment as deleted */
635
636    memset (&Allocation->UserSpace, 0xEA, Allocation->Size);
637
638    Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
639    return (Status);
640}
641
642
643/*******************************************************************************
644 *
645 * FUNCTION:    AcpiUtDumpAllocationInfo
646 *
647 * PARAMETERS:  None
648 *
649 * RETURN:      None
650 *
651 * DESCRIPTION: Print some info about the outstanding allocations.
652 *
653 ******************************************************************************/
654
655void
656AcpiUtDumpAllocationInfo (
657    void)
658{
659/*
660    ACPI_MEMORY_LIST        *MemList;
661*/
662
663    ACPI_FUNCTION_TRACE (UtDumpAllocationInfo);
664
665/*
666    ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
667        ("%30s: %4d (%3d Kb)\n", "Current allocations",
668        MemList->CurrentCount,
669        ROUND_UP_TO_1K (MemList->CurrentSize)));
670
671    ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
672        ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
673        MemList->MaxConcurrentCount,
674        ROUND_UP_TO_1K (MemList->MaxConcurrentSize)));
675
676
677    ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
678        ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
679        RunningObjectCount,
680        ROUND_UP_TO_1K (RunningObjectSize)));
681
682    ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
683        ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
684        RunningAllocCount,
685        ROUND_UP_TO_1K (RunningAllocSize)));
686
687
688    ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
689        ("%30s: %4d (%3d Kb)\n", "Current Nodes",
690        AcpiGbl_CurrentNodeCount,
691        ROUND_UP_TO_1K (AcpiGbl_CurrentNodeSize)));
692
693    ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
694        ("%30s: %4d (%3d Kb)\n", "Max Nodes",
695        AcpiGbl_MaxConcurrentNodeCount,
696        ROUND_UP_TO_1K ((AcpiGbl_MaxConcurrentNodeCount *
697            sizeof (ACPI_NAMESPACE_NODE)))));
698*/
699    return_VOID;
700}
701
702
703/*******************************************************************************
704 *
705 * FUNCTION:    AcpiUtDumpAllocations
706 *
707 * PARAMETERS:  Component           - Component(s) to dump info for.
708 *              Module              - Module to dump info for. NULL means all.
709 *
710 * RETURN:      None
711 *
712 * DESCRIPTION: Print a list of all outstanding allocations.
713 *
714 ******************************************************************************/
715
716void
717AcpiUtDumpAllocations (
718    UINT32                  Component,
719    const char              *Module)
720{
721    ACPI_DEBUG_MEM_BLOCK    *Element;
722    ACPI_DESCRIPTOR         *Descriptor;
723    UINT32                  NumOutstanding = 0;
724    UINT8                   DescriptorType;
725
726
727    ACPI_FUNCTION_TRACE (UtDumpAllocations);
728
729
730    if (AcpiGbl_DisableMemTracking)
731    {
732        return_VOID;
733    }
734
735    /*
736     * Walk the allocation list.
737     */
738    if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY)))
739    {
740        return_VOID;
741    }
742
743    Element = AcpiGbl_GlobalList->ListHead;
744    while (Element)
745    {
746        if ((Element->Component & Component) &&
747            ((Module == NULL) || (0 == strcmp (Module, Element->Module))))
748        {
749            Descriptor = ACPI_CAST_PTR (
750                ACPI_DESCRIPTOR, &Element->UserSpace);
751
752            if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR))
753            {
754                AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u "
755                    "[Not a Descriptor - too small]\n",
756                    Descriptor, Element->Size, Element->Module,
757                    Element->Line);
758            }
759            else
760            {
761                /* Ignore allocated objects that are in a cache */
762
763                if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) !=
764                    ACPI_DESC_TYPE_CACHED)
765                {
766                    AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u [%s] ",
767                        Descriptor, Element->Size, Element->Module,
768                        Element->Line, AcpiUtGetDescriptorName (Descriptor));
769
770                    /* Validate the descriptor type using Type field and length */
771
772                    DescriptorType = 0; /* Not a valid descriptor type */
773
774                    switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor))
775                    {
776                    case ACPI_DESC_TYPE_OPERAND:
777
778                        if (Element->Size == sizeof (ACPI_OPERAND_OBJECT))
779                        {
780                            DescriptorType = ACPI_DESC_TYPE_OPERAND;
781                        }
782                        break;
783
784                    case ACPI_DESC_TYPE_PARSER:
785
786                        if (Element->Size == sizeof (ACPI_PARSE_OBJECT))
787                        {
788                            DescriptorType = ACPI_DESC_TYPE_PARSER;
789                        }
790                        break;
791
792                    case ACPI_DESC_TYPE_NAMED:
793
794                        if (Element->Size == sizeof (ACPI_NAMESPACE_NODE))
795                        {
796                            DescriptorType = ACPI_DESC_TYPE_NAMED;
797                        }
798                        break;
799
800                    default:
801
802                        break;
803                    }
804
805                    /* Display additional info for the major descriptor types */
806
807                    switch (DescriptorType)
808                    {
809                    case ACPI_DESC_TYPE_OPERAND:
810
811                        AcpiOsPrintf ("%12.12s  RefCount 0x%04X\n",
812                            AcpiUtGetTypeName (Descriptor->Object.Common.Type),
813                            Descriptor->Object.Common.ReferenceCount);
814                        break;
815
816                    case ACPI_DESC_TYPE_PARSER:
817
818                        AcpiOsPrintf ("AmlOpcode 0x%04hX\n",
819                            Descriptor->Op.Asl.AmlOpcode);
820                        break;
821
822                    case ACPI_DESC_TYPE_NAMED:
823
824                        AcpiOsPrintf ("%4.4s\n",
825                            AcpiUtGetNodeName (&Descriptor->Node));
826                        break;
827
828                    default:
829
830                        AcpiOsPrintf ( "\n");
831                        break;
832                    }
833                }
834            }
835
836            NumOutstanding++;
837        }
838
839        Element = Element->Next;
840    }
841
842    (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
843
844    /* Print summary */
845
846    if (!NumOutstanding)
847    {
848        ACPI_INFO (("No outstanding allocations"));
849    }
850    else
851    {
852        ACPI_ERROR ((AE_INFO, "%u(0x%X) Outstanding allocations",
853            NumOutstanding, NumOutstanding));
854    }
855
856    return_VOID;
857}
858
859#endif  /* ACPI_DBG_TRACK_ALLOCATIONS */
860