1 | /****************************************************************************** |
2 | * |
3 | * Module Name: uttrack - Memory allocation tracking routines (debug only) |
4 | * |
5 | *****************************************************************************/ |
6 | |
7 | /* |
8 | * Copyright (C) 2000 - 2016, Intel Corp. |
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 | * These procedures are used for tracking memory leaks in the subsystem, and |
46 | * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set. |
47 | * |
48 | * Each memory allocation is tracked via a doubly linked list. Each |
49 | * element contains the caller's component, module name, function name, and |
50 | * line number. AcpiUtAllocate and AcpiUtAllocateZeroed call |
51 | * AcpiUtTrackAllocation to add an element to the list; deletion |
52 | * occurs in the body of AcpiUtFree. |
53 | */ |
54 | |
55 | #include "acpi.h" |
56 | #include "accommon.h" |
57 | |
58 | #ifdef ACPI_DBG_TRACK_ALLOCATIONS |
59 | |
60 | #define _COMPONENT ACPI_UTILITIES |
61 | ACPI_MODULE_NAME ("uttrack" ) |
62 | |
63 | |
64 | /* Local prototypes */ |
65 | |
66 | static ACPI_DEBUG_MEM_BLOCK * |
67 | AcpiUtFindAllocation ( |
68 | ACPI_DEBUG_MEM_BLOCK *Allocation); |
69 | |
70 | static ACPI_STATUS |
71 | AcpiUtTrackAllocation ( |
72 | ACPI_DEBUG_MEM_BLOCK *Address, |
73 | ACPI_SIZE Size, |
74 | UINT8 AllocType, |
75 | UINT32 Component, |
76 | const char *Module, |
77 | UINT32 Line); |
78 | |
79 | static ACPI_STATUS |
80 | AcpiUtRemoveAllocation ( |
81 | ACPI_DEBUG_MEM_BLOCK *Address, |
82 | UINT32 Component, |
83 | const char *Module, |
84 | UINT32 Line); |
85 | |
86 | |
87 | /******************************************************************************* |
88 | * |
89 | * FUNCTION: AcpiUtCreateList |
90 | * |
91 | * PARAMETERS: CacheName - Ascii name for the cache |
92 | * ObjectSize - Size of each cached object |
93 | * ReturnCache - Where the new cache object is returned |
94 | * |
95 | * RETURN: Status |
96 | * |
97 | * DESCRIPTION: Create a local memory list for tracking purposed |
98 | * |
99 | ******************************************************************************/ |
100 | |
101 | ACPI_STATUS |
102 | AcpiUtCreateList ( |
103 | const char *ListName, |
104 | UINT16 ObjectSize, |
105 | ACPI_MEMORY_LIST **ReturnCache) |
106 | { |
107 | ACPI_MEMORY_LIST *Cache; |
108 | |
109 | |
110 | Cache = AcpiOsAllocateZeroed (sizeof (ACPI_MEMORY_LIST)); |
111 | if (!Cache) |
112 | { |
113 | return (AE_NO_MEMORY); |
114 | } |
115 | |
116 | Cache->ListName = ListName; |
117 | Cache->ObjectSize = ObjectSize; |
118 | |
119 | *ReturnCache = Cache; |
120 | return (AE_OK); |
121 | } |
122 | |
123 | |
124 | /******************************************************************************* |
125 | * |
126 | * FUNCTION: AcpiUtAllocateAndTrack |
127 | * |
128 | * PARAMETERS: Size - Size of the allocation |
129 | * Component - Component type of caller |
130 | * Module - Source file name of caller |
131 | * Line - Line number of caller |
132 | * |
133 | * RETURN: Address of the allocated memory on success, NULL on failure. |
134 | * |
135 | * DESCRIPTION: The subsystem's equivalent of malloc. |
136 | * |
137 | ******************************************************************************/ |
138 | |
139 | void * |
140 | AcpiUtAllocateAndTrack ( |
141 | ACPI_SIZE Size, |
142 | UINT32 Component, |
143 | const char *Module, |
144 | UINT32 Line) |
145 | { |
146 | ACPI_DEBUG_MEM_BLOCK *Allocation; |
147 | ACPI_STATUS Status; |
148 | |
149 | |
150 | /* Check for an inadvertent size of zero bytes */ |
151 | |
152 | if (!Size) |
153 | { |
154 | ACPI_WARNING ((Module, Line, |
155 | "Attempt to allocate zero bytes, allocating 1 byte" )); |
156 | Size = 1; |
157 | } |
158 | |
159 | Allocation = AcpiOsAllocate (Size + sizeof (ACPI_DEBUG_MEM_HEADER)); |
160 | if (!Allocation) |
161 | { |
162 | /* Report allocation error */ |
163 | |
164 | ACPI_WARNING ((Module, Line, |
165 | "Could not allocate size %u" , (UINT32) Size)); |
166 | |
167 | return (NULL); |
168 | } |
169 | |
170 | Status = AcpiUtTrackAllocation ( |
171 | Allocation, Size, ACPI_MEM_MALLOC, Component, Module, Line); |
172 | if (ACPI_FAILURE (Status)) |
173 | { |
174 | AcpiOsFree (Allocation); |
175 | return (NULL); |
176 | } |
177 | |
178 | AcpiGbl_GlobalList->TotalAllocated++; |
179 | AcpiGbl_GlobalList->TotalSize += (UINT32) Size; |
180 | AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size; |
181 | |
182 | if (AcpiGbl_GlobalList->CurrentTotalSize > |
183 | AcpiGbl_GlobalList->MaxOccupied) |
184 | { |
185 | AcpiGbl_GlobalList->MaxOccupied = |
186 | AcpiGbl_GlobalList->CurrentTotalSize; |
187 | } |
188 | |
189 | return ((void *) &Allocation->UserSpace); |
190 | } |
191 | |
192 | |
193 | /******************************************************************************* |
194 | * |
195 | * FUNCTION: AcpiUtAllocateZeroedAndTrack |
196 | * |
197 | * PARAMETERS: Size - Size of the allocation |
198 | * Component - Component type of caller |
199 | * Module - Source file name of caller |
200 | * Line - Line number of caller |
201 | * |
202 | * RETURN: Address of the allocated memory on success, NULL on failure. |
203 | * |
204 | * DESCRIPTION: Subsystem equivalent of calloc. |
205 | * |
206 | ******************************************************************************/ |
207 | |
208 | void * |
209 | AcpiUtAllocateZeroedAndTrack ( |
210 | ACPI_SIZE Size, |
211 | UINT32 Component, |
212 | const char *Module, |
213 | UINT32 Line) |
214 | { |
215 | ACPI_DEBUG_MEM_BLOCK *Allocation; |
216 | ACPI_STATUS Status; |
217 | |
218 | |
219 | /* Check for an inadvertent size of zero bytes */ |
220 | |
221 | if (!Size) |
222 | { |
223 | ACPI_WARNING ((Module, Line, |
224 | "Attempt to allocate zero bytes, allocating 1 byte" )); |
225 | Size = 1; |
226 | } |
227 | |
228 | Allocation = AcpiOsAllocateZeroed ( |
229 | Size + sizeof (ACPI_DEBUG_MEM_HEADER)); |
230 | if (!Allocation) |
231 | { |
232 | /* Report allocation error */ |
233 | |
234 | ACPI_ERROR ((Module, Line, |
235 | "Could not allocate size %u" , (UINT32) Size)); |
236 | return (NULL); |
237 | } |
238 | |
239 | Status = AcpiUtTrackAllocation (Allocation, Size, |
240 | ACPI_MEM_CALLOC, Component, Module, Line); |
241 | if (ACPI_FAILURE (Status)) |
242 | { |
243 | AcpiOsFree (Allocation); |
244 | return (NULL); |
245 | } |
246 | |
247 | AcpiGbl_GlobalList->TotalAllocated++; |
248 | AcpiGbl_GlobalList->TotalSize += (UINT32) Size; |
249 | AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size; |
250 | |
251 | if (AcpiGbl_GlobalList->CurrentTotalSize > |
252 | AcpiGbl_GlobalList->MaxOccupied) |
253 | { |
254 | AcpiGbl_GlobalList->MaxOccupied = |
255 | AcpiGbl_GlobalList->CurrentTotalSize; |
256 | } |
257 | |
258 | return ((void *) &Allocation->UserSpace); |
259 | } |
260 | |
261 | |
262 | /******************************************************************************* |
263 | * |
264 | * FUNCTION: AcpiUtFreeAndTrack |
265 | * |
266 | * PARAMETERS: Allocation - Address of the memory to deallocate |
267 | * Component - Component type of caller |
268 | * Module - Source file name of caller |
269 | * Line - Line number of caller |
270 | * |
271 | * RETURN: None |
272 | * |
273 | * DESCRIPTION: Frees the memory at Allocation |
274 | * |
275 | ******************************************************************************/ |
276 | |
277 | void |
278 | AcpiUtFreeAndTrack ( |
279 | void *Allocation, |
280 | UINT32 Component, |
281 | const char *Module, |
282 | UINT32 Line) |
283 | { |
284 | ACPI_DEBUG_MEM_BLOCK *DebugBlock; |
285 | ACPI_STATUS Status; |
286 | |
287 | |
288 | ACPI_FUNCTION_TRACE_PTR (UtFree, Allocation); |
289 | |
290 | |
291 | if (NULL == Allocation) |
292 | { |
293 | ACPI_ERROR ((Module, Line, |
294 | "Attempt to delete a NULL address" )); |
295 | |
296 | return_VOID; |
297 | } |
298 | |
299 | DebugBlock = ACPI_CAST_PTR (ACPI_DEBUG_MEM_BLOCK, |
300 | (((char *) Allocation) - sizeof (ACPI_DEBUG_MEM_HEADER))); |
301 | |
302 | AcpiGbl_GlobalList->TotalFreed++; |
303 | AcpiGbl_GlobalList->CurrentTotalSize -= DebugBlock->Size; |
304 | |
305 | Status = AcpiUtRemoveAllocation (DebugBlock, Component, Module, Line); |
306 | if (ACPI_FAILURE (Status)) |
307 | { |
308 | ACPI_EXCEPTION ((AE_INFO, Status, "Could not free memory" )); |
309 | } |
310 | |
311 | AcpiOsFree (DebugBlock); |
312 | ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n" , |
313 | Allocation, DebugBlock)); |
314 | return_VOID; |
315 | } |
316 | |
317 | |
318 | /******************************************************************************* |
319 | * |
320 | * FUNCTION: AcpiUtFindAllocation |
321 | * |
322 | * PARAMETERS: Allocation - Address of allocated memory |
323 | * |
324 | * RETURN: Three cases: |
325 | * 1) List is empty, NULL is returned. |
326 | * 2) Element was found. Returns Allocation parameter. |
327 | * 3) Element was not found. Returns position where it should be |
328 | * inserted into the list. |
329 | * |
330 | * DESCRIPTION: Searches for an element in the global allocation tracking list. |
331 | * If the element is not found, returns the location within the |
332 | * list where the element should be inserted. |
333 | * |
334 | * Note: The list is ordered by larger-to-smaller addresses. |
335 | * |
336 | * This global list is used to detect memory leaks in ACPICA as |
337 | * well as other issues such as an attempt to release the same |
338 | * internal object more than once. Although expensive as far |
339 | * as cpu time, this list is much more helpful for finding these |
340 | * types of issues than using memory leak detectors outside of |
341 | * the ACPICA code. |
342 | * |
343 | ******************************************************************************/ |
344 | |
345 | static ACPI_DEBUG_MEM_BLOCK * |
346 | AcpiUtFindAllocation ( |
347 | ACPI_DEBUG_MEM_BLOCK *Allocation) |
348 | { |
349 | ACPI_DEBUG_MEM_BLOCK *Element; |
350 | |
351 | |
352 | Element = AcpiGbl_GlobalList->ListHead; |
353 | if (!Element) |
354 | { |
355 | return (NULL); |
356 | } |
357 | |
358 | /* |
359 | * Search for the address. |
360 | * |
361 | * Note: List is ordered by larger-to-smaller addresses, on the |
362 | * assumption that a new allocation usually has a larger address |
363 | * than previous allocations. |
364 | */ |
365 | while (Element > Allocation) |
366 | { |
367 | /* Check for end-of-list */ |
368 | |
369 | if (!Element->Next) |
370 | { |
371 | return (Element); |
372 | } |
373 | |
374 | Element = Element->Next; |
375 | } |
376 | |
377 | if (Element == Allocation) |
378 | { |
379 | return (Element); |
380 | } |
381 | |
382 | return (Element->Previous); |
383 | } |
384 | |
385 | |
386 | /******************************************************************************* |
387 | * |
388 | * FUNCTION: AcpiUtTrackAllocation |
389 | * |
390 | * PARAMETERS: Allocation - Address of allocated memory |
391 | * Size - Size of the allocation |
392 | * AllocType - MEM_MALLOC or MEM_CALLOC |
393 | * Component - Component type of caller |
394 | * Module - Source file name of caller |
395 | * Line - Line number of caller |
396 | * |
397 | * RETURN: Status |
398 | * |
399 | * DESCRIPTION: Inserts an element into the global allocation tracking list. |
400 | * |
401 | ******************************************************************************/ |
402 | |
403 | static ACPI_STATUS |
404 | AcpiUtTrackAllocation ( |
405 | ACPI_DEBUG_MEM_BLOCK *Allocation, |
406 | ACPI_SIZE Size, |
407 | UINT8 AllocType, |
408 | UINT32 Component, |
409 | const char *Module, |
410 | UINT32 Line) |
411 | { |
412 | ACPI_MEMORY_LIST *MemList; |
413 | ACPI_DEBUG_MEM_BLOCK *Element; |
414 | ACPI_STATUS Status = AE_OK; |
415 | |
416 | |
417 | ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation); |
418 | |
419 | |
420 | if (AcpiGbl_DisableMemTracking) |
421 | { |
422 | return_ACPI_STATUS (AE_OK); |
423 | } |
424 | |
425 | MemList = AcpiGbl_GlobalList; |
426 | Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY); |
427 | if (ACPI_FAILURE (Status)) |
428 | { |
429 | return_ACPI_STATUS (Status); |
430 | } |
431 | |
432 | /* |
433 | * Search the global list for this address to make sure it is not |
434 | * already present. This will catch several kinds of problems. |
435 | */ |
436 | Element = AcpiUtFindAllocation (Allocation); |
437 | if (Element == Allocation) |
438 | { |
439 | ACPI_ERROR ((AE_INFO, |
440 | "UtTrackAllocation: Allocation (%p) already present in global list!" , |
441 | Allocation)); |
442 | goto UnlockAndExit; |
443 | } |
444 | |
445 | /* Fill in the instance data */ |
446 | |
447 | Allocation->Size = (UINT32) Size; |
448 | Allocation->AllocType = AllocType; |
449 | Allocation->Component = Component; |
450 | Allocation->Line = Line; |
451 | |
452 | strncpy (Allocation->Module, Module, ACPI_MAX_MODULE_NAME); |
453 | Allocation->Module[ACPI_MAX_MODULE_NAME-1] = 0; |
454 | |
455 | if (!Element) |
456 | { |
457 | /* Insert at list head */ |
458 | |
459 | if (MemList->ListHead) |
460 | { |
461 | ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous = |
462 | Allocation; |
463 | } |
464 | |
465 | Allocation->Next = MemList->ListHead; |
466 | Allocation->Previous = NULL; |
467 | |
468 | MemList->ListHead = Allocation; |
469 | } |
470 | else |
471 | { |
472 | /* Insert after element */ |
473 | |
474 | Allocation->Next = Element->Next; |
475 | Allocation->Previous = Element; |
476 | |
477 | if (Element->Next) |
478 | { |
479 | (Element->Next)->Previous = Allocation; |
480 | } |
481 | |
482 | Element->Next = Allocation; |
483 | } |
484 | |
485 | |
486 | UnlockAndExit: |
487 | Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); |
488 | return_ACPI_STATUS (Status); |
489 | } |
490 | |
491 | |
492 | /******************************************************************************* |
493 | * |
494 | * FUNCTION: AcpiUtRemoveAllocation |
495 | * |
496 | * PARAMETERS: Allocation - Address of allocated memory |
497 | * Component - Component type of caller |
498 | * Module - Source file name of caller |
499 | * Line - Line number of caller |
500 | * |
501 | * RETURN: Status |
502 | * |
503 | * DESCRIPTION: Deletes an element from the global allocation tracking list. |
504 | * |
505 | ******************************************************************************/ |
506 | |
507 | static ACPI_STATUS |
508 | AcpiUtRemoveAllocation ( |
509 | ACPI_DEBUG_MEM_BLOCK *Allocation, |
510 | UINT32 Component, |
511 | const char *Module, |
512 | UINT32 Line) |
513 | { |
514 | ACPI_MEMORY_LIST *MemList; |
515 | ACPI_STATUS Status; |
516 | |
517 | |
518 | ACPI_FUNCTION_NAME (UtRemoveAllocation); |
519 | |
520 | |
521 | if (AcpiGbl_DisableMemTracking) |
522 | { |
523 | return (AE_OK); |
524 | } |
525 | |
526 | MemList = AcpiGbl_GlobalList; |
527 | if (NULL == MemList->ListHead) |
528 | { |
529 | /* No allocations! */ |
530 | |
531 | ACPI_ERROR ((Module, Line, |
532 | "Empty allocation list, nothing to free!" )); |
533 | |
534 | return (AE_OK); |
535 | } |
536 | |
537 | Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY); |
538 | if (ACPI_FAILURE (Status)) |
539 | { |
540 | return (Status); |
541 | } |
542 | |
543 | /* Unlink */ |
544 | |
545 | if (Allocation->Previous) |
546 | { |
547 | (Allocation->Previous)->Next = Allocation->Next; |
548 | } |
549 | else |
550 | { |
551 | MemList->ListHead = Allocation->Next; |
552 | } |
553 | |
554 | if (Allocation->Next) |
555 | { |
556 | (Allocation->Next)->Previous = Allocation->Previous; |
557 | } |
558 | |
559 | ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n" , |
560 | &Allocation->UserSpace, Allocation->Size)); |
561 | |
562 | /* Mark the segment as deleted */ |
563 | |
564 | memset (&Allocation->UserSpace, 0xEA, Allocation->Size); |
565 | |
566 | Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); |
567 | return (Status); |
568 | } |
569 | |
570 | |
571 | /******************************************************************************* |
572 | * |
573 | * FUNCTION: AcpiUtDumpAllocationInfo |
574 | * |
575 | * PARAMETERS: None |
576 | * |
577 | * RETURN: None |
578 | * |
579 | * DESCRIPTION: Print some info about the outstanding allocations. |
580 | * |
581 | ******************************************************************************/ |
582 | |
583 | void |
584 | AcpiUtDumpAllocationInfo ( |
585 | void) |
586 | { |
587 | /* |
588 | ACPI_MEMORY_LIST *MemList; |
589 | */ |
590 | |
591 | ACPI_FUNCTION_TRACE (UtDumpAllocationInfo); |
592 | |
593 | /* |
594 | ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, |
595 | ("%30s: %4d (%3d Kb)\n", "Current allocations", |
596 | MemList->CurrentCount, |
597 | ROUND_UP_TO_1K (MemList->CurrentSize))); |
598 | |
599 | ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, |
600 | ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations", |
601 | MemList->MaxConcurrentCount, |
602 | ROUND_UP_TO_1K (MemList->MaxConcurrentSize))); |
603 | |
604 | |
605 | ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, |
606 | ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects", |
607 | RunningObjectCount, |
608 | ROUND_UP_TO_1K (RunningObjectSize))); |
609 | |
610 | ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, |
611 | ("%30s: %4d (%3d Kb)\n", "Total (all) allocations", |
612 | RunningAllocCount, |
613 | ROUND_UP_TO_1K (RunningAllocSize))); |
614 | |
615 | |
616 | ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, |
617 | ("%30s: %4d (%3d Kb)\n", "Current Nodes", |
618 | AcpiGbl_CurrentNodeCount, |
619 | ROUND_UP_TO_1K (AcpiGbl_CurrentNodeSize))); |
620 | |
621 | ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, |
622 | ("%30s: %4d (%3d Kb)\n", "Max Nodes", |
623 | AcpiGbl_MaxConcurrentNodeCount, |
624 | ROUND_UP_TO_1K ((AcpiGbl_MaxConcurrentNodeCount * |
625 | sizeof (ACPI_NAMESPACE_NODE))))); |
626 | */ |
627 | return_VOID; |
628 | } |
629 | |
630 | |
631 | /******************************************************************************* |
632 | * |
633 | * FUNCTION: AcpiUtDumpAllocations |
634 | * |
635 | * PARAMETERS: Component - Component(s) to dump info for. |
636 | * Module - Module to dump info for. NULL means all. |
637 | * |
638 | * RETURN: None |
639 | * |
640 | * DESCRIPTION: Print a list of all outstanding allocations. |
641 | * |
642 | ******************************************************************************/ |
643 | |
644 | void |
645 | AcpiUtDumpAllocations ( |
646 | UINT32 Component, |
647 | const char *Module) |
648 | { |
649 | ACPI_DEBUG_MEM_BLOCK *Element; |
650 | ACPI_DESCRIPTOR *Descriptor; |
651 | UINT32 NumOutstanding = 0; |
652 | UINT8 DescriptorType; |
653 | |
654 | |
655 | ACPI_FUNCTION_TRACE (UtDumpAllocations); |
656 | |
657 | |
658 | if (AcpiGbl_DisableMemTracking) |
659 | { |
660 | return_VOID; |
661 | } |
662 | |
663 | /* |
664 | * Walk the allocation list. |
665 | */ |
666 | if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY))) |
667 | { |
668 | return_VOID; |
669 | } |
670 | |
671 | Element = AcpiGbl_GlobalList->ListHead; |
672 | while (Element) |
673 | { |
674 | if ((Element->Component & Component) && |
675 | ((Module == NULL) || (0 == strcmp (Module, Element->Module)))) |
676 | { |
677 | Descriptor = ACPI_CAST_PTR ( |
678 | ACPI_DESCRIPTOR, &Element->UserSpace); |
679 | |
680 | if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR)) |
681 | { |
682 | AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u " |
683 | "[Not a Descriptor - too small]\n" , |
684 | Descriptor, Element->Size, Element->Module, |
685 | Element->Line); |
686 | } |
687 | else |
688 | { |
689 | /* Ignore allocated objects that are in a cache */ |
690 | |
691 | if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != |
692 | ACPI_DESC_TYPE_CACHED) |
693 | { |
694 | AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u [%s] " , |
695 | Descriptor, Element->Size, Element->Module, |
696 | Element->Line, AcpiUtGetDescriptorName (Descriptor)); |
697 | |
698 | /* Validate the descriptor type using Type field and length */ |
699 | |
700 | DescriptorType = 0; /* Not a valid descriptor type */ |
701 | |
702 | switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor)) |
703 | { |
704 | case ACPI_DESC_TYPE_OPERAND: |
705 | |
706 | if (Element->Size == sizeof (ACPI_OPERAND_OBJECT)) |
707 | { |
708 | DescriptorType = ACPI_DESC_TYPE_OPERAND; |
709 | } |
710 | break; |
711 | |
712 | case ACPI_DESC_TYPE_PARSER: |
713 | |
714 | if (Element->Size == sizeof (ACPI_PARSE_OBJECT)) |
715 | { |
716 | DescriptorType = ACPI_DESC_TYPE_PARSER; |
717 | } |
718 | break; |
719 | |
720 | case ACPI_DESC_TYPE_NAMED: |
721 | |
722 | if (Element->Size == sizeof (ACPI_NAMESPACE_NODE)) |
723 | { |
724 | DescriptorType = ACPI_DESC_TYPE_NAMED; |
725 | } |
726 | break; |
727 | |
728 | default: |
729 | |
730 | break; |
731 | } |
732 | |
733 | /* Display additional info for the major descriptor types */ |
734 | |
735 | switch (DescriptorType) |
736 | { |
737 | case ACPI_DESC_TYPE_OPERAND: |
738 | |
739 | AcpiOsPrintf ("%12.12s RefCount 0x%04X\n" , |
740 | AcpiUtGetTypeName (Descriptor->Object.Common.Type), |
741 | Descriptor->Object.Common.ReferenceCount); |
742 | break; |
743 | |
744 | case ACPI_DESC_TYPE_PARSER: |
745 | |
746 | AcpiOsPrintf ("AmlOpcode 0x%04hX\n" , |
747 | Descriptor->Op.Asl.AmlOpcode); |
748 | break; |
749 | |
750 | case ACPI_DESC_TYPE_NAMED: |
751 | |
752 | AcpiOsPrintf ("%4.4s\n" , |
753 | AcpiUtGetNodeName (&Descriptor->Node)); |
754 | break; |
755 | |
756 | default: |
757 | |
758 | AcpiOsPrintf ( "\n" ); |
759 | break; |
760 | } |
761 | } |
762 | } |
763 | |
764 | NumOutstanding++; |
765 | } |
766 | |
767 | Element = Element->Next; |
768 | } |
769 | |
770 | (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY); |
771 | |
772 | /* Print summary */ |
773 | |
774 | if (!NumOutstanding) |
775 | { |
776 | ACPI_INFO (("No outstanding allocations" )); |
777 | } |
778 | else |
779 | { |
780 | ACPI_ERROR ((AE_INFO, "%u(0x%X) Outstanding allocations" , |
781 | NumOutstanding, NumOutstanding)); |
782 | } |
783 | |
784 | return_VOID; |
785 | } |
786 | |
787 | #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ |
788 | |