1 /****************************************************************************** 2 * 3 * Module Name: uttrack - Memory allocation tracking routines (debug only) 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2013, 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 ACPI_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 = 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 * FUNCTION: acpi_ut_allocate_zeroed_and_track 176 * 177 * PARAMETERS: size - Size of the allocation 178 * component - Component type of caller 179 * module - Source file name of caller 180 * line - Line number of caller 181 * 182 * RETURN: Address of the allocated memory on success, NULL on failure. 183 * 184 * DESCRIPTION: Subsystem equivalent of calloc. 185 * 186 ******************************************************************************/ 187 188 void *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 /* Check for an inadvertent size of zero bytes */ 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 /* Report allocation error */ 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 * FUNCTION: acpi_ut_free_and_track 238 * 239 * PARAMETERS: allocation - Address of the memory to deallocate 240 * component - Component type of caller 241 * module - Source file name of caller 242 * line - Line number of caller 243 * 244 * RETURN: None 245 * 246 * DESCRIPTION: Frees the memory at Allocation 247 * 248 ******************************************************************************/ 249 250 void 251 acpi_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 * FUNCTION: acpi_ut_find_allocation 286 * 287 * PARAMETERS: allocation - Address of allocated memory 288 * 289 * RETURN: Three cases: 290 * 1) List is empty, NULL is returned. 291 * 2) Element was found. Returns Allocation parameter. 292 * 3) Element was not found. Returns position where it should be 293 * inserted into the list. 294 * 295 * DESCRIPTION: Searches for an element in the global allocation tracking list. 296 * If the element is not found, returns the location within the 297 * list where the element should be inserted. 298 * 299 * Note: The list is ordered by larger-to-smaller addresses. 300 * 301 * This global list is used to detect memory leaks in ACPICA as 302 * well as other issues such as an attempt to release the same 303 * internal object more than once. Although expensive as far 304 * as cpu time, this list is much more helpful for finding these 305 * types of issues than using memory leak detectors outside of 306 * the ACPICA code. 307 * 308 ******************************************************************************/ 309 310 static 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 * Search for the address. 323 * 324 * Note: List is ordered by larger-to-smaller addresses, on the 325 * assumption that a new allocation usually has a larger address 326 * than previous allocations. 327 */ 328 while (element > allocation) { 329 330 /* Check for end-of-list */ 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 * FUNCTION: acpi_ut_track_allocation 349 * 350 * PARAMETERS: allocation - Address of allocated memory 351 * size - Size of the allocation 352 * alloc_type - MEM_MALLOC or MEM_CALLOC 353 * component - Component type of caller 354 * module - Source file name of caller 355 * line - Line number of caller 356 * 357 * RETURN: Status 358 * 359 * DESCRIPTION: Inserts an element into the global allocation tracking list. 360 * 361 ******************************************************************************/ 362 363 static acpi_status 364 acpi_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 * Search the global list for this address to make sure it is not 387 * already present. This will catch several kinds of problems. 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 /* Fill in the instance data */ 398 399 allocation->size = (u32)size; 400 allocation->alloc_type = alloc_type; 401 allocation->component = component; 402 allocation->line = line; 403 404 ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME); 405 allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0; 406 407 if (!element) { 408 409 /* Insert at list head */ 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 /* Insert after element */ 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 * FUNCTION: acpi_ut_remove_allocation 441 * 442 * PARAMETERS: allocation - Address of allocated memory 443 * component - Component type of caller 444 * module - Source file name of caller 445 * line - Line number of caller 446 * 447 * RETURN: Status 448 * 449 * DESCRIPTION: Deletes an element from the global allocation tracking list. 450 * 451 ******************************************************************************/ 452 453 static acpi_status 454 acpi_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 /* No allocations! */ 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 /* Unlink */ 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 /* Mark the segment as deleted */ 498 499 ACPI_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 * FUNCTION: acpi_ut_dump_allocation_info 508 * 509 * PARAMETERS: None 510 * 511 * RETURN: None 512 * 513 * DESCRIPTION: Print some info about the outstanding allocations. 514 * 515 ******************************************************************************/ 516 517 void acpi_ut_dump_allocation_info(void) 518 { 519 /* 520 struct acpi_memory_list *mem_list; 521 */ 522 523 ACPI_FUNCTION_TRACE(ut_dump_allocation_info); 524 525 /* 526 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 527 ("%30s: %4d (%3d Kb)\n", "Current allocations", 528 mem_list->current_count, 529 ROUND_UP_TO_1K (mem_list->current_size))); 530 531 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 532 ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations", 533 mem_list->max_concurrent_count, 534 ROUND_UP_TO_1K (mem_list->max_concurrent_size))); 535 536 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 537 ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects", 538 running_object_count, 539 ROUND_UP_TO_1K (running_object_size))); 540 541 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 542 ("%30s: %4d (%3d Kb)\n", "Total (all) allocations", 543 running_alloc_count, 544 ROUND_UP_TO_1K (running_alloc_size))); 545 546 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 547 ("%30s: %4d (%3d Kb)\n", "Current Nodes", 548 acpi_gbl_current_node_count, 549 ROUND_UP_TO_1K (acpi_gbl_current_node_size))); 550 551 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 552 ("%30s: %4d (%3d Kb)\n", "Max Nodes", 553 acpi_gbl_max_concurrent_node_count, 554 ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count * 555 sizeof (struct acpi_namespace_node))))); 556 */ 557 return_VOID; 558 } 559 560 /******************************************************************************* 561 * 562 * FUNCTION: acpi_ut_dump_allocations 563 * 564 * PARAMETERS: component - Component(s) to dump info for. 565 * module - Module to dump info for. NULL means all. 566 * 567 * RETURN: None 568 * 569 * DESCRIPTION: Print a list of all outstanding allocations. 570 * 571 ******************************************************************************/ 572 573 void 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 * Walk the allocation list. 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 == ACPI_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 /* Ignore allocated objects that are in a cache */ 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 /* Validate the descriptor type using Type field and length */ 621 622 descriptor_type = 0; /* Not a valid descriptor type */ 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 /* Display additional info for the major descriptor types */ 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 /* Print summary */ 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 /* ACPI_DBG_TRACK_ALLOCATIONS */ 722