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(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(sizeof(struct acpi_memory_list));
99 if (!cache) {
100 return (AE_NO_MEMORY);
101 }
102
103 memset(cache, 0, sizeof(struct acpi_memory_list));
104
105 cache->list_name = list_name;
106 cache->object_size = object_size;
107
108 *return_cache = cache;
109 return (AE_OK);
110}
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127void *acpi_ut_allocate_and_track(acpi_size size,
128 u32 component, const char *module, u32 line)
129{
130 struct acpi_debug_mem_block *allocation;
131 acpi_status status;
132
133
134
135 if (!size) {
136 ACPI_WARNING((module, line,
137 "Attempt to allocate zero bytes, allocating 1 byte"));
138 size = 1;
139 }
140
141 allocation =
142 acpi_os_allocate(size + sizeof(struct acpi_debug_mem_header));
143 if (!allocation) {
144
145
146
147 ACPI_WARNING((module, line,
148 "Could not allocate size %u", (u32)size));
149
150 return (NULL);
151 }
152
153 status = acpi_ut_track_allocation(allocation, size,
154 ACPI_MEM_MALLOC, component, module,
155 line);
156 if (ACPI_FAILURE(status)) {
157 acpi_os_free(allocation);
158 return (NULL);
159 }
160
161 acpi_gbl_global_list->total_allocated++;
162 acpi_gbl_global_list->total_size += (u32)size;
163 acpi_gbl_global_list->current_total_size += (u32)size;
164 if (acpi_gbl_global_list->current_total_size >
165 acpi_gbl_global_list->max_occupied) {
166 acpi_gbl_global_list->max_occupied =
167 acpi_gbl_global_list->current_total_size;
168 }
169
170 return ((void *)&allocation->user_space);
171}
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
189 u32 component,
190 const char *module, u32 line)
191{
192 struct acpi_debug_mem_block *allocation;
193 acpi_status status;
194
195
196
197 if (!size) {
198 ACPI_WARNING((module, line,
199 "Attempt to allocate zero bytes, allocating 1 byte"));
200 size = 1;
201 }
202
203 allocation =
204 acpi_os_allocate_zeroed(size +
205 sizeof(struct acpi_debug_mem_header));
206 if (!allocation) {
207
208
209
210 ACPI_ERROR((module, line,
211 "Could not allocate size %u", (u32)size));
212 return (NULL);
213 }
214
215 status = acpi_ut_track_allocation(allocation, size,
216 ACPI_MEM_CALLOC, component, module,
217 line);
218 if (ACPI_FAILURE(status)) {
219 acpi_os_free(allocation);
220 return (NULL);
221 }
222
223 acpi_gbl_global_list->total_allocated++;
224 acpi_gbl_global_list->total_size += (u32)size;
225 acpi_gbl_global_list->current_total_size += (u32)size;
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 = acpi_ut_remove_allocation(debug_block,
273 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\n", allocation));
280 return_VOID;
281}
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
310static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
311 acpi_debug_mem_block
312 *allocation)
313{
314 struct acpi_debug_mem_block *element;
315
316 element = acpi_gbl_global_list->list_head;
317 if (!element) {
318 return (NULL);
319 }
320
321
322
323
324
325
326
327
328 while (element > allocation) {
329
330
331
332 if (!element->next) {
333 return (element);
334 }
335
336 element = element->next;
337 }
338
339 if (element == allocation) {
340 return (element);
341 }
342
343 return (element->previous);
344}
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363static acpi_status
364acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
365 acpi_size size,
366 u8 alloc_type,
367 u32 component, const char *module, u32 line)
368{
369 struct acpi_memory_list *mem_list;
370 struct acpi_debug_mem_block *element;
371 acpi_status status = AE_OK;
372
373 ACPI_FUNCTION_TRACE_PTR(ut_track_allocation, allocation);
374
375 if (acpi_gbl_disable_mem_tracking) {
376 return_ACPI_STATUS(AE_OK);
377 }
378
379 mem_list = acpi_gbl_global_list;
380 status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
381 if (ACPI_FAILURE(status)) {
382 return_ACPI_STATUS(status);
383 }
384
385
386
387
388
389 element = acpi_ut_find_allocation(allocation);
390 if (element == allocation) {
391 ACPI_ERROR((AE_INFO,
392 "UtTrackAllocation: Allocation (%p) already present in global list!",
393 allocation));
394 goto unlock_and_exit;
395 }
396
397
398
399 allocation->size = (u32)size;
400 allocation->alloc_type = alloc_type;
401 allocation->component = component;
402 allocation->line = line;
403
404 strncpy(allocation->module, module, ACPI_MAX_MODULE_NAME);
405 allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0;
406
407 if (!element) {
408
409
410
411 if (mem_list->list_head) {
412 ((struct acpi_debug_mem_block *)(mem_list->list_head))->
413 previous = allocation;
414 }
415
416 allocation->next = mem_list->list_head;
417 allocation->previous = NULL;
418
419 mem_list->list_head = allocation;
420 } else {
421
422
423 allocation->next = element->next;
424 allocation->previous = element;
425
426 if (element->next) {
427 (element->next)->previous = allocation;
428 }
429
430 element->next = allocation;
431 }
432
433 unlock_and_exit:
434 status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
435 return_ACPI_STATUS(status);
436}
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453static acpi_status
454acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
455 u32 component, const char *module, u32 line)
456{
457 struct acpi_memory_list *mem_list;
458 acpi_status status;
459
460 ACPI_FUNCTION_NAME(ut_remove_allocation);
461
462 if (acpi_gbl_disable_mem_tracking) {
463 return (AE_OK);
464 }
465
466 mem_list = acpi_gbl_global_list;
467 if (NULL == mem_list->list_head) {
468
469
470
471 ACPI_ERROR((module, line,
472 "Empty allocation list, nothing to free!"));
473
474 return (AE_OK);
475 }
476
477 status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
478 if (ACPI_FAILURE(status)) {
479 return (status);
480 }
481
482
483
484 if (allocation->previous) {
485 (allocation->previous)->next = allocation->next;
486 } else {
487 mem_list->list_head = allocation->next;
488 }
489
490 if (allocation->next) {
491 (allocation->next)->previous = allocation->previous;
492 }
493
494 ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
495 &allocation->user_space, allocation->size));
496
497
498
499 memset(&allocation->user_space, 0xEA, allocation->size);
500
501 status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
502 return (status);
503}
504
505
506
507
508
509
510
511
512
513
514
515
516
517void acpi_ut_dump_allocation_info(void)
518{
519
520
521
522
523 ACPI_FUNCTION_TRACE(ut_dump_allocation_info);
524
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 return_VOID;
558}
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573void acpi_ut_dump_allocations(u32 component, const char *module)
574{
575 struct acpi_debug_mem_block *element;
576 union acpi_descriptor *descriptor;
577 u32 num_outstanding = 0;
578 u8 descriptor_type;
579
580 ACPI_FUNCTION_TRACE(ut_dump_allocations);
581
582 if (acpi_gbl_disable_mem_tracking) {
583 return_VOID;
584 }
585
586
587
588
589 if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
590 return_VOID;
591 }
592
593 element = acpi_gbl_global_list->list_head;
594 while (element) {
595 if ((element->component & component) &&
596 ((module == NULL)
597 || (0 == strcmp(module, element->module)))) {
598 descriptor =
599 ACPI_CAST_PTR(union acpi_descriptor,
600 &element->user_space);
601
602 if (element->size <
603 sizeof(struct acpi_common_descriptor)) {
604 acpi_os_printf("%p Length 0x%04X %9.9s-%u "
605 "[Not a Descriptor - too small]\n",
606 descriptor, element->size,
607 element->module, element->line);
608 } else {
609
610
611 if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) !=
612 ACPI_DESC_TYPE_CACHED) {
613 acpi_os_printf
614 ("%p Length 0x%04X %9.9s-%u [%s] ",
615 descriptor, element->size,
616 element->module, element->line,
617 acpi_ut_get_descriptor_name
618 (descriptor));
619
620
621
622 descriptor_type = 0;
623
624 switch (ACPI_GET_DESCRIPTOR_TYPE
625 (descriptor)) {
626 case ACPI_DESC_TYPE_OPERAND:
627
628 if (element->size ==
629 sizeof(union
630 acpi_operand_object))
631 {
632 descriptor_type =
633 ACPI_DESC_TYPE_OPERAND;
634 }
635 break;
636
637 case ACPI_DESC_TYPE_PARSER:
638
639 if (element->size ==
640 sizeof(union
641 acpi_parse_object)) {
642 descriptor_type =
643 ACPI_DESC_TYPE_PARSER;
644 }
645 break;
646
647 case ACPI_DESC_TYPE_NAMED:
648
649 if (element->size ==
650 sizeof(struct
651 acpi_namespace_node))
652 {
653 descriptor_type =
654 ACPI_DESC_TYPE_NAMED;
655 }
656 break;
657
658 default:
659
660 break;
661 }
662
663
664
665 switch (descriptor_type) {
666 case ACPI_DESC_TYPE_OPERAND:
667
668 acpi_os_printf
669 ("%12.12s RefCount 0x%04X\n",
670 acpi_ut_get_type_name
671 (descriptor->object.common.
672 type),
673 descriptor->object.common.
674 reference_count);
675 break;
676
677 case ACPI_DESC_TYPE_PARSER:
678
679 acpi_os_printf
680 ("AmlOpcode 0x%04hX\n",
681 descriptor->op.asl.
682 aml_opcode);
683 break;
684
685 case ACPI_DESC_TYPE_NAMED:
686
687 acpi_os_printf("%4.4s\n",
688 acpi_ut_get_node_name
689 (&descriptor->
690 node));
691 break;
692
693 default:
694
695 acpi_os_printf("\n");
696 break;
697 }
698 }
699 }
700
701 num_outstanding++;
702 }
703
704 element = element->next;
705 }
706
707 (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
708
709
710
711 if (!num_outstanding) {
712 ACPI_INFO((AE_INFO, "No outstanding allocations"));
713 } else {
714 ACPI_ERROR((AE_INFO, "%u(0x%X) Outstanding allocations",
715 num_outstanding, num_outstanding));
716 }
717
718 return_VOID;
719}
720
721#endif
722