utalloc.c revision 151937
1/******************************************************************************
2 *
3 * Module Name: utalloc - local memory allocation routines
4 *              $Revision: 1.149 $
5 *
6 *****************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
13 * All rights reserved.
14 *
15 * 2. License
16 *
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights.  You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
20 * property rights.
21 *
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
28 *
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code.  No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision.  In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change.  Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee.  Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
54 *
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117#define __UTALLOC_C__
118
119#include <contrib/dev/acpica/acpi.h>
120
121#define _COMPONENT          ACPI_UTILITIES
122        ACPI_MODULE_NAME    ("utalloc")
123
124/* Local prototypes */
125
126static ACPI_DEBUG_MEM_BLOCK *
127AcpiUtFindAllocation (
128    void                    *Allocation);
129
130static ACPI_STATUS
131AcpiUtTrackAllocation (
132    ACPI_DEBUG_MEM_BLOCK    *Address,
133    ACPI_SIZE               Size,
134    UINT8                   AllocType,
135    UINT32                  Component,
136    char                    *Module,
137    UINT32                  Line);
138
139static ACPI_STATUS
140AcpiUtRemoveAllocation (
141    ACPI_DEBUG_MEM_BLOCK    *Address,
142    UINT32                  Component,
143    char                    *Module,
144    UINT32                  Line);
145
146#ifdef ACPI_DBG_TRACK_ALLOCATIONS
147static ACPI_STATUS
148AcpiUtCreateList (
149    char                    *ListName,
150    UINT16                  ObjectSize,
151    ACPI_MEMORY_LIST        **ReturnCache);
152#endif
153
154
155/*******************************************************************************
156 *
157 * FUNCTION:    AcpiUtCreateCaches
158 *
159 * PARAMETERS:  None
160 *
161 * RETURN:      Status
162 *
163 * DESCRIPTION: Create all local caches
164 *
165 ******************************************************************************/
166
167ACPI_STATUS
168AcpiUtCreateCaches (
169    void)
170{
171    ACPI_STATUS             Status;
172
173
174#ifdef ACPI_DBG_TRACK_ALLOCATIONS
175
176    /* Memory allocation lists */
177
178    Status = AcpiUtCreateList ("Acpi-Global", 0,
179                &AcpiGbl_GlobalList);
180    if (ACPI_FAILURE (Status))
181    {
182        return (Status);
183    }
184
185    Status = AcpiUtCreateList ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE),
186                &AcpiGbl_NsNodeList);
187    if (ACPI_FAILURE (Status))
188    {
189        return (Status);
190    }
191#endif
192
193    /* Object Caches, for frequently used objects */
194
195    Status = AcpiOsCreateCache ("Acpi-State", sizeof (ACPI_GENERIC_STATE),
196                ACPI_MAX_STATE_CACHE_DEPTH, &AcpiGbl_StateCache);
197    if (ACPI_FAILURE (Status))
198    {
199        return (Status);
200    }
201
202    Status = AcpiOsCreateCache ("Acpi-Parse", sizeof (ACPI_PARSE_OBJ_COMMON),
203                ACPI_MAX_PARSE_CACHE_DEPTH, &AcpiGbl_PsNodeCache);
204    if (ACPI_FAILURE (Status))
205    {
206        return (Status);
207    }
208
209    Status = AcpiOsCreateCache ("Acpi-ParseExt", sizeof (ACPI_PARSE_OBJ_NAMED),
210                ACPI_MAX_EXTPARSE_CACHE_DEPTH, &AcpiGbl_PsNodeExtCache);
211    if (ACPI_FAILURE (Status))
212    {
213        return (Status);
214    }
215
216    Status = AcpiOsCreateCache ("Acpi-Operand", sizeof (ACPI_OPERAND_OBJECT),
217                ACPI_MAX_OBJECT_CACHE_DEPTH, &AcpiGbl_OperandCache);
218    if (ACPI_FAILURE (Status))
219    {
220        return (Status);
221    }
222
223    return (AE_OK);
224}
225
226
227/*******************************************************************************
228 *
229 * FUNCTION:    AcpiUtDeleteCaches
230 *
231 * PARAMETERS:  None
232 *
233 * RETURN:      Status
234 *
235 * DESCRIPTION: Purge and delete all local caches
236 *
237 ******************************************************************************/
238
239ACPI_STATUS
240AcpiUtDeleteCaches (
241    void)
242{
243
244    (void) AcpiOsDeleteCache (AcpiGbl_StateCache);
245    AcpiGbl_StateCache = NULL;
246
247    (void) AcpiOsDeleteCache (AcpiGbl_OperandCache);
248    AcpiGbl_OperandCache = NULL;
249
250    (void) AcpiOsDeleteCache (AcpiGbl_PsNodeCache);
251    AcpiGbl_PsNodeCache = NULL;
252
253    (void) AcpiOsDeleteCache (AcpiGbl_PsNodeExtCache);
254    AcpiGbl_PsNodeExtCache = NULL;
255
256    return (AE_OK);
257}
258
259
260/*******************************************************************************
261 *
262 * FUNCTION:    AcpiUtValidateBuffer
263 *
264 * PARAMETERS:  Buffer              - Buffer descriptor to be validated
265 *
266 * RETURN:      Status
267 *
268 * DESCRIPTION: Perform parameter validation checks on an ACPI_BUFFER
269 *
270 ******************************************************************************/
271
272ACPI_STATUS
273AcpiUtValidateBuffer (
274    ACPI_BUFFER             *Buffer)
275{
276
277    /* Obviously, the structure pointer must be valid */
278
279    if (!Buffer)
280    {
281        return (AE_BAD_PARAMETER);
282    }
283
284    /* Special semantics for the length */
285
286    if ((Buffer->Length == ACPI_NO_BUFFER)              ||
287        (Buffer->Length == ACPI_ALLOCATE_BUFFER)        ||
288        (Buffer->Length == ACPI_ALLOCATE_LOCAL_BUFFER))
289    {
290        return (AE_OK);
291    }
292
293    /* Length is valid, the buffer pointer must be also */
294
295    if (!Buffer->Pointer)
296    {
297        return (AE_BAD_PARAMETER);
298    }
299
300    return (AE_OK);
301}
302
303
304/*******************************************************************************
305 *
306 * FUNCTION:    AcpiUtInitializeBuffer
307 *
308 * PARAMETERS:  Buffer              - Buffer to be validated
309 *              RequiredLength      - Length needed
310 *
311 * RETURN:      Status
312 *
313 * DESCRIPTION: Validate that the buffer is of the required length or
314 *              allocate a new buffer.  Returned buffer is always zeroed.
315 *
316 ******************************************************************************/
317
318ACPI_STATUS
319AcpiUtInitializeBuffer (
320    ACPI_BUFFER             *Buffer,
321    ACPI_SIZE               RequiredLength)
322{
323    ACPI_STATUS             Status = AE_OK;
324
325
326    switch (Buffer->Length)
327    {
328    case ACPI_NO_BUFFER:
329
330        /* Set the exception and returned the required length */
331
332        Status = AE_BUFFER_OVERFLOW;
333        break;
334
335
336    case ACPI_ALLOCATE_BUFFER:
337
338        /* Allocate a new buffer */
339
340        Buffer->Pointer = AcpiOsAllocate (RequiredLength);
341        if (!Buffer->Pointer)
342        {
343            return (AE_NO_MEMORY);
344        }
345
346        /* Clear the buffer */
347
348        ACPI_MEMSET (Buffer->Pointer, 0, RequiredLength);
349        break;
350
351
352    case ACPI_ALLOCATE_LOCAL_BUFFER:
353
354        /* Allocate a new buffer with local interface to allow tracking */
355
356        Buffer->Pointer = ACPI_MEM_CALLOCATE (RequiredLength);
357        if (!Buffer->Pointer)
358        {
359            return (AE_NO_MEMORY);
360        }
361        break;
362
363
364    default:
365
366        /* Existing buffer: Validate the size of the buffer */
367
368        if (Buffer->Length < RequiredLength)
369        {
370            Status = AE_BUFFER_OVERFLOW;
371            break;
372        }
373
374        /* Clear the buffer */
375
376        ACPI_MEMSET (Buffer->Pointer, 0, RequiredLength);
377        break;
378    }
379
380    Buffer->Length = RequiredLength;
381    return (Status);
382}
383
384
385/*******************************************************************************
386 *
387 * FUNCTION:    AcpiUtAllocate
388 *
389 * PARAMETERS:  Size                - Size of the allocation
390 *              Component           - Component type of caller
391 *              Module              - Source file name of caller
392 *              Line                - Line number of caller
393 *
394 * RETURN:      Address of the allocated memory on success, NULL on failure.
395 *
396 * DESCRIPTION: The subsystem's equivalent of malloc.
397 *
398 ******************************************************************************/
399
400void *
401AcpiUtAllocate (
402    ACPI_SIZE               Size,
403    UINT32                  Component,
404    char                    *Module,
405    UINT32                  Line)
406{
407    void                    *Allocation;
408
409
410    ACPI_FUNCTION_TRACE_U32 ("UtAllocate", Size);
411
412
413    /* Check for an inadvertent size of zero bytes */
414
415    if (!Size)
416    {
417        _ACPI_REPORT_ERROR (Module, Line, Component,
418                ("UtAllocate: Attempt to allocate zero bytes, allocating 1 byte\n"));
419        Size = 1;
420    }
421
422    Allocation = AcpiOsAllocate (Size);
423    if (!Allocation)
424    {
425        /* Report allocation error */
426
427        _ACPI_REPORT_ERROR (Module, Line, Component,
428                ("UtAllocate: Could not allocate size %X\n", (UINT32) Size));
429
430        return_PTR (NULL);
431    }
432
433    return_PTR (Allocation);
434}
435
436
437/*******************************************************************************
438 *
439 * FUNCTION:    AcpiUtCallocate
440 *
441 * PARAMETERS:  Size                - Size of the allocation
442 *              Component           - Component type of caller
443 *              Module              - Source file name of caller
444 *              Line                - Line number of caller
445 *
446 * RETURN:      Address of the allocated memory on success, NULL on failure.
447 *
448 * DESCRIPTION: Subsystem equivalent of calloc.
449 *
450 ******************************************************************************/
451
452void *
453AcpiUtCallocate (
454    ACPI_SIZE               Size,
455    UINT32                  Component,
456    char                    *Module,
457    UINT32                  Line)
458{
459    void                    *Allocation;
460
461
462    ACPI_FUNCTION_TRACE_U32 ("UtCallocate", Size);
463
464
465    /* Check for an inadvertent size of zero bytes */
466
467    if (!Size)
468    {
469        _ACPI_REPORT_ERROR (Module, Line, Component,
470                ("UtCallocate: Attempt to allocate zero bytes, allocating 1 byte\n"));
471        Size = 1;
472    }
473
474    Allocation = AcpiOsAllocate (Size);
475    if (!Allocation)
476    {
477        /* Report allocation error */
478
479        _ACPI_REPORT_ERROR (Module, Line, Component,
480                ("UtCallocate: Could not allocate size %X\n", (UINT32) Size));
481        return_PTR (NULL);
482    }
483
484    /* Clear the memory block */
485
486    ACPI_MEMSET (Allocation, 0, Size);
487    return_PTR (Allocation);
488}
489
490
491#ifdef ACPI_DBG_TRACK_ALLOCATIONS
492/*
493 * These procedures are used for tracking memory leaks in the subsystem, and
494 * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
495 *
496 * Each memory allocation is tracked via a doubly linked list.  Each
497 * element contains the caller's component, module name, function name, and
498 * line number.  AcpiUtAllocate and AcpiUtCallocate call
499 * AcpiUtTrackAllocation to add an element to the list; deletion
500 * occurs in the body of AcpiUtFree.
501 */
502
503/*******************************************************************************
504 *
505 * FUNCTION:    AcpiUtCreateList
506 *
507 * PARAMETERS:  CacheName       - Ascii name for the cache
508 *              ObjectSize      - Size of each cached object
509 *              ReturnCache     - Where the new cache object is returned
510 *
511 * RETURN:      Status
512 *
513 * DESCRIPTION: Create a local memory list for tracking purposed
514 *
515 ******************************************************************************/
516
517static ACPI_STATUS
518AcpiUtCreateList (
519    char                    *ListName,
520    UINT16                  ObjectSize,
521    ACPI_MEMORY_LIST        **ReturnCache)
522{
523    ACPI_MEMORY_LIST        *Cache;
524
525
526    Cache = AcpiOsAllocate (sizeof (ACPI_MEMORY_LIST));
527    if (!Cache)
528    {
529        return (AE_NO_MEMORY);
530    }
531
532    ACPI_MEMSET (Cache, 0, sizeof (ACPI_MEMORY_LIST));
533
534    Cache->ListName   = ListName;
535    Cache->ObjectSize = ObjectSize;
536
537    *ReturnCache = Cache;
538    return (AE_OK);
539}
540
541
542/*******************************************************************************
543 *
544 * FUNCTION:    AcpiUtAllocateAndTrack
545 *
546 * PARAMETERS:  Size                - Size of the allocation
547 *              Component           - Component type of caller
548 *              Module              - Source file name of caller
549 *              Line                - Line number of caller
550 *
551 * RETURN:      Address of the allocated memory on success, NULL on failure.
552 *
553 * DESCRIPTION: The subsystem's equivalent of malloc.
554 *
555 ******************************************************************************/
556
557void *
558AcpiUtAllocateAndTrack (
559    ACPI_SIZE               Size,
560    UINT32                  Component,
561    char                    *Module,
562    UINT32                  Line)
563{
564    ACPI_DEBUG_MEM_BLOCK    *Allocation;
565    ACPI_STATUS             Status;
566
567
568    Allocation = AcpiUtAllocate (Size + sizeof (ACPI_DEBUG_MEM_HEADER),
569                    Component, Module, Line);
570    if (!Allocation)
571    {
572        return (NULL);
573    }
574
575    Status = AcpiUtTrackAllocation (Allocation, Size,
576                    ACPI_MEM_MALLOC, Component, Module, Line);
577    if (ACPI_FAILURE (Status))
578    {
579        AcpiOsFree (Allocation);
580        return (NULL);
581    }
582
583    AcpiGbl_GlobalList->TotalAllocated++;
584    AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
585
586    return ((void *) &Allocation->UserSpace);
587}
588
589
590/*******************************************************************************
591 *
592 * FUNCTION:    AcpiUtCallocateAndTrack
593 *
594 * PARAMETERS:  Size                - Size of the allocation
595 *              Component           - Component type of caller
596 *              Module              - Source file name of caller
597 *              Line                - Line number of caller
598 *
599 * RETURN:      Address of the allocated memory on success, NULL on failure.
600 *
601 * DESCRIPTION: Subsystem equivalent of calloc.
602 *
603 ******************************************************************************/
604
605void *
606AcpiUtCallocateAndTrack (
607    ACPI_SIZE               Size,
608    UINT32                  Component,
609    char                    *Module,
610    UINT32                  Line)
611{
612    ACPI_DEBUG_MEM_BLOCK    *Allocation;
613    ACPI_STATUS             Status;
614
615
616    Allocation = AcpiUtCallocate (Size + sizeof (ACPI_DEBUG_MEM_HEADER),
617                    Component, Module, Line);
618    if (!Allocation)
619    {
620        /* Report allocation error */
621
622        _ACPI_REPORT_ERROR (Module, Line, Component,
623                ("UtCallocate: Could not allocate size %X\n", (UINT32) Size));
624        return (NULL);
625    }
626
627    Status = AcpiUtTrackAllocation (Allocation, Size,
628                        ACPI_MEM_CALLOC, Component, Module, Line);
629    if (ACPI_FAILURE (Status))
630    {
631        AcpiOsFree (Allocation);
632        return (NULL);
633    }
634
635    AcpiGbl_GlobalList->TotalAllocated++;
636    AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
637
638    return ((void *) &Allocation->UserSpace);
639}
640
641
642/*******************************************************************************
643 *
644 * FUNCTION:    AcpiUtFreeAndTrack
645 *
646 * PARAMETERS:  Allocation          - Address of the memory to deallocate
647 *              Component           - Component type of caller
648 *              Module              - Source file name of caller
649 *              Line                - Line number of caller
650 *
651 * RETURN:      None
652 *
653 * DESCRIPTION: Frees the memory at Allocation
654 *
655 ******************************************************************************/
656
657void
658AcpiUtFreeAndTrack (
659    void                    *Allocation,
660    UINT32                  Component,
661    char                    *Module,
662    UINT32                  Line)
663{
664    ACPI_DEBUG_MEM_BLOCK    *DebugBlock;
665    ACPI_STATUS             Status;
666
667
668    ACPI_FUNCTION_TRACE_PTR ("UtFree", Allocation);
669
670
671    if (NULL == Allocation)
672    {
673        _ACPI_REPORT_ERROR (Module, Line, Component,
674            ("AcpiUtFree: Attempt to delete a NULL address\n"));
675
676        return_VOID;
677    }
678
679    DebugBlock = ACPI_CAST_PTR (ACPI_DEBUG_MEM_BLOCK,
680                    (((char *) Allocation) - sizeof (ACPI_DEBUG_MEM_HEADER)));
681
682    AcpiGbl_GlobalList->TotalFreed++;
683    AcpiGbl_GlobalList->CurrentTotalSize -= DebugBlock->Size;
684
685    Status = AcpiUtRemoveAllocation (DebugBlock,
686                    Component, Module, Line);
687    if (ACPI_FAILURE (Status))
688    {
689        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not free memory, %s\n",
690            AcpiFormatException (Status)));
691    }
692
693    AcpiOsFree (DebugBlock);
694
695    ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed\n", Allocation));
696
697    return_VOID;
698}
699
700
701/*******************************************************************************
702 *
703 * FUNCTION:    AcpiUtFindAllocation
704 *
705 * PARAMETERS:  Allocation              - Address of allocated memory
706 *
707 * RETURN:      A list element if found; NULL otherwise.
708 *
709 * DESCRIPTION: Searches for an element in the global allocation tracking list.
710 *
711 ******************************************************************************/
712
713static ACPI_DEBUG_MEM_BLOCK *
714AcpiUtFindAllocation (
715    void                    *Allocation)
716{
717    ACPI_DEBUG_MEM_BLOCK    *Element;
718
719
720    ACPI_FUNCTION_ENTRY ();
721
722
723    Element = AcpiGbl_GlobalList->ListHead;
724
725    /* Search for the address. */
726
727    while (Element)
728    {
729        if (Element == Allocation)
730        {
731            return (Element);
732        }
733
734        Element = Element->Next;
735    }
736
737    return (NULL);
738}
739
740
741/*******************************************************************************
742 *
743 * FUNCTION:    AcpiUtTrackAllocation
744 *
745 * PARAMETERS:  Allocation          - Address of allocated memory
746 *              Size                - Size of the allocation
747 *              AllocType           - MEM_MALLOC or MEM_CALLOC
748 *              Component           - Component type of caller
749 *              Module              - Source file name of caller
750 *              Line                - Line number of caller
751 *
752 * RETURN:      None.
753 *
754 * DESCRIPTION: Inserts an element into the global allocation tracking list.
755 *
756 ******************************************************************************/
757
758static ACPI_STATUS
759AcpiUtTrackAllocation (
760    ACPI_DEBUG_MEM_BLOCK    *Allocation,
761    ACPI_SIZE               Size,
762    UINT8                   AllocType,
763    UINT32                  Component,
764    char                    *Module,
765    UINT32                  Line)
766{
767    ACPI_MEMORY_LIST        *MemList;
768    ACPI_DEBUG_MEM_BLOCK    *Element;
769    ACPI_STATUS             Status = AE_OK;
770
771
772    ACPI_FUNCTION_TRACE_PTR ("UtTrackAllocation", Allocation);
773
774
775    MemList = AcpiGbl_GlobalList;
776    Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
777    if (ACPI_FAILURE (Status))
778    {
779        return_ACPI_STATUS (Status);
780    }
781
782    /*
783     * Search list for this address to make sure it is not already on the list.
784     * This will catch several kinds of problems.
785     */
786    Element = AcpiUtFindAllocation (Allocation);
787    if (Element)
788    {
789        ACPI_REPORT_ERROR ((
790            "UtTrackAllocation: Allocation already present in list! (%p)\n",
791            Allocation));
792
793        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Element %p Address %p\n",
794            Element, Allocation));
795
796        goto UnlockAndExit;
797    }
798
799    /* Fill in the instance data. */
800
801    Allocation->Size      = (UINT32) Size;
802    Allocation->AllocType = AllocType;
803    Allocation->Component = Component;
804    Allocation->Line      = Line;
805
806    ACPI_STRNCPY (Allocation->Module, Module, ACPI_MAX_MODULE_NAME);
807    Allocation->Module[ACPI_MAX_MODULE_NAME-1] = 0;
808
809    /* Insert at list head */
810
811    if (MemList->ListHead)
812    {
813        ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous = Allocation;
814    }
815
816    Allocation->Next = MemList->ListHead;
817    Allocation->Previous = NULL;
818
819    MemList->ListHead = Allocation;
820
821
822UnlockAndExit:
823    Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
824    return_ACPI_STATUS (Status);
825}
826
827
828/*******************************************************************************
829 *
830 * FUNCTION:    AcpiUtRemoveAllocation
831 *
832 * PARAMETERS:  Allocation          - Address of allocated memory
833 *              Component           - Component type of caller
834 *              Module              - Source file name of caller
835 *              Line                - Line number of caller
836 *
837 * RETURN:
838 *
839 * DESCRIPTION: Deletes an element from the global allocation tracking list.
840 *
841 ******************************************************************************/
842
843static ACPI_STATUS
844AcpiUtRemoveAllocation (
845    ACPI_DEBUG_MEM_BLOCK    *Allocation,
846    UINT32                  Component,
847    char                    *Module,
848    UINT32                  Line)
849{
850    ACPI_MEMORY_LIST        *MemList;
851    ACPI_STATUS             Status;
852
853
854    ACPI_FUNCTION_TRACE ("UtRemoveAllocation");
855
856
857    MemList = AcpiGbl_GlobalList;
858    if (NULL == MemList->ListHead)
859    {
860        /* No allocations! */
861
862        _ACPI_REPORT_ERROR (Module, Line, Component,
863            ("UtRemoveAllocation: Empty allocation list, nothing to free!\n"));
864
865        return_ACPI_STATUS (AE_OK);
866    }
867
868    Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
869    if (ACPI_FAILURE (Status))
870    {
871        return_ACPI_STATUS (Status);
872    }
873
874    /* Unlink */
875
876    if (Allocation->Previous)
877    {
878        (Allocation->Previous)->Next = Allocation->Next;
879    }
880    else
881    {
882        MemList->ListHead = Allocation->Next;
883    }
884
885    if (Allocation->Next)
886    {
887        (Allocation->Next)->Previous = Allocation->Previous;
888    }
889
890    /* Mark the segment as deleted */
891
892    ACPI_MEMSET (&Allocation->UserSpace, 0xEA, Allocation->Size);
893
894    ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n",
895        Allocation->Size));
896
897    Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
898    return_ACPI_STATUS (Status);
899}
900
901
902/*******************************************************************************
903 *
904 * FUNCTION:    AcpiUtDumpAllocationInfo
905 *
906 * PARAMETERS:
907 *
908 * RETURN:      None
909 *
910 * DESCRIPTION: Print some info about the outstanding allocations.
911 *
912 ******************************************************************************/
913
914void
915AcpiUtDumpAllocationInfo (
916    void)
917{
918/*
919    ACPI_MEMORY_LIST        *MemList;
920*/
921
922    ACPI_FUNCTION_TRACE ("UtDumpAllocationInfo");
923
924/*
925    ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
926                    ("%30s: %4d (%3d Kb)\n", "Current allocations",
927                    MemList->CurrentCount,
928                    ROUND_UP_TO_1K (MemList->CurrentSize)));
929
930    ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
931                    ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
932                    MemList->MaxConcurrentCount,
933                    ROUND_UP_TO_1K (MemList->MaxConcurrentSize)));
934
935
936    ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
937                    ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
938                    RunningObjectCount,
939                    ROUND_UP_TO_1K (RunningObjectSize)));
940
941    ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
942                    ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
943                    RunningAllocCount,
944                    ROUND_UP_TO_1K (RunningAllocSize)));
945
946
947    ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
948                    ("%30s: %4d (%3d Kb)\n", "Current Nodes",
949                    AcpiGbl_CurrentNodeCount,
950                    ROUND_UP_TO_1K (AcpiGbl_CurrentNodeSize)));
951
952    ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
953                    ("%30s: %4d (%3d Kb)\n", "Max Nodes",
954                    AcpiGbl_MaxConcurrentNodeCount,
955                    ROUND_UP_TO_1K ((AcpiGbl_MaxConcurrentNodeCount *
956                        sizeof (ACPI_NAMESPACE_NODE)))));
957*/
958    return_VOID;
959}
960
961
962/*******************************************************************************
963 *
964 * FUNCTION:    AcpiUtDumpAllocations
965 *
966 * PARAMETERS:  Component           - Component(s) to dump info for.
967 *              Module              - Module to dump info for.  NULL means all.
968 *
969 * RETURN:      None
970 *
971 * DESCRIPTION: Print a list of all outstanding allocations.
972 *
973 ******************************************************************************/
974
975void
976AcpiUtDumpAllocations (
977    UINT32                  Component,
978    char                    *Module)
979{
980    ACPI_DEBUG_MEM_BLOCK    *Element;
981    ACPI_DESCRIPTOR         *Descriptor;
982    UINT32                  NumOutstanding = 0;
983
984
985    ACPI_FUNCTION_TRACE ("UtDumpAllocations");
986
987
988    /*
989     * Walk the allocation list.
990     */
991    if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY)))
992    {
993        return;
994    }
995
996    Element = AcpiGbl_GlobalList->ListHead;
997    while (Element)
998    {
999        if ((Element->Component & Component) &&
1000            ((Module == NULL) || (0 == ACPI_STRCMP (Module, Element->Module))))
1001        {
1002            /* Ignore allocated objects that are in a cache */
1003
1004            Descriptor = ACPI_CAST_PTR (ACPI_DESCRIPTOR, &Element->UserSpace);
1005            if (Descriptor->DescriptorId != ACPI_DESC_TYPE_CACHED)
1006            {
1007                AcpiOsPrintf ("%p Len %04X %9.9s-%d [%s] ",
1008                    Descriptor, Element->Size, Element->Module,
1009                    Element->Line, AcpiUtGetDescriptorName (Descriptor));
1010
1011                /* Most of the elements will be Operand objects. */
1012
1013                switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor))
1014                {
1015                case ACPI_DESC_TYPE_OPERAND:
1016                    AcpiOsPrintf ("%12.12s R%hd",
1017                        AcpiUtGetTypeName (Descriptor->Object.Common.Type),
1018                        Descriptor->Object.Common.ReferenceCount);
1019                    break;
1020
1021                case ACPI_DESC_TYPE_PARSER:
1022                    AcpiOsPrintf ("AmlOpcode %04hX",
1023                        Descriptor->Op.Asl.AmlOpcode);
1024                    break;
1025
1026                case ACPI_DESC_TYPE_NAMED:
1027                    AcpiOsPrintf ("%4.4s",
1028                        AcpiUtGetNodeName (&Descriptor->Node));
1029                    break;
1030
1031                default:
1032                    break;
1033                }
1034
1035                AcpiOsPrintf ( "\n");
1036                NumOutstanding++;
1037            }
1038        }
1039        Element = Element->Next;
1040    }
1041
1042    (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
1043
1044    /* Print summary */
1045
1046    if (!NumOutstanding)
1047    {
1048        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
1049            "No outstanding allocations\n"));
1050    }
1051    else
1052    {
1053        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
1054            "%d(%X) Outstanding allocations\n",
1055            NumOutstanding, NumOutstanding));
1056    }
1057
1058    return_VOID;
1059}
1060
1061#endif  /* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */
1062
1063