0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #include <acpi/acpi.h>
0022 #include "accommon.h"
0023
0024 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
0025
0026 #define _COMPONENT ACPI_UTILITIES
0027 ACPI_MODULE_NAME("uttrack")
0028
0029
0030 static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
0031 acpi_debug_mem_block
0032 *allocation);
0033
0034 static acpi_status
0035 acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
0036 acpi_size size,
0037 u8 alloc_type,
0038 u32 component, const char *module, u32 line);
0039
0040 static acpi_status
0041 acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
0042 u32 component, const char *module, u32 line);
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 acpi_status
0059 acpi_ut_create_list(const char *list_name,
0060 u16 object_size, struct acpi_memory_list **return_cache)
0061 {
0062 struct acpi_memory_list *cache;
0063
0064 cache = acpi_os_allocate_zeroed(sizeof(struct acpi_memory_list));
0065 if (!cache) {
0066 return (AE_NO_MEMORY);
0067 }
0068
0069 cache->list_name = list_name;
0070 cache->object_size = object_size;
0071
0072 *return_cache = cache;
0073 return (AE_OK);
0074 }
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 void *acpi_ut_allocate_and_track(acpi_size size,
0092 u32 component, const char *module, u32 line)
0093 {
0094 struct acpi_debug_mem_block *allocation;
0095 acpi_status status;
0096
0097
0098
0099 if (!size) {
0100 ACPI_WARNING((module, line,
0101 "Attempt to allocate zero bytes, allocating 1 byte"));
0102 size = 1;
0103 }
0104
0105 allocation =
0106 acpi_os_allocate(size + sizeof(struct acpi_debug_mem_header));
0107 if (!allocation) {
0108
0109
0110
0111 ACPI_WARNING((module, line,
0112 "Could not allocate size %u", (u32)size));
0113
0114 return (NULL);
0115 }
0116
0117 status =
0118 acpi_ut_track_allocation(allocation, size, ACPI_MEM_MALLOC,
0119 component, module, line);
0120 if (ACPI_FAILURE(status)) {
0121 acpi_os_free(allocation);
0122 return (NULL);
0123 }
0124
0125 acpi_gbl_global_list->total_allocated++;
0126 acpi_gbl_global_list->total_size += (u32)size;
0127 acpi_gbl_global_list->current_total_size += (u32)size;
0128
0129 if (acpi_gbl_global_list->current_total_size >
0130 acpi_gbl_global_list->max_occupied) {
0131 acpi_gbl_global_list->max_occupied =
0132 acpi_gbl_global_list->current_total_size;
0133 }
0134
0135 return ((void *)&allocation->user_space);
0136 }
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153 void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
0154 u32 component,
0155 const char *module, u32 line)
0156 {
0157 struct acpi_debug_mem_block *allocation;
0158 acpi_status status;
0159
0160
0161
0162 if (!size) {
0163 ACPI_WARNING((module, line,
0164 "Attempt to allocate zero bytes, allocating 1 byte"));
0165 size = 1;
0166 }
0167
0168 allocation =
0169 acpi_os_allocate_zeroed(size +
0170 sizeof(struct acpi_debug_mem_header));
0171 if (!allocation) {
0172
0173
0174
0175 ACPI_ERROR((module, line,
0176 "Could not allocate size %u", (u32)size));
0177 return (NULL);
0178 }
0179
0180 status = acpi_ut_track_allocation(allocation, size,
0181 ACPI_MEM_CALLOC, component, module,
0182 line);
0183 if (ACPI_FAILURE(status)) {
0184 acpi_os_free(allocation);
0185 return (NULL);
0186 }
0187
0188 acpi_gbl_global_list->total_allocated++;
0189 acpi_gbl_global_list->total_size += (u32)size;
0190 acpi_gbl_global_list->current_total_size += (u32)size;
0191
0192 if (acpi_gbl_global_list->current_total_size >
0193 acpi_gbl_global_list->max_occupied) {
0194 acpi_gbl_global_list->max_occupied =
0195 acpi_gbl_global_list->current_total_size;
0196 }
0197
0198 return ((void *)&allocation->user_space);
0199 }
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216 void
0217 acpi_ut_free_and_track(void *allocation,
0218 u32 component, const char *module, u32 line)
0219 {
0220 struct acpi_debug_mem_block *debug_block;
0221 acpi_status status;
0222
0223 ACPI_FUNCTION_TRACE_PTR(ut_free, allocation);
0224
0225 if (NULL == allocation) {
0226 ACPI_ERROR((module, line, "Attempt to delete a NULL address"));
0227
0228 return_VOID;
0229 }
0230
0231 debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block,
0232 (((char *)allocation) -
0233 sizeof(struct acpi_debug_mem_header)));
0234
0235 acpi_gbl_global_list->total_freed++;
0236 acpi_gbl_global_list->current_total_size -= debug_block->size;
0237
0238 status =
0239 acpi_ut_remove_allocation(debug_block, component, module, line);
0240 if (ACPI_FAILURE(status)) {
0241 ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
0242 }
0243
0244 acpi_os_free(debug_block);
0245 ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n",
0246 allocation, debug_block));
0247 return_VOID;
0248 }
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
0278 acpi_debug_mem_block
0279 *allocation)
0280 {
0281 struct acpi_debug_mem_block *element;
0282
0283 element = acpi_gbl_global_list->list_head;
0284 if (!element) {
0285 return (NULL);
0286 }
0287
0288
0289
0290
0291
0292
0293
0294
0295 while (element > allocation) {
0296
0297
0298
0299 if (!element->next) {
0300 return (element);
0301 }
0302
0303 element = element->next;
0304 }
0305
0306 if (element == allocation) {
0307 return (element);
0308 }
0309
0310 return (element->previous);
0311 }
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330 static acpi_status
0331 acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
0332 acpi_size size,
0333 u8 alloc_type,
0334 u32 component, const char *module, u32 line)
0335 {
0336 struct acpi_memory_list *mem_list;
0337 struct acpi_debug_mem_block *element;
0338 acpi_status status = AE_OK;
0339
0340 ACPI_FUNCTION_TRACE_PTR(ut_track_allocation, allocation);
0341
0342 if (acpi_gbl_disable_mem_tracking) {
0343 return_ACPI_STATUS(AE_OK);
0344 }
0345
0346 mem_list = acpi_gbl_global_list;
0347 status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
0348 if (ACPI_FAILURE(status)) {
0349 return_ACPI_STATUS(status);
0350 }
0351
0352
0353
0354
0355
0356 element = acpi_ut_find_allocation(allocation);
0357 if (element == allocation) {
0358 ACPI_ERROR((AE_INFO,
0359 "UtTrackAllocation: Allocation (%p) already present in global list!",
0360 allocation));
0361 goto unlock_and_exit;
0362 }
0363
0364
0365
0366 allocation->size = (u32)size;
0367 allocation->alloc_type = alloc_type;
0368 allocation->component = component;
0369 allocation->line = line;
0370
0371 acpi_ut_safe_strncpy(allocation->module, (char *)module,
0372 ACPI_MAX_MODULE_NAME);
0373
0374 if (!element) {
0375
0376
0377
0378 if (mem_list->list_head) {
0379 ((struct acpi_debug_mem_block *)(mem_list->list_head))->
0380 previous = allocation;
0381 }
0382
0383 allocation->next = mem_list->list_head;
0384 allocation->previous = NULL;
0385
0386 mem_list->list_head = allocation;
0387 } else {
0388
0389
0390 allocation->next = element->next;
0391 allocation->previous = element;
0392
0393 if (element->next) {
0394 (element->next)->previous = allocation;
0395 }
0396
0397 element->next = allocation;
0398 }
0399
0400 unlock_and_exit:
0401 status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
0402 return_ACPI_STATUS(status);
0403 }
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420 static acpi_status
0421 acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
0422 u32 component, const char *module, u32 line)
0423 {
0424 struct acpi_memory_list *mem_list;
0425 acpi_status status;
0426
0427 ACPI_FUNCTION_NAME(ut_remove_allocation);
0428
0429 if (acpi_gbl_disable_mem_tracking) {
0430 return (AE_OK);
0431 }
0432
0433 mem_list = acpi_gbl_global_list;
0434 if (NULL == mem_list->list_head) {
0435
0436
0437
0438 ACPI_ERROR((module, line,
0439 "Empty allocation list, nothing to free!"));
0440
0441 return (AE_OK);
0442 }
0443
0444 status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
0445 if (ACPI_FAILURE(status)) {
0446 return (status);
0447 }
0448
0449
0450
0451 if (allocation->previous) {
0452 (allocation->previous)->next = allocation->next;
0453 } else {
0454 mem_list->list_head = allocation->next;
0455 }
0456
0457 if (allocation->next) {
0458 (allocation->next)->previous = allocation->previous;
0459 }
0460
0461 ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
0462 &allocation->user_space, allocation->size));
0463
0464
0465
0466 memset(&allocation->user_space, 0xEA, allocation->size);
0467
0468 status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
0469 return (status);
0470 }
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484 void acpi_ut_dump_allocation_info(void)
0485 {
0486
0487
0488
0489
0490 ACPI_FUNCTION_TRACE(ut_dump_allocation_info);
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524 return_VOID;
0525 }
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540 void acpi_ut_dump_allocations(u32 component, const char *module)
0541 {
0542 struct acpi_debug_mem_block *element;
0543 union acpi_descriptor *descriptor;
0544 u32 num_outstanding = 0;
0545 u8 descriptor_type;
0546
0547 ACPI_FUNCTION_TRACE(ut_dump_allocations);
0548
0549 if (acpi_gbl_disable_mem_tracking) {
0550 return_VOID;
0551 }
0552
0553
0554
0555
0556 if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
0557 return_VOID;
0558 }
0559
0560 if (!acpi_gbl_global_list) {
0561 goto exit;
0562 }
0563
0564 element = acpi_gbl_global_list->list_head;
0565 while (element) {
0566 if ((element->component & component) &&
0567 ((module == NULL)
0568 || (0 == strcmp(module, element->module)))) {
0569 descriptor =
0570 ACPI_CAST_PTR(union acpi_descriptor,
0571 &element->user_space);
0572
0573 if (element->size <
0574 sizeof(struct acpi_common_descriptor)) {
0575 acpi_os_printf("%p Length 0x%04X %9.9s-%4.4u "
0576 "[Not a Descriptor - too small]\n",
0577 descriptor, element->size,
0578 element->module, element->line);
0579 } else {
0580
0581
0582 if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) !=
0583 ACPI_DESC_TYPE_CACHED) {
0584 acpi_os_printf
0585 ("%p Length 0x%04X %9.9s-%4.4u [%s] ",
0586 descriptor, element->size,
0587 element->module, element->line,
0588 acpi_ut_get_descriptor_name
0589 (descriptor));
0590
0591
0592
0593 if (acpi_gbl_verbose_leak_dump) {
0594 acpi_os_printf("\n");
0595 acpi_ut_dump_buffer((u8 *)
0596 descriptor,
0597 element->
0598 size,
0599 DB_BYTE_DISPLAY,
0600 0);
0601 }
0602
0603
0604
0605 descriptor_type = 0;
0606
0607 switch (ACPI_GET_DESCRIPTOR_TYPE
0608 (descriptor)) {
0609 case ACPI_DESC_TYPE_OPERAND:
0610
0611 if (element->size ==
0612 sizeof(union
0613 acpi_operand_object))
0614 {
0615 descriptor_type =
0616 ACPI_DESC_TYPE_OPERAND;
0617 }
0618 break;
0619
0620 case ACPI_DESC_TYPE_PARSER:
0621
0622 if (element->size ==
0623 sizeof(union
0624 acpi_parse_object)) {
0625 descriptor_type =
0626 ACPI_DESC_TYPE_PARSER;
0627 }
0628 break;
0629
0630 case ACPI_DESC_TYPE_NAMED:
0631
0632 if (element->size ==
0633 sizeof(struct
0634 acpi_namespace_node))
0635 {
0636 descriptor_type =
0637 ACPI_DESC_TYPE_NAMED;
0638 }
0639 break;
0640
0641 default:
0642
0643 break;
0644 }
0645
0646
0647
0648 switch (descriptor_type) {
0649 case ACPI_DESC_TYPE_OPERAND:
0650
0651 acpi_os_printf
0652 ("%12.12s RefCount 0x%04X\n",
0653 acpi_ut_get_type_name
0654 (descriptor->object.common.
0655 type),
0656 descriptor->object.common.
0657 reference_count);
0658 break;
0659
0660 case ACPI_DESC_TYPE_PARSER:
0661
0662 acpi_os_printf
0663 ("AmlOpcode 0x%04X\n",
0664 descriptor->op.asl.
0665 aml_opcode);
0666 break;
0667
0668 case ACPI_DESC_TYPE_NAMED:
0669
0670 acpi_os_printf("%4.4s\n",
0671 acpi_ut_get_node_name
0672 (&descriptor->
0673 node));
0674 break;
0675
0676 default:
0677
0678 acpi_os_printf("\n");
0679 break;
0680 }
0681 }
0682 }
0683
0684 num_outstanding++;
0685 }
0686
0687 element = element->next;
0688 }
0689
0690 exit:
0691 (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
0692
0693
0694
0695 if (!num_outstanding) {
0696 ACPI_INFO(("No outstanding allocations"));
0697 } else {
0698 ACPI_ERROR((AE_INFO, "%u (0x%X) Outstanding cache allocations",
0699 num_outstanding, num_outstanding));
0700 }
0701
0702 return_VOID;
0703 }
0704
0705 #endif