aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/utilities/utalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/utilities/utalloc.c')
-rw-r--r--drivers/acpi/utilities/utalloc.c988
1 files changed, 988 insertions, 0 deletions
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
new file mode 100644
index 000000000000..3313439c4bc7
--- /dev/null
+++ b/drivers/acpi/utilities/utalloc.c
@@ -0,0 +1,988 @@
1/******************************************************************************
2 *
3 * Module Name: utalloc - local cache and memory allocation routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
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.
42 */
43
44
45#include <acpi/acpi.h>
46
47#define _COMPONENT ACPI_UTILITIES
48 ACPI_MODULE_NAME ("utalloc")
49
50
51/******************************************************************************
52 *
53 * FUNCTION: acpi_ut_release_to_cache
54 *
55 * PARAMETERS: list_id - Memory list/cache ID
56 * Object - The object to be released
57 *
58 * RETURN: None
59 *
60 * DESCRIPTION: Release an object to the specified cache. If cache is full,
61 * the object is deleted.
62 *
63 ******************************************************************************/
64
65void
66acpi_ut_release_to_cache (
67 u32 list_id,
68 void *object)
69{
70 struct acpi_memory_list *cache_info;
71
72
73 ACPI_FUNCTION_ENTRY ();
74
75
76 cache_info = &acpi_gbl_memory_lists[list_id];
77
78#ifdef ACPI_ENABLE_OBJECT_CACHE
79
80 /* If walk cache is full, just free this wallkstate object */
81
82 if (cache_info->cache_depth >= cache_info->max_cache_depth) {
83 ACPI_MEM_FREE (object);
84 ACPI_MEM_TRACKING (cache_info->total_freed++);
85 }
86
87 /* Otherwise put this object back into the cache */
88
89 else {
90 if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) {
91 return;
92 }
93
94 /* Mark the object as cached */
95
96 ACPI_MEMSET (object, 0xCA, cache_info->object_size);
97 ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_CACHED);
98
99 /* Put the object at the head of the cache list */
100
101 * (ACPI_CAST_INDIRECT_PTR (char, &(((char *) object)[cache_info->link_offset]))) = cache_info->list_head;
102 cache_info->list_head = object;
103 cache_info->cache_depth++;
104
105 (void) acpi_ut_release_mutex (ACPI_MTX_CACHES);
106 }
107
108#else
109
110 /* Object cache is disabled; just free the object */
111
112 ACPI_MEM_FREE (object);
113 ACPI_MEM_TRACKING (cache_info->total_freed++);
114#endif
115}
116
117
118/******************************************************************************
119 *
120 * FUNCTION: acpi_ut_acquire_from_cache
121 *
122 * PARAMETERS: list_id - Memory list ID
123 *
124 * RETURN: A requested object. NULL if the object could not be
125 * allocated.
126 *
127 * DESCRIPTION: Get an object from the specified cache. If cache is empty,
128 * the object is allocated.
129 *
130 ******************************************************************************/
131
132void *
133acpi_ut_acquire_from_cache (
134 u32 list_id)
135{
136 struct acpi_memory_list *cache_info;
137 void *object;
138
139
140 ACPI_FUNCTION_NAME ("ut_acquire_from_cache");
141
142
143 cache_info = &acpi_gbl_memory_lists[list_id];
144
145#ifdef ACPI_ENABLE_OBJECT_CACHE
146
147 if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) {
148 return (NULL);
149 }
150
151 ACPI_MEM_TRACKING (cache_info->cache_requests++);
152
153 /* Check the cache first */
154
155 if (cache_info->list_head) {
156 /* There is an object available, use it */
157
158 object = cache_info->list_head;
159 cache_info->list_head = *(ACPI_CAST_INDIRECT_PTR (char, &(((char *) object)[cache_info->link_offset])));
160
161 ACPI_MEM_TRACKING (cache_info->cache_hits++);
162 cache_info->cache_depth--;
163
164#ifdef ACPI_DBG_TRACK_ALLOCATIONS
165 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p from %s\n",
166 object, acpi_gbl_memory_lists[list_id].list_name));
167#endif
168
169 if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_CACHES))) {
170 return (NULL);
171 }
172
173 /* Clear (zero) the previously used Object */
174
175 ACPI_MEMSET (object, 0, cache_info->object_size);
176 }
177
178 else {
179 /* The cache is empty, create a new object */
180
181 /* Avoid deadlock with ACPI_MEM_CALLOCATE */
182
183 if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_CACHES))) {
184 return (NULL);
185 }
186
187 object = ACPI_MEM_CALLOCATE (cache_info->object_size);
188 ACPI_MEM_TRACKING (cache_info->total_allocated++);
189 }
190
191#else
192
193 /* Object cache is disabled; just allocate the object */
194
195 object = ACPI_MEM_CALLOCATE (cache_info->object_size);
196 ACPI_MEM_TRACKING (cache_info->total_allocated++);
197#endif
198
199 return (object);
200}
201
202
203#ifdef ACPI_ENABLE_OBJECT_CACHE
204/******************************************************************************
205 *
206 * FUNCTION: acpi_ut_delete_generic_cache
207 *
208 * PARAMETERS: list_id - Memory list ID
209 *
210 * RETURN: None
211 *
212 * DESCRIPTION: Free all objects within the requested cache.
213 *
214 ******************************************************************************/
215
216void
217acpi_ut_delete_generic_cache (
218 u32 list_id)
219{
220 struct acpi_memory_list *cache_info;
221 char *next;
222
223
224 ACPI_FUNCTION_ENTRY ();
225
226
227 cache_info = &acpi_gbl_memory_lists[list_id];
228 while (cache_info->list_head) {
229 /* Delete one cached state object */
230
231 next = *(ACPI_CAST_INDIRECT_PTR (char, &(((char *) cache_info->list_head)[cache_info->link_offset])));
232 ACPI_MEM_FREE (cache_info->list_head);
233
234 cache_info->list_head = next;
235 cache_info->cache_depth--;
236 }
237}
238#endif
239
240
241/*******************************************************************************
242 *
243 * FUNCTION: acpi_ut_validate_buffer
244 *
245 * PARAMETERS: Buffer - Buffer descriptor to be validated
246 *
247 * RETURN: Status
248 *
249 * DESCRIPTION: Perform parameter validation checks on an struct acpi_buffer
250 *
251 ******************************************************************************/
252
253acpi_status
254acpi_ut_validate_buffer (
255 struct acpi_buffer *buffer)
256{
257
258 /* Obviously, the structure pointer must be valid */
259
260 if (!buffer) {
261 return (AE_BAD_PARAMETER);
262 }
263
264 /* Special semantics for the length */
265
266 if ((buffer->length == ACPI_NO_BUFFER) ||
267 (buffer->length == ACPI_ALLOCATE_BUFFER) ||
268 (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) {
269 return (AE_OK);
270 }
271
272 /* Length is valid, the buffer pointer must be also */
273
274 if (!buffer->pointer) {
275 return (AE_BAD_PARAMETER);
276 }
277
278 return (AE_OK);
279}
280
281
282/*******************************************************************************
283 *
284 * FUNCTION: acpi_ut_initialize_buffer
285 *
286 * PARAMETERS: Buffer - Buffer to be validated
287 * required_length - Length needed
288 *
289 * RETURN: Status
290 *
291 * DESCRIPTION: Validate that the buffer is of the required length or
292 * allocate a new buffer. Returned buffer is always zeroed.
293 *
294 ******************************************************************************/
295
296acpi_status
297acpi_ut_initialize_buffer (
298 struct acpi_buffer *buffer,
299 acpi_size required_length)
300{
301 acpi_status status = AE_OK;
302
303
304 switch (buffer->length) {
305 case ACPI_NO_BUFFER:
306
307 /* Set the exception and returned the required length */
308
309 status = AE_BUFFER_OVERFLOW;
310 break;
311
312
313 case ACPI_ALLOCATE_BUFFER:
314
315 /* Allocate a new buffer */
316
317 buffer->pointer = acpi_os_allocate (required_length);
318 if (!buffer->pointer) {
319 return (AE_NO_MEMORY);
320 }
321
322 /* Clear the buffer */
323
324 ACPI_MEMSET (buffer->pointer, 0, required_length);
325 break;
326
327
328 case ACPI_ALLOCATE_LOCAL_BUFFER:
329
330 /* Allocate a new buffer with local interface to allow tracking */
331
332 buffer->pointer = ACPI_MEM_CALLOCATE (required_length);
333 if (!buffer->pointer) {
334 return (AE_NO_MEMORY);
335 }
336 break;
337
338
339 default:
340
341 /* Existing buffer: Validate the size of the buffer */
342
343 if (buffer->length < required_length) {
344 status = AE_BUFFER_OVERFLOW;
345 break;
346 }
347
348 /* Clear the buffer */
349
350 ACPI_MEMSET (buffer->pointer, 0, required_length);
351 break;
352 }
353
354 buffer->length = required_length;
355 return (status);
356}
357
358
359/*******************************************************************************
360 *
361 * FUNCTION: acpi_ut_allocate
362 *
363 * PARAMETERS: Size - Size of the allocation
364 * Component - Component type of caller
365 * Module - Source file name of caller
366 * Line - Line number of caller
367 *
368 * RETURN: Address of the allocated memory on success, NULL on failure.
369 *
370 * DESCRIPTION: The subsystem's equivalent of malloc.
371 *
372 ******************************************************************************/
373
374void *
375acpi_ut_allocate (
376 acpi_size size,
377 u32 component,
378 char *module,
379 u32 line)
380{
381 void *allocation;
382
383
384 ACPI_FUNCTION_TRACE_U32 ("ut_allocate", size);
385
386
387 /* Check for an inadvertent size of zero bytes */
388
389 if (!size) {
390 _ACPI_REPORT_ERROR (module, line, component,
391 ("ut_allocate: Attempt to allocate zero bytes\n"));
392 size = 1;
393 }
394
395 allocation = acpi_os_allocate (size);
396 if (!allocation) {
397 /* Report allocation error */
398
399 _ACPI_REPORT_ERROR (module, line, component,
400 ("ut_allocate: Could not allocate size %X\n", (u32) size));
401
402 return_PTR (NULL);
403 }
404
405 return_PTR (allocation);
406}
407
408
409/*******************************************************************************
410 *
411 * FUNCTION: acpi_ut_callocate
412 *
413 * PARAMETERS: Size - Size of the allocation
414 * Component - Component type of caller
415 * Module - Source file name of caller
416 * Line - Line number of caller
417 *
418 * RETURN: Address of the allocated memory on success, NULL on failure.
419 *
420 * DESCRIPTION: Subsystem equivalent of calloc.
421 *
422 ******************************************************************************/
423
424void *
425acpi_ut_callocate (
426 acpi_size size,
427 u32 component,
428 char *module,
429 u32 line)
430{
431 void *allocation;
432
433
434 ACPI_FUNCTION_TRACE_U32 ("ut_callocate", size);
435
436
437 /* Check for an inadvertent size of zero bytes */
438
439 if (!size) {
440 _ACPI_REPORT_ERROR (module, line, component,
441 ("ut_callocate: Attempt to allocate zero bytes\n"));
442 return_PTR (NULL);
443 }
444
445 allocation = acpi_os_allocate (size);
446 if (!allocation) {
447 /* Report allocation error */
448
449 _ACPI_REPORT_ERROR (module, line, component,
450 ("ut_callocate: Could not allocate size %X\n", (u32) size));
451 return_PTR (NULL);
452 }
453
454 /* Clear the memory block */
455
456 ACPI_MEMSET (allocation, 0, size);
457 return_PTR (allocation);
458}
459
460
461#ifdef ACPI_DBG_TRACK_ALLOCATIONS
462/*
463 * These procedures are used for tracking memory leaks in the subsystem, and
464 * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
465 *
466 * Each memory allocation is tracked via a doubly linked list. Each
467 * element contains the caller's component, module name, function name, and
468 * line number. acpi_ut_allocate and acpi_ut_callocate call
469 * acpi_ut_track_allocation to add an element to the list; deletion
470 * occurs in the body of acpi_ut_free.
471 */
472
473
474/*******************************************************************************
475 *
476 * FUNCTION: acpi_ut_allocate_and_track
477 *
478 * PARAMETERS: Size - Size of the allocation
479 * Component - Component type of caller
480 * Module - Source file name of caller
481 * Line - Line number of caller
482 *
483 * RETURN: Address of the allocated memory on success, NULL on failure.
484 *
485 * DESCRIPTION: The subsystem's equivalent of malloc.
486 *
487 ******************************************************************************/
488
489void *
490acpi_ut_allocate_and_track (
491 acpi_size size,
492 u32 component,
493 char *module,
494 u32 line)
495{
496 struct acpi_debug_mem_block *allocation;
497 acpi_status status;
498
499
500 allocation = acpi_ut_allocate (size + sizeof (struct acpi_debug_mem_header), component,
501 module, line);
502 if (!allocation) {
503 return (NULL);
504 }
505
506 status = acpi_ut_track_allocation (ACPI_MEM_LIST_GLOBAL, allocation, size,
507 ACPI_MEM_MALLOC, component, module, line);
508 if (ACPI_FAILURE (status)) {
509 acpi_os_free (allocation);
510 return (NULL);
511 }
512
513 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_allocated++;
514 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size += (u32) size;
515
516 return ((void *) &allocation->user_space);
517}
518
519
520/*******************************************************************************
521 *
522 * FUNCTION: acpi_ut_callocate_and_track
523 *
524 * PARAMETERS: Size - Size of the allocation
525 * Component - Component type of caller
526 * Module - Source file name of caller
527 * Line - Line number of caller
528 *
529 * RETURN: Address of the allocated memory on success, NULL on failure.
530 *
531 * DESCRIPTION: Subsystem equivalent of calloc.
532 *
533 ******************************************************************************/
534
535void *
536acpi_ut_callocate_and_track (
537 acpi_size size,
538 u32 component,
539 char *module,
540 u32 line)
541{
542 struct acpi_debug_mem_block *allocation;
543 acpi_status status;
544
545
546 allocation = acpi_ut_callocate (size + sizeof (struct acpi_debug_mem_header), component,
547 module, line);
548 if (!allocation) {
549 /* Report allocation error */
550
551 _ACPI_REPORT_ERROR (module, line, component,
552 ("ut_callocate: Could not allocate size %X\n", (u32) size));
553 return (NULL);
554 }
555
556 status = acpi_ut_track_allocation (ACPI_MEM_LIST_GLOBAL, allocation, size,
557 ACPI_MEM_CALLOC, component, module, line);
558 if (ACPI_FAILURE (status)) {
559 acpi_os_free (allocation);
560 return (NULL);
561 }
562
563 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_allocated++;
564 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size += (u32) size;
565
566 return ((void *) &allocation->user_space);
567}
568
569
570/*******************************************************************************
571 *
572 * FUNCTION: acpi_ut_free_and_track
573 *
574 * PARAMETERS: Allocation - Address of the memory to deallocate
575 * Component - Component type of caller
576 * Module - Source file name of caller
577 * Line - Line number of caller
578 *
579 * RETURN: None
580 *
581 * DESCRIPTION: Frees the memory at Allocation
582 *
583 ******************************************************************************/
584
585void
586acpi_ut_free_and_track (
587 void *allocation,
588 u32 component,
589 char *module,
590 u32 line)
591{
592 struct acpi_debug_mem_block *debug_block;
593 acpi_status status;
594
595
596 ACPI_FUNCTION_TRACE_PTR ("ut_free", allocation);
597
598
599 if (NULL == allocation) {
600 _ACPI_REPORT_ERROR (module, line, component,
601 ("acpi_ut_free: Attempt to delete a NULL address\n"));
602
603 return_VOID;
604 }
605
606 debug_block = ACPI_CAST_PTR (struct acpi_debug_mem_block,
607 (((char *) allocation) - sizeof (struct acpi_debug_mem_header)));
608
609 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_freed++;
610 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size -= debug_block->size;
611
612 status = acpi_ut_remove_allocation (ACPI_MEM_LIST_GLOBAL, debug_block,
613 component, module, line);
614 if (ACPI_FAILURE (status)) {
615 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not free memory, %s\n",
616 acpi_format_exception (status)));
617 }
618
619 acpi_os_free (debug_block);
620
621 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
622
623 return_VOID;
624}
625
626
627/*******************************************************************************
628 *
629 * FUNCTION: acpi_ut_find_allocation
630 *
631 * PARAMETERS: list_id - Memory list to search
632 * Allocation - Address of allocated memory
633 *
634 * RETURN: A list element if found; NULL otherwise.
635 *
636 * DESCRIPTION: Searches for an element in the global allocation tracking list.
637 *
638 ******************************************************************************/
639
640struct acpi_debug_mem_block *
641acpi_ut_find_allocation (
642 u32 list_id,
643 void *allocation)
644{
645 struct acpi_debug_mem_block *element;
646
647
648 ACPI_FUNCTION_ENTRY ();
649
650
651 if (list_id > ACPI_MEM_LIST_MAX) {
652 return (NULL);
653 }
654
655 element = acpi_gbl_memory_lists[list_id].list_head;
656
657 /* Search for the address. */
658
659 while (element) {
660 if (element == allocation) {
661 return (element);
662 }
663
664 element = element->next;
665 }
666
667 return (NULL);
668}
669
670
671/*******************************************************************************
672 *
673 * FUNCTION: acpi_ut_track_allocation
674 *
675 * PARAMETERS: list_id - Memory list to search
676 * Allocation - Address of allocated memory
677 * Size - Size of the allocation
678 * alloc_type - MEM_MALLOC or MEM_CALLOC
679 * Component - Component type of caller
680 * Module - Source file name of caller
681 * Line - Line number of caller
682 *
683 * RETURN: None.
684 *
685 * DESCRIPTION: Inserts an element into the global allocation tracking list.
686 *
687 ******************************************************************************/
688
689acpi_status
690acpi_ut_track_allocation (
691 u32 list_id,
692 struct acpi_debug_mem_block *allocation,
693 acpi_size size,
694 u8 alloc_type,
695 u32 component,
696 char *module,
697 u32 line)
698{
699 struct acpi_memory_list *mem_list;
700 struct acpi_debug_mem_block *element;
701 acpi_status status = AE_OK;
702
703
704 ACPI_FUNCTION_TRACE_PTR ("ut_track_allocation", allocation);
705
706
707 if (list_id > ACPI_MEM_LIST_MAX) {
708 return_ACPI_STATUS (AE_BAD_PARAMETER);
709 }
710
711 mem_list = &acpi_gbl_memory_lists[list_id];
712 status = acpi_ut_acquire_mutex (ACPI_MTX_MEMORY);
713 if (ACPI_FAILURE (status)) {
714 return_ACPI_STATUS (status);
715 }
716
717 /*
718 * Search list for this address to make sure it is not already on the list.
719 * This will catch several kinds of problems.
720 */
721
722 element = acpi_ut_find_allocation (list_id, allocation);
723 if (element) {
724 ACPI_REPORT_ERROR (("ut_track_allocation: Allocation already present in list! (%p)\n",
725 allocation));
726
727 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Element %p Address %p\n", element, allocation));
728
729 goto unlock_and_exit;
730 }
731
732 /* Fill in the instance data. */
733
734 allocation->size = (u32) size;
735 allocation->alloc_type = alloc_type;
736 allocation->component = component;
737 allocation->line = line;
738
739 ACPI_STRNCPY (allocation->module, module, ACPI_MAX_MODULE_NAME);
740 allocation->module[ACPI_MAX_MODULE_NAME-1] = 0;
741
742 /* Insert at list head */
743
744 if (mem_list->list_head) {
745 ((struct acpi_debug_mem_block *)(mem_list->list_head))->previous = allocation;
746 }
747
748 allocation->next = mem_list->list_head;
749 allocation->previous = NULL;
750
751 mem_list->list_head = allocation;
752
753
754unlock_and_exit:
755 status = acpi_ut_release_mutex (ACPI_MTX_MEMORY);
756 return_ACPI_STATUS (status);
757}
758
759
760/*******************************************************************************
761 *
762 * FUNCTION: acpi_ut_remove_allocation
763 *
764 * PARAMETERS: list_id - Memory list to search
765 * Allocation - Address of allocated memory
766 * Component - Component type of caller
767 * Module - Source file name of caller
768 * Line - Line number of caller
769 *
770 * RETURN:
771 *
772 * DESCRIPTION: Deletes an element from the global allocation tracking list.
773 *
774 ******************************************************************************/
775
776acpi_status
777acpi_ut_remove_allocation (
778 u32 list_id,
779 struct acpi_debug_mem_block *allocation,
780 u32 component,
781 char *module,
782 u32 line)
783{
784 struct acpi_memory_list *mem_list;
785 acpi_status status;
786
787
788 ACPI_FUNCTION_TRACE ("ut_remove_allocation");
789
790
791 if (list_id > ACPI_MEM_LIST_MAX) {
792 return_ACPI_STATUS (AE_BAD_PARAMETER);
793 }
794
795 mem_list = &acpi_gbl_memory_lists[list_id];
796 if (NULL == mem_list->list_head) {
797 /* No allocations! */
798
799 _ACPI_REPORT_ERROR (module, line, component,
800 ("ut_remove_allocation: Empty allocation list, nothing to free!\n"));
801
802 return_ACPI_STATUS (AE_OK);
803 }
804
805 status = acpi_ut_acquire_mutex (ACPI_MTX_MEMORY);
806 if (ACPI_FAILURE (status)) {
807 return_ACPI_STATUS (status);
808 }
809
810 /* Unlink */
811
812 if (allocation->previous) {
813 (allocation->previous)->next = allocation->next;
814 }
815 else {
816 mem_list->list_head = allocation->next;
817 }
818
819 if (allocation->next) {
820 (allocation->next)->previous = allocation->previous;
821 }
822
823 /* Mark the segment as deleted */
824
825 ACPI_MEMSET (&allocation->user_space, 0xEA, allocation->size);
826
827 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n", allocation->size));
828
829 status = acpi_ut_release_mutex (ACPI_MTX_MEMORY);
830 return_ACPI_STATUS (status);
831}
832
833
834/*******************************************************************************
835 *
836 * FUNCTION: acpi_ut_dump_allocation_info
837 *
838 * PARAMETERS:
839 *
840 * RETURN: None
841 *
842 * DESCRIPTION: Print some info about the outstanding allocations.
843 *
844 ******************************************************************************/
845#ifdef ACPI_FUTURE_USAGE
846void
847acpi_ut_dump_allocation_info (
848 void)
849{
850/*
851 struct acpi_memory_list *mem_list;
852*/
853
854 ACPI_FUNCTION_TRACE ("ut_dump_allocation_info");
855
856/*
857 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
858 ("%30s: %4d (%3d Kb)\n", "Current allocations",
859 mem_list->current_count,
860 ROUND_UP_TO_1K (mem_list->current_size)));
861
862 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
863 ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
864 mem_list->max_concurrent_count,
865 ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
866
867
868 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
869 ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
870 running_object_count,
871 ROUND_UP_TO_1K (running_object_size)));
872
873 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
874 ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
875 running_alloc_count,
876 ROUND_UP_TO_1K (running_alloc_size)));
877
878
879 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
880 ("%30s: %4d (%3d Kb)\n", "Current Nodes",
881 acpi_gbl_current_node_count,
882 ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
883
884 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
885 ("%30s: %4d (%3d Kb)\n", "Max Nodes",
886 acpi_gbl_max_concurrent_node_count,
887 ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count * sizeof (struct acpi_namespace_node)))));
888*/
889 return_VOID;
890}
891#endif /* ACPI_FUTURE_USAGE */
892
893
894/*******************************************************************************
895 *
896 * FUNCTION: acpi_ut_dump_allocations
897 *
898 * PARAMETERS: Component - Component(s) to dump info for.
899 * Module - Module to dump info for. NULL means all.
900 *
901 * RETURN: None
902 *
903 * DESCRIPTION: Print a list of all outstanding allocations.
904 *
905 ******************************************************************************/
906
907void
908acpi_ut_dump_allocations (
909 u32 component,
910 char *module)
911{
912 struct acpi_debug_mem_block *element;
913 union acpi_descriptor *descriptor;
914 u32 num_outstanding = 0;
915
916
917 ACPI_FUNCTION_TRACE ("ut_dump_allocations");
918
919
920 /*
921 * Walk the allocation list.
922 */
923 if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_MEMORY))) {
924 return;
925 }
926
927 element = acpi_gbl_memory_lists[0].list_head;
928 while (element) {
929 if ((element->component & component) &&
930 ((module == NULL) || (0 == ACPI_STRCMP (module, element->module)))) {
931 /* Ignore allocated objects that are in a cache */
932
933 descriptor = ACPI_CAST_PTR (union acpi_descriptor, &element->user_space);
934 if (descriptor->descriptor_id != ACPI_DESC_TYPE_CACHED) {
935 acpi_os_printf ("%p Len %04X %9.9s-%d [%s] ",
936 descriptor, element->size, element->module,
937 element->line, acpi_ut_get_descriptor_name (descriptor));
938
939 /* Most of the elements will be Operand objects. */
940
941 switch (ACPI_GET_DESCRIPTOR_TYPE (descriptor)) {
942 case ACPI_DESC_TYPE_OPERAND:
943 acpi_os_printf ("%12.12s R%hd",
944 acpi_ut_get_type_name (descriptor->object.common.type),
945 descriptor->object.common.reference_count);
946 break;
947
948 case ACPI_DESC_TYPE_PARSER:
949 acpi_os_printf ("aml_opcode %04hX",
950 descriptor->op.asl.aml_opcode);
951 break;
952
953 case ACPI_DESC_TYPE_NAMED:
954 acpi_os_printf ("%4.4s",
955 acpi_ut_get_node_name (&descriptor->node));
956 break;
957
958 default:
959 break;
960 }
961
962 acpi_os_printf ( "\n");
963 num_outstanding++;
964 }
965 }
966 element = element->next;
967 }
968
969 (void) acpi_ut_release_mutex (ACPI_MTX_MEMORY);
970
971 /* Print summary */
972
973 if (!num_outstanding) {
974 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
975 "No outstanding allocations.\n"));
976 }
977 else {
978 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
979 "%d(%X) Outstanding allocations\n",
980 num_outstanding, num_outstanding));
981 }
982
983 return_VOID;
984}
985
986
987#endif /* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */
988