1 /******************************************************************************
3 * Module Name: utalloc - local memory allocation routines
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2005, R. Byron Moore
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
45 #include <acpi/acpi.h>
47 #define _COMPONENT ACPI_UTILITIES
48 ACPI_MODULE_NAME ("utalloc")
50 /* Local prototypes */
52 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
53 static struct acpi_debug_mem_block
*
54 acpi_ut_find_allocation (
58 acpi_ut_track_allocation (
59 struct acpi_debug_mem_block
*address
,
67 acpi_ut_remove_allocation (
68 struct acpi_debug_mem_block
*address
,
72 #endif /* ACPI_DBG_TRACK_ALLOCATIONS */
74 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
79 struct acpi_memory_list
**return_cache
);
83 /*******************************************************************************
85 * FUNCTION: acpi_ut_create_caches
91 * DESCRIPTION: Create all local caches
93 ******************************************************************************/
96 acpi_ut_create_caches (
102 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
104 /* Memory allocation lists */
106 status
= acpi_ut_create_list ("Acpi-Global", 0,
107 &acpi_gbl_global_list
);
108 if (ACPI_FAILURE (status
)) {
112 status
= acpi_ut_create_list ("Acpi-Namespace", sizeof (struct acpi_namespace_node
),
113 &acpi_gbl_ns_node_list
);
114 if (ACPI_FAILURE (status
)) {
119 /* Object Caches, for frequently used objects */
121 status
= acpi_os_create_cache ("acpi_state", sizeof (union acpi_generic_state
),
122 ACPI_MAX_STATE_CACHE_DEPTH
, &acpi_gbl_state_cache
);
123 if (ACPI_FAILURE (status
)) {
127 status
= acpi_os_create_cache ("acpi_parse", sizeof (struct acpi_parse_obj_common
),
128 ACPI_MAX_PARSE_CACHE_DEPTH
, &acpi_gbl_ps_node_cache
);
129 if (ACPI_FAILURE (status
)) {
133 status
= acpi_os_create_cache ("acpi_parse_ext", sizeof (struct acpi_parse_obj_named
),
134 ACPI_MAX_EXTPARSE_CACHE_DEPTH
, &acpi_gbl_ps_node_ext_cache
);
135 if (ACPI_FAILURE (status
)) {
139 status
= acpi_os_create_cache ("acpi_operand", sizeof (union acpi_operand_object
),
140 ACPI_MAX_OBJECT_CACHE_DEPTH
, &acpi_gbl_operand_cache
);
141 if (ACPI_FAILURE (status
)) {
149 /*******************************************************************************
151 * FUNCTION: acpi_ut_delete_caches
157 * DESCRIPTION: Purge and delete all local caches
159 ******************************************************************************/
162 acpi_ut_delete_caches (
166 (void) acpi_os_delete_cache (acpi_gbl_state_cache
);
167 acpi_gbl_state_cache
= NULL
;
169 (void) acpi_os_delete_cache (acpi_gbl_operand_cache
);
170 acpi_gbl_operand_cache
= NULL
;
172 (void) acpi_os_delete_cache (acpi_gbl_ps_node_cache
);
173 acpi_gbl_ps_node_cache
= NULL
;
175 (void) acpi_os_delete_cache (acpi_gbl_ps_node_ext_cache
);
176 acpi_gbl_ps_node_ext_cache
= NULL
;
181 /*******************************************************************************
183 * FUNCTION: acpi_ut_validate_buffer
185 * PARAMETERS: Buffer - Buffer descriptor to be validated
189 * DESCRIPTION: Perform parameter validation checks on an struct acpi_buffer
191 ******************************************************************************/
194 acpi_ut_validate_buffer (
195 struct acpi_buffer
*buffer
)
198 /* Obviously, the structure pointer must be valid */
201 return (AE_BAD_PARAMETER
);
204 /* Special semantics for the length */
206 if ((buffer
->length
== ACPI_NO_BUFFER
) ||
207 (buffer
->length
== ACPI_ALLOCATE_BUFFER
) ||
208 (buffer
->length
== ACPI_ALLOCATE_LOCAL_BUFFER
)) {
212 /* Length is valid, the buffer pointer must be also */
214 if (!buffer
->pointer
) {
215 return (AE_BAD_PARAMETER
);
222 /*******************************************************************************
224 * FUNCTION: acpi_ut_initialize_buffer
226 * PARAMETERS: Buffer - Buffer to be validated
227 * required_length - Length needed
231 * DESCRIPTION: Validate that the buffer is of the required length or
232 * allocate a new buffer. Returned buffer is always zeroed.
234 ******************************************************************************/
237 acpi_ut_initialize_buffer (
238 struct acpi_buffer
*buffer
,
239 acpi_size required_length
)
241 acpi_status status
= AE_OK
;
244 switch (buffer
->length
) {
247 /* Set the exception and returned the required length */
249 status
= AE_BUFFER_OVERFLOW
;
253 case ACPI_ALLOCATE_BUFFER
:
255 /* Allocate a new buffer */
257 buffer
->pointer
= acpi_os_allocate (required_length
);
258 if (!buffer
->pointer
) {
259 return (AE_NO_MEMORY
);
262 /* Clear the buffer */
264 ACPI_MEMSET (buffer
->pointer
, 0, required_length
);
268 case ACPI_ALLOCATE_LOCAL_BUFFER
:
270 /* Allocate a new buffer with local interface to allow tracking */
272 buffer
->pointer
= ACPI_MEM_CALLOCATE (required_length
);
273 if (!buffer
->pointer
) {
274 return (AE_NO_MEMORY
);
281 /* Existing buffer: Validate the size of the buffer */
283 if (buffer
->length
< required_length
) {
284 status
= AE_BUFFER_OVERFLOW
;
288 /* Clear the buffer */
290 ACPI_MEMSET (buffer
->pointer
, 0, required_length
);
294 buffer
->length
= required_length
;
299 /*******************************************************************************
301 * FUNCTION: acpi_ut_allocate
303 * PARAMETERS: Size - Size of the allocation
304 * Component - Component type of caller
305 * Module - Source file name of caller
306 * Line - Line number of caller
308 * RETURN: Address of the allocated memory on success, NULL on failure.
310 * DESCRIPTION: The subsystem's equivalent of malloc.
312 ******************************************************************************/
324 ACPI_FUNCTION_TRACE_U32 ("ut_allocate", size
);
327 /* Check for an inadvertent size of zero bytes */
330 _ACPI_REPORT_ERROR (module
, line
, component
,
331 ("ut_allocate: Attempt to allocate zero bytes\n"));
335 allocation
= acpi_os_allocate (size
);
337 /* Report allocation error */
339 _ACPI_REPORT_ERROR (module
, line
, component
,
340 ("ut_allocate: Could not allocate size %X\n", (u32
) size
));
345 return_PTR (allocation
);
349 /*******************************************************************************
351 * FUNCTION: acpi_ut_callocate
353 * PARAMETERS: Size - Size of the allocation
354 * Component - Component type of caller
355 * Module - Source file name of caller
356 * Line - Line number of caller
358 * RETURN: Address of the allocated memory on success, NULL on failure.
360 * DESCRIPTION: Subsystem equivalent of calloc.
362 ******************************************************************************/
374 ACPI_FUNCTION_TRACE_U32 ("ut_callocate", size
);
377 /* Check for an inadvertent size of zero bytes */
380 _ACPI_REPORT_ERROR (module
, line
, component
,
381 ("ut_callocate: Attempt to allocate zero bytes\n"));
385 allocation
= acpi_os_allocate (size
);
387 /* Report allocation error */
389 _ACPI_REPORT_ERROR (module
, line
, component
,
390 ("ut_callocate: Could not allocate size %X\n", (u32
) size
));
394 /* Clear the memory block */
396 ACPI_MEMSET (allocation
, 0, size
);
397 return_PTR (allocation
);
401 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
403 * These procedures are used for tracking memory leaks in the subsystem, and
404 * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
406 * Each memory allocation is tracked via a doubly linked list. Each
407 * element contains the caller's component, module name, function name, and
408 * line number. acpi_ut_allocate and acpi_ut_callocate call
409 * acpi_ut_track_allocation to add an element to the list; deletion
410 * occurs in the body of acpi_ut_free.
413 /*******************************************************************************
415 * FUNCTION: acpi_ut_create_list
417 * PARAMETERS: cache_name - Ascii name for the cache
418 * object_size - Size of each cached object
419 * return_cache - Where the new cache object is returned
423 * DESCRIPTION: Create a local memory list for tracking purposed
425 ******************************************************************************/
428 acpi_ut_create_list (
431 struct acpi_memory_list
**return_cache
)
433 struct acpi_memory_list
*cache
;
436 cache
= acpi_os_allocate (sizeof (struct acpi_memory_list
));
438 return (AE_NO_MEMORY
);
441 ACPI_MEMSET (cache
, 0, sizeof (struct acpi_memory_list
));
443 cache
->list_name
= list_name
;
444 cache
->object_size
= object_size
;
446 *return_cache
= cache
;
451 /*******************************************************************************
453 * FUNCTION: acpi_ut_allocate_and_track
455 * PARAMETERS: Size - Size of the allocation
456 * Component - Component type of caller
457 * Module - Source file name of caller
458 * Line - Line number of caller
460 * RETURN: Address of the allocated memory on success, NULL on failure.
462 * DESCRIPTION: The subsystem's equivalent of malloc.
464 ******************************************************************************/
467 acpi_ut_allocate_and_track (
473 struct acpi_debug_mem_block
*allocation
;
477 allocation
= acpi_ut_allocate (size
+ sizeof (struct acpi_debug_mem_header
),
478 component
, module
, line
);
483 status
= acpi_ut_track_allocation (allocation
, size
,
484 ACPI_MEM_MALLOC
, component
, module
, line
);
485 if (ACPI_FAILURE (status
)) {
486 acpi_os_free (allocation
);
490 acpi_gbl_global_list
->total_allocated
++;
491 acpi_gbl_global_list
->current_total_size
+= (u32
) size
;
493 return ((void *) &allocation
->user_space
);
497 /*******************************************************************************
499 * FUNCTION: acpi_ut_callocate_and_track
501 * PARAMETERS: Size - Size of the allocation
502 * Component - Component type of caller
503 * Module - Source file name of caller
504 * Line - Line number of caller
506 * RETURN: Address of the allocated memory on success, NULL on failure.
508 * DESCRIPTION: Subsystem equivalent of calloc.
510 ******************************************************************************/
513 acpi_ut_callocate_and_track (
519 struct acpi_debug_mem_block
*allocation
;
523 allocation
= acpi_ut_callocate (size
+ sizeof (struct acpi_debug_mem_header
),
524 component
, module
, line
);
526 /* Report allocation error */
528 _ACPI_REPORT_ERROR (module
, line
, component
,
529 ("ut_callocate: Could not allocate size %X\n", (u32
) size
));
533 status
= acpi_ut_track_allocation (allocation
, size
,
534 ACPI_MEM_CALLOC
, component
, module
, line
);
535 if (ACPI_FAILURE (status
)) {
536 acpi_os_free (allocation
);
540 acpi_gbl_global_list
->total_allocated
++;
541 acpi_gbl_global_list
->current_total_size
+= (u32
) size
;
543 return ((void *) &allocation
->user_space
);
547 /*******************************************************************************
549 * FUNCTION: acpi_ut_free_and_track
551 * PARAMETERS: Allocation - Address of the memory to deallocate
552 * Component - Component type of caller
553 * Module - Source file name of caller
554 * Line - Line number of caller
558 * DESCRIPTION: Frees the memory at Allocation
560 ******************************************************************************/
563 acpi_ut_free_and_track (
569 struct acpi_debug_mem_block
*debug_block
;
573 ACPI_FUNCTION_TRACE_PTR ("ut_free", allocation
);
576 if (NULL
== allocation
) {
577 _ACPI_REPORT_ERROR (module
, line
, component
,
578 ("acpi_ut_free: Attempt to delete a NULL address\n"));
583 debug_block
= ACPI_CAST_PTR (struct acpi_debug_mem_block
,
584 (((char *) allocation
) - sizeof (struct acpi_debug_mem_header
)));
586 acpi_gbl_global_list
->total_freed
++;
587 acpi_gbl_global_list
->current_total_size
-= debug_block
->size
;
589 status
= acpi_ut_remove_allocation (debug_block
,
590 component
, module
, line
);
591 if (ACPI_FAILURE (status
)) {
592 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR
, "Could not free memory, %s\n",
593 acpi_format_exception (status
)));
596 acpi_os_free (debug_block
);
598 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS
, "%p freed\n", allocation
));
604 /*******************************************************************************
606 * FUNCTION: acpi_ut_find_allocation
608 * PARAMETERS: Allocation - Address of allocated memory
610 * RETURN: A list element if found; NULL otherwise.
612 * DESCRIPTION: Searches for an element in the global allocation tracking list.
614 ******************************************************************************/
616 static struct acpi_debug_mem_block
*
617 acpi_ut_find_allocation (
620 struct acpi_debug_mem_block
*element
;
623 ACPI_FUNCTION_ENTRY ();
626 element
= acpi_gbl_global_list
->list_head
;
628 /* Search for the address. */
631 if (element
== allocation
) {
635 element
= element
->next
;
642 /*******************************************************************************
644 * FUNCTION: acpi_ut_track_allocation
646 * PARAMETERS: Allocation - Address of allocated memory
647 * Size - Size of the allocation
648 * alloc_type - MEM_MALLOC or MEM_CALLOC
649 * Component - Component type of caller
650 * Module - Source file name of caller
651 * Line - Line number of caller
655 * DESCRIPTION: Inserts an element into the global allocation tracking list.
657 ******************************************************************************/
660 acpi_ut_track_allocation (
661 struct acpi_debug_mem_block
*allocation
,
668 struct acpi_memory_list
*mem_list
;
669 struct acpi_debug_mem_block
*element
;
670 acpi_status status
= AE_OK
;
673 ACPI_FUNCTION_TRACE_PTR ("ut_track_allocation", allocation
);
676 mem_list
= acpi_gbl_global_list
;
677 status
= acpi_ut_acquire_mutex (ACPI_MTX_MEMORY
);
678 if (ACPI_FAILURE (status
)) {
679 return_ACPI_STATUS (status
);
683 * Search list for this address to make sure it is not already on the list.
684 * This will catch several kinds of problems.
686 element
= acpi_ut_find_allocation (allocation
);
689 "ut_track_allocation: Allocation already present in list! (%p)\n",
692 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR
, "Element %p Address %p\n",
693 element
, allocation
));
695 goto unlock_and_exit
;
698 /* Fill in the instance data. */
700 allocation
->size
= (u32
) size
;
701 allocation
->alloc_type
= alloc_type
;
702 allocation
->component
= component
;
703 allocation
->line
= line
;
705 ACPI_STRNCPY (allocation
->module
, module
, ACPI_MAX_MODULE_NAME
);
706 allocation
->module
[ACPI_MAX_MODULE_NAME
-1] = 0;
708 /* Insert at list head */
710 if (mem_list
->list_head
) {
711 ((struct acpi_debug_mem_block
*)(mem_list
->list_head
))->previous
= allocation
;
714 allocation
->next
= mem_list
->list_head
;
715 allocation
->previous
= NULL
;
717 mem_list
->list_head
= allocation
;
721 status
= acpi_ut_release_mutex (ACPI_MTX_MEMORY
);
722 return_ACPI_STATUS (status
);
726 /*******************************************************************************
728 * FUNCTION: acpi_ut_remove_allocation
730 * PARAMETERS: Allocation - Address of allocated memory
731 * Component - Component type of caller
732 * Module - Source file name of caller
733 * Line - Line number of caller
737 * DESCRIPTION: Deletes an element from the global allocation tracking list.
739 ******************************************************************************/
742 acpi_ut_remove_allocation (
743 struct acpi_debug_mem_block
*allocation
,
748 struct acpi_memory_list
*mem_list
;
752 ACPI_FUNCTION_TRACE ("ut_remove_allocation");
755 mem_list
= acpi_gbl_global_list
;
756 if (NULL
== mem_list
->list_head
) {
757 /* No allocations! */
759 _ACPI_REPORT_ERROR (module
, line
, component
,
760 ("ut_remove_allocation: Empty allocation list, nothing to free!\n"));
762 return_ACPI_STATUS (AE_OK
);
765 status
= acpi_ut_acquire_mutex (ACPI_MTX_MEMORY
);
766 if (ACPI_FAILURE (status
)) {
767 return_ACPI_STATUS (status
);
772 if (allocation
->previous
) {
773 (allocation
->previous
)->next
= allocation
->next
;
776 mem_list
->list_head
= allocation
->next
;
779 if (allocation
->next
) {
780 (allocation
->next
)->previous
= allocation
->previous
;
783 /* Mark the segment as deleted */
785 ACPI_MEMSET (&allocation
->user_space
, 0xEA, allocation
->size
);
787 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS
, "Freeing size 0%X\n",
790 status
= acpi_ut_release_mutex (ACPI_MTX_MEMORY
);
791 return_ACPI_STATUS (status
);
795 /*******************************************************************************
797 * FUNCTION: acpi_ut_dump_allocation_info
803 * DESCRIPTION: Print some info about the outstanding allocations.
805 ******************************************************************************/
807 #ifdef ACPI_FUTURE_USAGE
809 acpi_ut_dump_allocation_info (
813 struct acpi_memory_list *mem_list;
816 ACPI_FUNCTION_TRACE ("ut_dump_allocation_info");
819 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
820 ("%30s: %4d (%3d Kb)\n", "Current allocations",
821 mem_list->current_count,
822 ROUND_UP_TO_1K (mem_list->current_size)));
824 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
825 ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
826 mem_list->max_concurrent_count,
827 ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
830 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
831 ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
832 running_object_count,
833 ROUND_UP_TO_1K (running_object_size)));
835 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
836 ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
838 ROUND_UP_TO_1K (running_alloc_size)));
841 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
842 ("%30s: %4d (%3d Kb)\n", "Current Nodes",
843 acpi_gbl_current_node_count,
844 ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
846 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
847 ("%30s: %4d (%3d Kb)\n", "Max Nodes",
848 acpi_gbl_max_concurrent_node_count,
849 ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
850 sizeof (struct acpi_namespace_node)))));
854 #endif /* ACPI_FUTURE_USAGE */
857 /*******************************************************************************
859 * FUNCTION: acpi_ut_dump_allocations
861 * PARAMETERS: Component - Component(s) to dump info for.
862 * Module - Module to dump info for. NULL means all.
866 * DESCRIPTION: Print a list of all outstanding allocations.
868 ******************************************************************************/
871 acpi_ut_dump_allocations (
875 struct acpi_debug_mem_block
*element
;
876 union acpi_descriptor
*descriptor
;
877 u32 num_outstanding
= 0;
880 ACPI_FUNCTION_TRACE ("ut_dump_allocations");
884 * Walk the allocation list.
886 if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_MEMORY
))) {
890 element
= acpi_gbl_global_list
->list_head
;
892 if ((element
->component
& component
) &&
893 ((module
== NULL
) || (0 == ACPI_STRCMP (module
, element
->module
)))) {
894 /* Ignore allocated objects that are in a cache */
896 descriptor
= ACPI_CAST_PTR (union acpi_descriptor
, &element
->user_space
);
897 if (descriptor
->descriptor_id
!= ACPI_DESC_TYPE_CACHED
) {
898 acpi_os_printf ("%p Len %04X %9.9s-%d [%s] ",
899 descriptor
, element
->size
, element
->module
,
900 element
->line
, acpi_ut_get_descriptor_name (descriptor
));
902 /* Most of the elements will be Operand objects. */
904 switch (ACPI_GET_DESCRIPTOR_TYPE (descriptor
)) {
905 case ACPI_DESC_TYPE_OPERAND
:
906 acpi_os_printf ("%12.12s R%hd",
907 acpi_ut_get_type_name (descriptor
->object
.common
.type
),
908 descriptor
->object
.common
.reference_count
);
911 case ACPI_DESC_TYPE_PARSER
:
912 acpi_os_printf ("aml_opcode %04hX",
913 descriptor
->op
.asl
.aml_opcode
);
916 case ACPI_DESC_TYPE_NAMED
:
917 acpi_os_printf ("%4.4s",
918 acpi_ut_get_node_name (&descriptor
->node
));
925 acpi_os_printf ( "\n");
929 element
= element
->next
;
932 (void) acpi_ut_release_mutex (ACPI_MTX_MEMORY
);
936 if (!num_outstanding
) {
937 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR
,
938 "No outstanding allocations.\n"));
941 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR
,
942 "%d(%X) Outstanding allocations\n",
943 num_outstanding
, num_outstanding
));
949 #endif /* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */