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