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. acpi_ut_allocate and acpi_ut_allocate_zeroed call 51 * acpi_ut_track_allocation to add an element to the list; deletion 52 * occurs in the body of acpi_ut_free. 53 */ 54 55 #include <acpi/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 /* Local prototypes */ 64 static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct 65 acpi_debug_mem_block 66 *allocation); 67 68 static acpi_status 69 acpi_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 74 static acpi_status 75 acpi_ut_remove_allocation(struct acpi_debug_mem_block *address, 76 u32 component, const char *module, u32 line); 77 78 /******************************************************************************* 79 * 80 * FUNCTION: acpi_ut_create_list 81 * 82 * PARAMETERS: cache_name - Ascii name for the cache 83 * object_size - Size of each cached object 84 * return_cache - Where the new cache object is returned 85 * 86 * RETURN: Status 87 * 88 * DESCRIPTION: Create a local memory list for tracking purposed 89 * 90 ******************************************************************************/ 91 92 acpi_status 93 acpi_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 * FUNCTION: acpi_ut_allocate_and_track 115 * 116 * PARAMETERS: size - Size of the allocation 117 * component - Component type of caller 118 * module - Source file name of caller 119 * line - Line number of caller 120 * 121 * RETURN: Address of the allocated memory on success, NULL on failure. 122 * 123 * DESCRIPTION: The subsystem's equivalent of malloc. 124 * 125 ******************************************************************************/ 126 127 void *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 /* Check for an inadvertent size of zero bytes */ 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 /* Report allocation error */ 146 147 ACPI_WARNING((module, line, 148 "Could not allocate size %u", (u32)size)); 149 150 return (NULL); 151 } 152 153 status = 154 acpi_ut_track_allocation(allocation, size, ACPI_MEM_MALLOC, 155 component, module, 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 165 if (acpi_gbl_global_list->current_total_size > 166 acpi_gbl_global_list->max_occupied) { 167 acpi_gbl_global_list->max_occupied = 168 acpi_gbl_global_list->current_total_size; 169 } 170 171 return ((void *)&allocation->user_space); 172 } 173 174 /******************************************************************************* 175 * 176 * FUNCTION: acpi_ut_allocate_zeroed_and_track 177 * 178 * PARAMETERS: size - Size of the allocation 179 * component - Component type of caller 180 * module - Source file name of caller 181 * line - Line number of caller 182 * 183 * RETURN: Address of the allocated memory on success, NULL on failure. 184 * 185 * DESCRIPTION: Subsystem equivalent of calloc. 186 * 187 ******************************************************************************/ 188 189 void *acpi_ut_allocate_zeroed_and_track(acpi_size size, 190 u32 component, 191 const char *module, u32 line) 192 { 193 struct acpi_debug_mem_block *allocation; 194 acpi_status status; 195 196 /* Check for an inadvertent size of zero bytes */ 197 198 if (!size) { 199 ACPI_WARNING((module, line, 200 "Attempt to allocate zero bytes, allocating 1 byte")); 201 size = 1; 202 } 203 204 allocation = 205 acpi_os_allocate_zeroed(size + 206 sizeof(struct acpi_debug_mem_header)); 207 if (!allocation) { 208 209 /* Report allocation error */ 210 211 ACPI_ERROR((module, line, 212 "Could not allocate size %u", (u32)size)); 213 return (NULL); 214 } 215 216 status = acpi_ut_track_allocation(allocation, size, 217 ACPI_MEM_CALLOC, component, module, 218 line); 219 if (ACPI_FAILURE(status)) { 220 acpi_os_free(allocation); 221 return (NULL); 222 } 223 224 acpi_gbl_global_list->total_allocated++; 225 acpi_gbl_global_list->total_size += (u32)size; 226 acpi_gbl_global_list->current_total_size += (u32)size; 227 228 if (acpi_gbl_global_list->current_total_size > 229 acpi_gbl_global_list->max_occupied) { 230 acpi_gbl_global_list->max_occupied = 231 acpi_gbl_global_list->current_total_size; 232 } 233 234 return ((void *)&allocation->user_space); 235 } 236 237 /******************************************************************************* 238 * 239 * FUNCTION: acpi_ut_free_and_track 240 * 241 * PARAMETERS: allocation - Address of the memory to deallocate 242 * component - Component type of caller 243 * module - Source file name of caller 244 * line - Line number of caller 245 * 246 * RETURN: None 247 * 248 * DESCRIPTION: Frees the memory at Allocation 249 * 250 ******************************************************************************/ 251 252 void 253 acpi_ut_free_and_track(void *allocation, 254 u32 component, const char *module, u32 line) 255 { 256 struct acpi_debug_mem_block *debug_block; 257 acpi_status status; 258 259 ACPI_FUNCTION_TRACE_PTR(ut_free, allocation); 260 261 if (NULL == allocation) { 262 ACPI_ERROR((module, line, "Attempt to delete a NULL address")); 263 264 return_VOID; 265 } 266 267 debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block, 268 (((char *)allocation) - 269 sizeof(struct acpi_debug_mem_header))); 270 271 acpi_gbl_global_list->total_freed++; 272 acpi_gbl_global_list->current_total_size -= debug_block->size; 273 274 status = 275 acpi_ut_remove_allocation(debug_block, component, module, line); 276 if (ACPI_FAILURE(status)) { 277 ACPI_EXCEPTION((AE_INFO, status, "Could not free memory")); 278 } 279 280 acpi_os_free(debug_block); 281 ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n", 282 allocation, debug_block)); 283 return_VOID; 284 } 285 286 /******************************************************************************* 287 * 288 * FUNCTION: acpi_ut_find_allocation 289 * 290 * PARAMETERS: allocation - Address of allocated memory 291 * 292 * RETURN: Three cases: 293 * 1) List is empty, NULL is returned. 294 * 2) Element was found. Returns Allocation parameter. 295 * 3) Element was not found. Returns position where it should be 296 * inserted into the list. 297 * 298 * DESCRIPTION: Searches for an element in the global allocation tracking list. 299 * If the element is not found, returns the location within the 300 * list where the element should be inserted. 301 * 302 * Note: The list is ordered by larger-to-smaller addresses. 303 * 304 * This global list is used to detect memory leaks in ACPICA as 305 * well as other issues such as an attempt to release the same 306 * internal object more than once. Although expensive as far 307 * as cpu time, this list is much more helpful for finding these 308 * types of issues than using memory leak detectors outside of 309 * the ACPICA code. 310 * 311 ******************************************************************************/ 312 313 static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct 314 acpi_debug_mem_block 315 *allocation) 316 { 317 struct acpi_debug_mem_block *element; 318 319 element = acpi_gbl_global_list->list_head; 320 if (!element) { 321 return (NULL); 322 } 323 324 /* 325 * Search for the address. 326 * 327 * Note: List is ordered by larger-to-smaller addresses, on the 328 * assumption that a new allocation usually has a larger address 329 * than previous allocations. 330 */ 331 while (element > allocation) { 332 333 /* Check for end-of-list */ 334 335 if (!element->next) { 336 return (element); 337 } 338 339 element = element->next; 340 } 341 342 if (element == allocation) { 343 return (element); 344 } 345 346 return (element->previous); 347 } 348 349 /******************************************************************************* 350 * 351 * FUNCTION: acpi_ut_track_allocation 352 * 353 * PARAMETERS: allocation - Address of allocated memory 354 * size - Size of the allocation 355 * alloc_type - MEM_MALLOC or MEM_CALLOC 356 * component - Component type of caller 357 * module - Source file name of caller 358 * line - Line number of caller 359 * 360 * RETURN: Status 361 * 362 * DESCRIPTION: Inserts an element into the global allocation tracking list. 363 * 364 ******************************************************************************/ 365 366 static acpi_status 367 acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation, 368 acpi_size size, 369 u8 alloc_type, 370 u32 component, const char *module, u32 line) 371 { 372 struct acpi_memory_list *mem_list; 373 struct acpi_debug_mem_block *element; 374 acpi_status status = AE_OK; 375 376 ACPI_FUNCTION_TRACE_PTR(ut_track_allocation, allocation); 377 378 if (acpi_gbl_disable_mem_tracking) { 379 return_ACPI_STATUS(AE_OK); 380 } 381 382 mem_list = acpi_gbl_global_list; 383 status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY); 384 if (ACPI_FAILURE(status)) { 385 return_ACPI_STATUS(status); 386 } 387 388 /* 389 * Search the global list for this address to make sure it is not 390 * already present. This will catch several kinds of problems. 391 */ 392 element = acpi_ut_find_allocation(allocation); 393 if (element == allocation) { 394 ACPI_ERROR((AE_INFO, 395 "UtTrackAllocation: Allocation (%p) already present in global list!", 396 allocation)); 397 goto unlock_and_exit; 398 } 399 400 /* Fill in the instance data */ 401 402 allocation->size = (u32)size; 403 allocation->alloc_type = alloc_type; 404 allocation->component = component; 405 allocation->line = line; 406 407 strncpy(allocation->module, module, ACPI_MAX_MODULE_NAME); 408 allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0; 409 410 if (!element) { 411 412 /* Insert at list head */ 413 414 if (mem_list->list_head) { 415 ((struct acpi_debug_mem_block *)(mem_list->list_head))-> 416 previous = allocation; 417 } 418 419 allocation->next = mem_list->list_head; 420 allocation->previous = NULL; 421 422 mem_list->list_head = allocation; 423 } else { 424 /* Insert after element */ 425 426 allocation->next = element->next; 427 allocation->previous = element; 428 429 if (element->next) { 430 (element->next)->previous = allocation; 431 } 432 433 element->next = allocation; 434 } 435 436 unlock_and_exit: 437 status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); 438 return_ACPI_STATUS(status); 439 } 440 441 /******************************************************************************* 442 * 443 * FUNCTION: acpi_ut_remove_allocation 444 * 445 * PARAMETERS: allocation - Address of allocated memory 446 * component - Component type of caller 447 * module - Source file name of caller 448 * line - Line number of caller 449 * 450 * RETURN: Status 451 * 452 * DESCRIPTION: Deletes an element from the global allocation tracking list. 453 * 454 ******************************************************************************/ 455 456 static acpi_status 457 acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation, 458 u32 component, const char *module, u32 line) 459 { 460 struct acpi_memory_list *mem_list; 461 acpi_status status; 462 463 ACPI_FUNCTION_NAME(ut_remove_allocation); 464 465 if (acpi_gbl_disable_mem_tracking) { 466 return (AE_OK); 467 } 468 469 mem_list = acpi_gbl_global_list; 470 if (NULL == mem_list->list_head) { 471 472 /* No allocations! */ 473 474 ACPI_ERROR((module, line, 475 "Empty allocation list, nothing to free!")); 476 477 return (AE_OK); 478 } 479 480 status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY); 481 if (ACPI_FAILURE(status)) { 482 return (status); 483 } 484 485 /* Unlink */ 486 487 if (allocation->previous) { 488 (allocation->previous)->next = allocation->next; 489 } else { 490 mem_list->list_head = allocation->next; 491 } 492 493 if (allocation->next) { 494 (allocation->next)->previous = allocation->previous; 495 } 496 497 ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n", 498 &allocation->user_space, allocation->size)); 499 500 /* Mark the segment as deleted */ 501 502 memset(&allocation->user_space, 0xEA, allocation->size); 503 504 status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); 505 return (status); 506 } 507 508 /******************************************************************************* 509 * 510 * FUNCTION: acpi_ut_dump_allocation_info 511 * 512 * PARAMETERS: None 513 * 514 * RETURN: None 515 * 516 * DESCRIPTION: Print some info about the outstanding allocations. 517 * 518 ******************************************************************************/ 519 520 void acpi_ut_dump_allocation_info(void) 521 { 522 /* 523 struct acpi_memory_list *mem_list; 524 */ 525 526 ACPI_FUNCTION_TRACE(ut_dump_allocation_info); 527 528 /* 529 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 530 ("%30s: %4d (%3d Kb)\n", "Current allocations", 531 mem_list->current_count, 532 ROUND_UP_TO_1K (mem_list->current_size))); 533 534 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 535 ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations", 536 mem_list->max_concurrent_count, 537 ROUND_UP_TO_1K (mem_list->max_concurrent_size))); 538 539 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 540 ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects", 541 running_object_count, 542 ROUND_UP_TO_1K (running_object_size))); 543 544 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 545 ("%30s: %4d (%3d Kb)\n", "Total (all) allocations", 546 running_alloc_count, 547 ROUND_UP_TO_1K (running_alloc_size))); 548 549 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 550 ("%30s: %4d (%3d Kb)\n", "Current Nodes", 551 acpi_gbl_current_node_count, 552 ROUND_UP_TO_1K (acpi_gbl_current_node_size))); 553 554 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 555 ("%30s: %4d (%3d Kb)\n", "Max Nodes", 556 acpi_gbl_max_concurrent_node_count, 557 ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count * 558 sizeof (struct acpi_namespace_node))))); 559 */ 560 return_VOID; 561 } 562 563 /******************************************************************************* 564 * 565 * FUNCTION: acpi_ut_dump_allocations 566 * 567 * PARAMETERS: component - Component(s) to dump info for. 568 * module - Module to dump info for. NULL means all. 569 * 570 * RETURN: None 571 * 572 * DESCRIPTION: Print a list of all outstanding allocations. 573 * 574 ******************************************************************************/ 575 576 void acpi_ut_dump_allocations(u32 component, const char *module) 577 { 578 struct acpi_debug_mem_block *element; 579 union acpi_descriptor *descriptor; 580 u32 num_outstanding = 0; 581 u8 descriptor_type; 582 583 ACPI_FUNCTION_TRACE(ut_dump_allocations); 584 585 if (acpi_gbl_disable_mem_tracking) { 586 return_VOID; 587 } 588 589 /* 590 * Walk the allocation list. 591 */ 592 if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) { 593 return_VOID; 594 } 595 596 element = acpi_gbl_global_list->list_head; 597 while (element) { 598 if ((element->component & component) && 599 ((module == NULL) 600 || (0 == strcmp(module, element->module)))) { 601 descriptor = 602 ACPI_CAST_PTR(union acpi_descriptor, 603 &element->user_space); 604 605 if (element->size < 606 sizeof(struct acpi_common_descriptor)) { 607 acpi_os_printf("%p Length 0x%04X %9.9s-%u " 608 "[Not a Descriptor - too small]\n", 609 descriptor, element->size, 610 element->module, element->line); 611 } else { 612 /* Ignore allocated objects that are in a cache */ 613 614 if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) != 615 ACPI_DESC_TYPE_CACHED) { 616 acpi_os_printf 617 ("%p Length 0x%04X %9.9s-%u [%s] ", 618 descriptor, element->size, 619 element->module, element->line, 620 acpi_ut_get_descriptor_name 621 (descriptor)); 622 623 /* Validate the descriptor type using Type field and length */ 624 625 descriptor_type = 0; /* Not a valid descriptor type */ 626 627 switch (ACPI_GET_DESCRIPTOR_TYPE 628 (descriptor)) { 629 case ACPI_DESC_TYPE_OPERAND: 630 631 if (element->size == 632 sizeof(union 633 acpi_operand_object)) 634 { 635 descriptor_type = 636 ACPI_DESC_TYPE_OPERAND; 637 } 638 break; 639 640 case ACPI_DESC_TYPE_PARSER: 641 642 if (element->size == 643 sizeof(union 644 acpi_parse_object)) { 645 descriptor_type = 646 ACPI_DESC_TYPE_PARSER; 647 } 648 break; 649 650 case ACPI_DESC_TYPE_NAMED: 651 652 if (element->size == 653 sizeof(struct 654 acpi_namespace_node)) 655 { 656 descriptor_type = 657 ACPI_DESC_TYPE_NAMED; 658 } 659 break; 660 661 default: 662 663 break; 664 } 665 666 /* Display additional info for the major descriptor types */ 667 668 switch (descriptor_type) { 669 case ACPI_DESC_TYPE_OPERAND: 670 671 acpi_os_printf 672 ("%12.12s RefCount 0x%04X\n", 673 acpi_ut_get_type_name 674 (descriptor->object.common. 675 type), 676 descriptor->object.common. 677 reference_count); 678 break; 679 680 case ACPI_DESC_TYPE_PARSER: 681 682 acpi_os_printf 683 ("AmlOpcode 0x%04hX\n", 684 descriptor->op.asl. 685 aml_opcode); 686 break; 687 688 case ACPI_DESC_TYPE_NAMED: 689 690 acpi_os_printf("%4.4s\n", 691 acpi_ut_get_node_name 692 (&descriptor-> 693 node)); 694 break; 695 696 default: 697 698 acpi_os_printf("\n"); 699 break; 700 } 701 } 702 } 703 704 num_outstanding++; 705 } 706 707 element = element->next; 708 } 709 710 (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY); 711 712 /* Print summary */ 713 714 if (!num_outstanding) { 715 ACPI_INFO((AE_INFO, "No outstanding allocations")); 716 } else { 717 ACPI_ERROR((AE_INFO, "%u(0x%X) Outstanding allocations", 718 num_outstanding, num_outstanding)); 719 } 720 721 return_VOID; 722 } 723 724 #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ 725