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