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