1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55#include <acpi/acpi.h>
56#include "accommon.h"
57
58#ifdef ACPI_DBG_TRACK_ALLOCATIONS
59
60#define _COMPONENT ACPI_UTILITIES
61ACPI_MODULE_NAME("uttrack")
62
63
64static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
65 acpi_debug_mem_block
66 *allocation);
67
68static acpi_status
69acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
70 acpi_size size,
71 u8 alloc_type,
72 u32 component, const char *module, u32 line);
73
74static acpi_status
75acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
76 u32 component, const char *module, u32 line);
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92acpi_status
93acpi_ut_create_list(const char *list_name,
94 u16 object_size, struct acpi_memory_list **return_cache)
95{
96 struct acpi_memory_list *cache;
97
98 cache = acpi_os_allocate_zeroed(sizeof(struct acpi_memory_list));
99 if (!cache) {
100 return (AE_NO_MEMORY);
101 }
102
103 cache->list_name = list_name;
104 cache->object_size = object_size;
105
106 *return_cache = cache;
107 return (AE_OK);
108}
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125void *acpi_ut_allocate_and_track(acpi_size size,
126 u32 component, const char *module, u32 line)
127{
128 struct acpi_debug_mem_block *allocation;
129 acpi_status status;
130
131
132
133 if (!size) {
134 ACPI_WARNING((module, line,
135 "Attempt to allocate zero bytes, allocating 1 byte"));
136 size = 1;
137 }
138
139 allocation =
140 acpi_os_allocate(size + sizeof(struct acpi_debug_mem_header));
141 if (!allocation) {
142
143
144
145 ACPI_WARNING((module, line,
146 "Could not allocate size %u", (u32)size));
147
148 return (NULL);
149 }
150
151 status =
152 acpi_ut_track_allocation(allocation, size, ACPI_MEM_MALLOC,
153 component, module, line);
154 if (ACPI_FAILURE(status)) {
155 acpi_os_free(allocation);
156 return (NULL);
157 }
158
159 acpi_gbl_global_list->total_allocated++;
160 acpi_gbl_global_list->total_size += (u32)size;
161 acpi_gbl_global_list->current_total_size += (u32)size;
162
163 if (acpi_gbl_global_list->current_total_size >
164 acpi_gbl_global_list->max_occupied) {
165 acpi_gbl_global_list->max_occupied =
166 acpi_gbl_global_list->current_total_size;
167 }
168
169 return ((void *)&allocation->user_space);
170}
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
188 u32 component,
189 const char *module, u32 line)
190{
191 struct acpi_debug_mem_block *allocation;
192 acpi_status status;
193
194
195
196 if (!size) {
197 ACPI_WARNING((module, line,
198 "Attempt to allocate zero bytes, allocating 1 byte"));
199 size = 1;
200 }
201
202 allocation =
203 acpi_os_allocate_zeroed(size +
204 sizeof(struct acpi_debug_mem_header));
205 if (!allocation) {
206
207
208
209 ACPI_ERROR((module, line,
210 "Could not allocate size %u", (u32)size));
211 return (NULL);
212 }
213
214 status = acpi_ut_track_allocation(allocation, size,
215 ACPI_MEM_CALLOC, component, module,
216 line);
217 if (ACPI_FAILURE(status)) {
218 acpi_os_free(allocation);
219 return (NULL);
220 }
221
222 acpi_gbl_global_list->total_allocated++;
223 acpi_gbl_global_list->total_size += (u32)size;
224 acpi_gbl_global_list->current_total_size += (u32)size;
225
226 if (acpi_gbl_global_list->current_total_size >
227 acpi_gbl_global_list->max_occupied) {
228 acpi_gbl_global_list->max_occupied =
229 acpi_gbl_global_list->current_total_size;
230 }
231
232 return ((void *)&allocation->user_space);
233}
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250void
251acpi_ut_free_and_track(void *allocation,
252 u32 component, const char *module, u32 line)
253{
254 struct acpi_debug_mem_block *debug_block;
255 acpi_status status;
256
257 ACPI_FUNCTION_TRACE_PTR(ut_free, allocation);
258
259 if (NULL == allocation) {
260 ACPI_ERROR((module, line, "Attempt to delete a NULL address"));
261
262 return_VOID;
263 }
264
265 debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block,
266 (((char *)allocation) -
267 sizeof(struct acpi_debug_mem_header)));
268
269 acpi_gbl_global_list->total_freed++;
270 acpi_gbl_global_list->current_total_size -= debug_block->size;
271
272 status =
273 acpi_ut_remove_allocation(debug_block, component, module, line);
274 if (ACPI_FAILURE(status)) {
275 ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
276 }
277
278 acpi_os_free(debug_block);
279 ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n",
280 allocation, debug_block));
281 return_VOID;
282}
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
312 acpi_debug_mem_block
313 *allocation)
314{
315 struct acpi_debug_mem_block *element;
316
317 element = acpi_gbl_global_list->list_head;
318 if (!element) {
319 return (NULL);
320 }
321
322
323
324
325
326
327
328
329 while (element > allocation) {
330
331
332
333 if (!element->next) {
334 return (element);
335 }
336
337 element = element->next;
338 }
339
340 if (element == allocation) {
341 return (element);
342 }
343
344 return (element->previous);
345}
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364static acpi_status
365acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
366 acpi_size size,
367 u8 alloc_type,
368 u32 component, const char *module, u32 line)
369{
370 struct acpi_memory_list *mem_list;
371 struct acpi_debug_mem_block *element;
372 acpi_status status = AE_OK;
373
374 ACPI_FUNCTION_TRACE_PTR(ut_track_allocation, allocation);
375
376 if (acpi_gbl_disable_mem_tracking) {
377 return_ACPI_STATUS(AE_OK);
378 }
379
380 mem_list = acpi_gbl_global_list;
381 status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
382 if (ACPI_FAILURE(status)) {
383 return_ACPI_STATUS(status);
384 }
385
386
387
388
389
390 element = acpi_ut_find_allocation(allocation);
391 if (element == allocation) {
392 ACPI_ERROR((AE_INFO,
393 "UtTrackAllocation: Allocation (%p) already present in global list!",
394 allocation));
395 goto unlock_and_exit;
396 }
397
398
399
400 allocation->size = (u32)size;
401 allocation->alloc_type = alloc_type;
402 allocation->component = component;
403 allocation->line = line;
404
405 strncpy(allocation->module, module, ACPI_MAX_MODULE_NAME);
406 allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0;
407
408 if (!element) {
409
410
411
412 if (mem_list->list_head) {
413 ((struct acpi_debug_mem_block *)(mem_list->list_head))->
414 previous = allocation;
415 }
416
417 allocation->next = mem_list->list_head;
418 allocation->previous = NULL;
419
420 mem_list->list_head = allocation;
421 } else {
422
423
424 allocation->next = element->next;
425 allocation->previous = element;
426
427 if (element->next) {
428 (element->next)->previous = allocation;
429 }
430
431 element->next = allocation;
432 }
433
434unlock_and_exit:
435 status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
436 return_ACPI_STATUS(status);
437}
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454static acpi_status
455acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
456 u32 component, const char *module, u32 line)
457{
458 struct acpi_memory_list *mem_list;
459 acpi_status status;
460
461 ACPI_FUNCTION_NAME(ut_remove_allocation);
462
463 if (acpi_gbl_disable_mem_tracking) {
464 return (AE_OK);
465 }
466
467 mem_list = acpi_gbl_global_list;
468 if (NULL == mem_list->list_head) {
469
470
471
472 ACPI_ERROR((module, line,
473 "Empty allocation list, nothing to free!"));
474
475 return (AE_OK);
476 }
477
478 status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
479 if (ACPI_FAILURE(status)) {
480 return (status);
481 }
482
483
484
485 if (allocation->previous) {
486 (allocation->previous)->next = allocation->next;
487 } else {
488 mem_list->list_head = allocation->next;
489 }
490
491 if (allocation->next) {
492 (allocation->next)->previous = allocation->previous;
493 }
494
495 ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
496 &allocation->user_space, allocation->size));
497
498
499
500 memset(&allocation->user_space, 0xEA, allocation->size);
501
502 status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
503 return (status);
504}
505
506
507
508
509
510
511
512
513
514
515
516
517
518void acpi_ut_dump_allocation_info(void)
519{
520
521
522
523
524 ACPI_FUNCTION_TRACE(ut_dump_allocation_info);
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558 return_VOID;
559}
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574void acpi_ut_dump_allocations(u32 component, const char *module)
575{
576 struct acpi_debug_mem_block *element;
577 union acpi_descriptor *descriptor;
578 u32 num_outstanding = 0;
579 u8 descriptor_type;
580
581 ACPI_FUNCTION_TRACE(ut_dump_allocations);
582
583 if (acpi_gbl_disable_mem_tracking) {
584 return_VOID;
585 }
586
587
588
589
590 if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
591 return_VOID;
592 }
593
594 if (!acpi_gbl_global_list) {
595 goto exit;
596 }
597
598 element = acpi_gbl_global_list->list_head;
599 while (element) {
600 if ((element->component & component) &&
601 ((module == NULL)
602 || (0 == strcmp(module, element->module)))) {
603 descriptor =
604 ACPI_CAST_PTR(union acpi_descriptor,
605 &element->user_space);
606
607 if (element->size <
608 sizeof(struct acpi_common_descriptor)) {
609 acpi_os_printf("%p Length 0x%04X %9.9s-%4.4u "
610 "[Not a Descriptor - too small]\n",
611 descriptor, element->size,
612 element->module, element->line);
613 } else {
614
615
616 if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) !=
617 ACPI_DESC_TYPE_CACHED) {
618 acpi_os_printf
619 ("%p Length 0x%04X %9.9s-%4.4u [%s] ",
620 descriptor, element->size,
621 element->module, element->line,
622 acpi_ut_get_descriptor_name
623 (descriptor));
624
625
626
627 descriptor_type = 0;
628
629 switch (ACPI_GET_DESCRIPTOR_TYPE
630 (descriptor)) {
631 case ACPI_DESC_TYPE_OPERAND:
632
633 if (element->size ==
634 sizeof(union
635 acpi_operand_object))
636 {
637 descriptor_type =
638 ACPI_DESC_TYPE_OPERAND;
639 }
640 break;
641
642 case ACPI_DESC_TYPE_PARSER:
643
644 if (element->size ==
645 sizeof(union
646 acpi_parse_object)) {
647 descriptor_type =
648 ACPI_DESC_TYPE_PARSER;
649 }
650 break;
651
652 case ACPI_DESC_TYPE_NAMED:
653
654 if (element->size ==
655 sizeof(struct
656 acpi_namespace_node))
657 {
658 descriptor_type =
659 ACPI_DESC_TYPE_NAMED;
660 }
661 break;
662
663 default:
664
665 break;
666 }
667
668
669
670 switch (descriptor_type) {
671 case ACPI_DESC_TYPE_OPERAND:
672
673 acpi_os_printf
674 ("%12.12s RefCount 0x%04X\n",
675 acpi_ut_get_type_name
676 (descriptor->object.common.
677 type),
678 descriptor->object.common.
679 reference_count);
680 break;
681
682 case ACPI_DESC_TYPE_PARSER:
683
684 acpi_os_printf
685 ("AmlOpcode 0x%04hX\n",
686 descriptor->op.asl.
687 aml_opcode);
688 break;
689
690 case ACPI_DESC_TYPE_NAMED:
691
692 acpi_os_printf("%4.4s\n",
693 acpi_ut_get_node_name
694 (&descriptor->
695 node));
696 break;
697
698 default:
699
700 acpi_os_printf("\n");
701 break;
702 }
703 }
704 }
705
706 num_outstanding++;
707 }
708
709 element = element->next;
710 }
711
712exit:
713 (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
714
715
716
717 if (!num_outstanding) {
718 ACPI_INFO(("No outstanding allocations"));
719 } else {
720 ACPI_ERROR((AE_INFO, "%u(0x%X) Outstanding allocations",
721 num_outstanding, num_outstanding));
722 }
723
724 return_VOID;
725}
726
727#endif
728