at v2.6.13 1022 lines 28 kB view raw
1/****************************************************************************** 2 * 3 * Module Name: utalloc - local cache and memory allocation routines 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2005, R. Byron Moore 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#include <acpi/acpi.h> 46 47#define _COMPONENT ACPI_UTILITIES 48 ACPI_MODULE_NAME ("utalloc") 49 50/* Local prototypes */ 51 52#ifdef ACPI_DBG_TRACK_ALLOCATIONS 53static struct acpi_debug_mem_block * 54acpi_ut_find_allocation ( 55 u32 list_id, 56 void *allocation); 57 58static acpi_status 59acpi_ut_track_allocation ( 60 u32 list_id, 61 struct acpi_debug_mem_block *address, 62 acpi_size size, 63 u8 alloc_type, 64 u32 component, 65 char *module, 66 u32 line); 67 68static acpi_status 69acpi_ut_remove_allocation ( 70 u32 list_id, 71 struct acpi_debug_mem_block *address, 72 u32 component, 73 char *module, 74 u32 line); 75#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ 76 77 78/******************************************************************************* 79 * 80 * FUNCTION: acpi_ut_release_to_cache 81 * 82 * PARAMETERS: list_id - Memory list/cache ID 83 * Object - The object to be released 84 * 85 * RETURN: None 86 * 87 * DESCRIPTION: Release an object to the specified cache. If cache is full, 88 * the object is deleted. 89 * 90 ******************************************************************************/ 91 92void 93acpi_ut_release_to_cache ( 94 u32 list_id, 95 void *object) 96{ 97 struct acpi_memory_list *cache_info; 98 99 100 ACPI_FUNCTION_ENTRY (); 101 102 103 cache_info = &acpi_gbl_memory_lists[list_id]; 104 105#ifdef ACPI_ENABLE_OBJECT_CACHE 106 107 /* If walk cache is full, just free this wallkstate object */ 108 109 if (cache_info->cache_depth >= cache_info->max_cache_depth) { 110 ACPI_MEM_FREE (object); 111 ACPI_MEM_TRACKING (cache_info->total_freed++); 112 } 113 114 /* Otherwise put this object back into the cache */ 115 116 else { 117 if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) { 118 return; 119 } 120 121 /* Mark the object as cached */ 122 123 ACPI_MEMSET (object, 0xCA, cache_info->object_size); 124 ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_CACHED); 125 126 /* Put the object at the head of the cache list */ 127 128 * (ACPI_CAST_INDIRECT_PTR (char, 129 &(((char *) object)[cache_info->link_offset]))) = cache_info->list_head; 130 cache_info->list_head = object; 131 cache_info->cache_depth++; 132 133 (void) acpi_ut_release_mutex (ACPI_MTX_CACHES); 134 } 135 136#else 137 138 /* Object cache is disabled; just free the object */ 139 140 ACPI_MEM_FREE (object); 141 ACPI_MEM_TRACKING (cache_info->total_freed++); 142#endif 143} 144 145 146/******************************************************************************* 147 * 148 * FUNCTION: acpi_ut_acquire_from_cache 149 * 150 * PARAMETERS: list_id - Memory list ID 151 * 152 * RETURN: A requested object. NULL if the object could not be 153 * allocated. 154 * 155 * DESCRIPTION: Get an object from the specified cache. If cache is empty, 156 * the object is allocated. 157 * 158 ******************************************************************************/ 159 160void * 161acpi_ut_acquire_from_cache ( 162 u32 list_id) 163{ 164 struct acpi_memory_list *cache_info; 165 void *object; 166 167 168 ACPI_FUNCTION_NAME ("ut_acquire_from_cache"); 169 170 171 cache_info = &acpi_gbl_memory_lists[list_id]; 172 173#ifdef ACPI_ENABLE_OBJECT_CACHE 174 175 if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_CACHES))) { 176 return (NULL); 177 } 178 179 ACPI_MEM_TRACKING (cache_info->cache_requests++); 180 181 /* Check the cache first */ 182 183 if (cache_info->list_head) { 184 /* There is an object available, use it */ 185 186 object = cache_info->list_head; 187 cache_info->list_head = *(ACPI_CAST_INDIRECT_PTR (char, 188 &(((char *) object)[cache_info->link_offset]))); 189 190 ACPI_MEM_TRACKING (cache_info->cache_hits++); 191 cache_info->cache_depth--; 192 193#ifdef ACPI_DBG_TRACK_ALLOCATIONS 194 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p from %s\n", 195 object, acpi_gbl_memory_lists[list_id].list_name)); 196#endif 197 198 if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_CACHES))) { 199 return (NULL); 200 } 201 202 /* Clear (zero) the previously used Object */ 203 204 ACPI_MEMSET (object, 0, cache_info->object_size); 205 } 206 207 else { 208 /* The cache is empty, create a new object */ 209 210 /* Avoid deadlock with ACPI_MEM_CALLOCATE */ 211 212 if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_CACHES))) { 213 return (NULL); 214 } 215 216 object = ACPI_MEM_CALLOCATE (cache_info->object_size); 217 ACPI_MEM_TRACKING (cache_info->total_allocated++); 218 } 219 220#else 221 222 /* Object cache is disabled; just allocate the object */ 223 224 object = ACPI_MEM_CALLOCATE (cache_info->object_size); 225 ACPI_MEM_TRACKING (cache_info->total_allocated++); 226#endif 227 228 return (object); 229} 230 231 232#ifdef ACPI_ENABLE_OBJECT_CACHE 233/******************************************************************************* 234 * 235 * FUNCTION: acpi_ut_delete_generic_cache 236 * 237 * PARAMETERS: list_id - Memory list ID 238 * 239 * RETURN: None 240 * 241 * DESCRIPTION: Free all objects within the requested cache. 242 * 243 ******************************************************************************/ 244 245void 246acpi_ut_delete_generic_cache ( 247 u32 list_id) 248{ 249 struct acpi_memory_list *cache_info; 250 char *next; 251 252 253 ACPI_FUNCTION_ENTRY (); 254 255 256 cache_info = &acpi_gbl_memory_lists[list_id]; 257 while (cache_info->list_head) { 258 /* Delete one cached state object */ 259 260 next = *(ACPI_CAST_INDIRECT_PTR (char, 261 &(((char *) cache_info->list_head)[cache_info->link_offset]))); 262 ACPI_MEM_FREE (cache_info->list_head); 263 264 cache_info->list_head = next; 265 cache_info->cache_depth--; 266 } 267} 268#endif 269 270 271/******************************************************************************* 272 * 273 * FUNCTION: acpi_ut_validate_buffer 274 * 275 * PARAMETERS: Buffer - Buffer descriptor to be validated 276 * 277 * RETURN: Status 278 * 279 * DESCRIPTION: Perform parameter validation checks on an struct acpi_buffer 280 * 281 ******************************************************************************/ 282 283acpi_status 284acpi_ut_validate_buffer ( 285 struct acpi_buffer *buffer) 286{ 287 288 /* Obviously, the structure pointer must be valid */ 289 290 if (!buffer) { 291 return (AE_BAD_PARAMETER); 292 } 293 294 /* Special semantics for the length */ 295 296 if ((buffer->length == ACPI_NO_BUFFER) || 297 (buffer->length == ACPI_ALLOCATE_BUFFER) || 298 (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) { 299 return (AE_OK); 300 } 301 302 /* Length is valid, the buffer pointer must be also */ 303 304 if (!buffer->pointer) { 305 return (AE_BAD_PARAMETER); 306 } 307 308 return (AE_OK); 309} 310 311 312/******************************************************************************* 313 * 314 * FUNCTION: acpi_ut_initialize_buffer 315 * 316 * PARAMETERS: Buffer - Buffer to be validated 317 * required_length - Length needed 318 * 319 * RETURN: Status 320 * 321 * DESCRIPTION: Validate that the buffer is of the required length or 322 * allocate a new buffer. Returned buffer is always zeroed. 323 * 324 ******************************************************************************/ 325 326acpi_status 327acpi_ut_initialize_buffer ( 328 struct acpi_buffer *buffer, 329 acpi_size required_length) 330{ 331 acpi_status status = AE_OK; 332 333 334 switch (buffer->length) { 335 case ACPI_NO_BUFFER: 336 337 /* Set the exception and returned the required length */ 338 339 status = AE_BUFFER_OVERFLOW; 340 break; 341 342 343 case ACPI_ALLOCATE_BUFFER: 344 345 /* Allocate a new buffer */ 346 347 buffer->pointer = acpi_os_allocate (required_length); 348 if (!buffer->pointer) { 349 return (AE_NO_MEMORY); 350 } 351 352 /* Clear the buffer */ 353 354 ACPI_MEMSET (buffer->pointer, 0, required_length); 355 break; 356 357 358 case ACPI_ALLOCATE_LOCAL_BUFFER: 359 360 /* Allocate a new buffer with local interface to allow tracking */ 361 362 buffer->pointer = ACPI_MEM_CALLOCATE (required_length); 363 if (!buffer->pointer) { 364 return (AE_NO_MEMORY); 365 } 366 break; 367 368 369 default: 370 371 /* Existing buffer: Validate the size of the buffer */ 372 373 if (buffer->length < required_length) { 374 status = AE_BUFFER_OVERFLOW; 375 break; 376 } 377 378 /* Clear the buffer */ 379 380 ACPI_MEMSET (buffer->pointer, 0, required_length); 381 break; 382 } 383 384 buffer->length = required_length; 385 return (status); 386} 387 388 389/******************************************************************************* 390 * 391 * FUNCTION: acpi_ut_allocate 392 * 393 * PARAMETERS: Size - Size of the allocation 394 * Component - Component type of caller 395 * Module - Source file name of caller 396 * Line - Line number of caller 397 * 398 * RETURN: Address of the allocated memory on success, NULL on failure. 399 * 400 * DESCRIPTION: The subsystem's equivalent of malloc. 401 * 402 ******************************************************************************/ 403 404void * 405acpi_ut_allocate ( 406 acpi_size size, 407 u32 component, 408 char *module, 409 u32 line) 410{ 411 void *allocation; 412 413 414 ACPI_FUNCTION_TRACE_U32 ("ut_allocate", size); 415 416 417 /* Check for an inadvertent size of zero bytes */ 418 419 if (!size) { 420 _ACPI_REPORT_ERROR (module, line, component, 421 ("ut_allocate: Attempt to allocate zero bytes\n")); 422 size = 1; 423 } 424 425 allocation = acpi_os_allocate (size); 426 if (!allocation) { 427 /* Report allocation error */ 428 429 _ACPI_REPORT_ERROR (module, line, component, 430 ("ut_allocate: Could not allocate size %X\n", (u32) size)); 431 432 return_PTR (NULL); 433 } 434 435 return_PTR (allocation); 436} 437 438 439/******************************************************************************* 440 * 441 * FUNCTION: acpi_ut_callocate 442 * 443 * PARAMETERS: Size - Size of the allocation 444 * Component - Component type of caller 445 * Module - Source file name of caller 446 * Line - Line number of caller 447 * 448 * RETURN: Address of the allocated memory on success, NULL on failure. 449 * 450 * DESCRIPTION: Subsystem equivalent of calloc. 451 * 452 ******************************************************************************/ 453 454void * 455acpi_ut_callocate ( 456 acpi_size size, 457 u32 component, 458 char *module, 459 u32 line) 460{ 461 void *allocation; 462 463 464 ACPI_FUNCTION_TRACE_U32 ("ut_callocate", size); 465 466 467 /* Check for an inadvertent size of zero bytes */ 468 469 if (!size) { 470 _ACPI_REPORT_ERROR (module, line, component, 471 ("ut_callocate: Attempt to allocate zero bytes\n")); 472 return_PTR (NULL); 473 } 474 475 allocation = acpi_os_allocate (size); 476 if (!allocation) { 477 /* Report allocation error */ 478 479 _ACPI_REPORT_ERROR (module, line, component, 480 ("ut_callocate: Could not allocate size %X\n", (u32) size)); 481 return_PTR (NULL); 482 } 483 484 /* Clear the memory block */ 485 486 ACPI_MEMSET (allocation, 0, size); 487 return_PTR (allocation); 488} 489 490 491#ifdef ACPI_DBG_TRACK_ALLOCATIONS 492/* 493 * These procedures are used for tracking memory leaks in the subsystem, and 494 * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set. 495 * 496 * Each memory allocation is tracked via a doubly linked list. Each 497 * element contains the caller's component, module name, function name, and 498 * line number. acpi_ut_allocate and acpi_ut_callocate call 499 * acpi_ut_track_allocation to add an element to the list; deletion 500 * occurs in the body of acpi_ut_free. 501 */ 502 503 504/******************************************************************************* 505 * 506 * FUNCTION: acpi_ut_allocate_and_track 507 * 508 * PARAMETERS: Size - Size of the allocation 509 * Component - Component type of caller 510 * Module - Source file name of caller 511 * Line - Line number of caller 512 * 513 * RETURN: Address of the allocated memory on success, NULL on failure. 514 * 515 * DESCRIPTION: The subsystem's equivalent of malloc. 516 * 517 ******************************************************************************/ 518 519void * 520acpi_ut_allocate_and_track ( 521 acpi_size size, 522 u32 component, 523 char *module, 524 u32 line) 525{ 526 struct acpi_debug_mem_block *allocation; 527 acpi_status status; 528 529 530 allocation = acpi_ut_allocate (size + sizeof (struct acpi_debug_mem_header), 531 component, module, line); 532 if (!allocation) { 533 return (NULL); 534 } 535 536 status = acpi_ut_track_allocation (ACPI_MEM_LIST_GLOBAL, allocation, size, 537 ACPI_MEM_MALLOC, component, module, line); 538 if (ACPI_FAILURE (status)) { 539 acpi_os_free (allocation); 540 return (NULL); 541 } 542 543 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_allocated++; 544 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size += (u32) size; 545 546 return ((void *) &allocation->user_space); 547} 548 549 550/******************************************************************************* 551 * 552 * FUNCTION: acpi_ut_callocate_and_track 553 * 554 * PARAMETERS: Size - Size of the allocation 555 * Component - Component type of caller 556 * Module - Source file name of caller 557 * Line - Line number of caller 558 * 559 * RETURN: Address of the allocated memory on success, NULL on failure. 560 * 561 * DESCRIPTION: Subsystem equivalent of calloc. 562 * 563 ******************************************************************************/ 564 565void * 566acpi_ut_callocate_and_track ( 567 acpi_size size, 568 u32 component, 569 char *module, 570 u32 line) 571{ 572 struct acpi_debug_mem_block *allocation; 573 acpi_status status; 574 575 576 allocation = acpi_ut_callocate (size + sizeof (struct acpi_debug_mem_header), 577 component, module, line); 578 if (!allocation) { 579 /* Report allocation error */ 580 581 _ACPI_REPORT_ERROR (module, line, component, 582 ("ut_callocate: Could not allocate size %X\n", (u32) size)); 583 return (NULL); 584 } 585 586 status = acpi_ut_track_allocation (ACPI_MEM_LIST_GLOBAL, allocation, size, 587 ACPI_MEM_CALLOC, component, module, line); 588 if (ACPI_FAILURE (status)) { 589 acpi_os_free (allocation); 590 return (NULL); 591 } 592 593 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_allocated++; 594 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size += (u32) size; 595 596 return ((void *) &allocation->user_space); 597} 598 599 600/******************************************************************************* 601 * 602 * FUNCTION: acpi_ut_free_and_track 603 * 604 * PARAMETERS: Allocation - Address of the memory to deallocate 605 * Component - Component type of caller 606 * Module - Source file name of caller 607 * Line - Line number of caller 608 * 609 * RETURN: None 610 * 611 * DESCRIPTION: Frees the memory at Allocation 612 * 613 ******************************************************************************/ 614 615void 616acpi_ut_free_and_track ( 617 void *allocation, 618 u32 component, 619 char *module, 620 u32 line) 621{ 622 struct acpi_debug_mem_block *debug_block; 623 acpi_status status; 624 625 626 ACPI_FUNCTION_TRACE_PTR ("ut_free", allocation); 627 628 629 if (NULL == allocation) { 630 _ACPI_REPORT_ERROR (module, line, component, 631 ("acpi_ut_free: Attempt to delete a NULL address\n")); 632 633 return_VOID; 634 } 635 636 debug_block = ACPI_CAST_PTR (struct acpi_debug_mem_block, 637 (((char *) allocation) - sizeof (struct acpi_debug_mem_header))); 638 639 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_freed++; 640 acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size -= debug_block->size; 641 642 status = acpi_ut_remove_allocation (ACPI_MEM_LIST_GLOBAL, debug_block, 643 component, module, line); 644 if (ACPI_FAILURE (status)) { 645 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not free memory, %s\n", 646 acpi_format_exception (status))); 647 } 648 649 acpi_os_free (debug_block); 650 651 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation)); 652 653 return_VOID; 654} 655 656 657/******************************************************************************* 658 * 659 * FUNCTION: acpi_ut_find_allocation 660 * 661 * PARAMETERS: list_id - Memory list to search 662 * Allocation - Address of allocated memory 663 * 664 * RETURN: A list element if found; NULL otherwise. 665 * 666 * DESCRIPTION: Searches for an element in the global allocation tracking list. 667 * 668 ******************************************************************************/ 669 670static struct acpi_debug_mem_block * 671acpi_ut_find_allocation ( 672 u32 list_id, 673 void *allocation) 674{ 675 struct acpi_debug_mem_block *element; 676 677 678 ACPI_FUNCTION_ENTRY (); 679 680 681 if (list_id > ACPI_MEM_LIST_MAX) { 682 return (NULL); 683 } 684 685 element = acpi_gbl_memory_lists[list_id].list_head; 686 687 /* Search for the address. */ 688 689 while (element) { 690 if (element == allocation) { 691 return (element); 692 } 693 694 element = element->next; 695 } 696 697 return (NULL); 698} 699 700 701/******************************************************************************* 702 * 703 * FUNCTION: acpi_ut_track_allocation 704 * 705 * PARAMETERS: list_id - Memory list to search 706 * Allocation - Address of allocated memory 707 * Size - Size of the allocation 708 * alloc_type - MEM_MALLOC or MEM_CALLOC 709 * Component - Component type of caller 710 * Module - Source file name of caller 711 * Line - Line number of caller 712 * 713 * RETURN: None. 714 * 715 * DESCRIPTION: Inserts an element into the global allocation tracking list. 716 * 717 ******************************************************************************/ 718 719static acpi_status 720acpi_ut_track_allocation ( 721 u32 list_id, 722 struct acpi_debug_mem_block *allocation, 723 acpi_size size, 724 u8 alloc_type, 725 u32 component, 726 char *module, 727 u32 line) 728{ 729 struct acpi_memory_list *mem_list; 730 struct acpi_debug_mem_block *element; 731 acpi_status status = AE_OK; 732 733 734 ACPI_FUNCTION_TRACE_PTR ("ut_track_allocation", allocation); 735 736 737 if (list_id > ACPI_MEM_LIST_MAX) { 738 return_ACPI_STATUS (AE_BAD_PARAMETER); 739 } 740 741 mem_list = &acpi_gbl_memory_lists[list_id]; 742 status = acpi_ut_acquire_mutex (ACPI_MTX_MEMORY); 743 if (ACPI_FAILURE (status)) { 744 return_ACPI_STATUS (status); 745 } 746 747 /* 748 * Search list for this address to make sure it is not already on the list. 749 * This will catch several kinds of problems. 750 */ 751 752 element = acpi_ut_find_allocation (list_id, allocation); 753 if (element) { 754 ACPI_REPORT_ERROR (( 755 "ut_track_allocation: Allocation already present in list! (%p)\n", 756 allocation)); 757 758 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Element %p Address %p\n", 759 element, allocation)); 760 761 goto unlock_and_exit; 762 } 763 764 /* Fill in the instance data. */ 765 766 allocation->size = (u32) size; 767 allocation->alloc_type = alloc_type; 768 allocation->component = component; 769 allocation->line = line; 770 771 ACPI_STRNCPY (allocation->module, module, ACPI_MAX_MODULE_NAME); 772 allocation->module[ACPI_MAX_MODULE_NAME-1] = 0; 773 774 /* Insert at list head */ 775 776 if (mem_list->list_head) { 777 ((struct acpi_debug_mem_block *)(mem_list->list_head))->previous = allocation; 778 } 779 780 allocation->next = mem_list->list_head; 781 allocation->previous = NULL; 782 783 mem_list->list_head = allocation; 784 785 786unlock_and_exit: 787 status = acpi_ut_release_mutex (ACPI_MTX_MEMORY); 788 return_ACPI_STATUS (status); 789} 790 791 792/******************************************************************************* 793 * 794 * FUNCTION: acpi_ut_remove_allocation 795 * 796 * PARAMETERS: list_id - Memory list to search 797 * Allocation - Address of allocated memory 798 * Component - Component type of caller 799 * Module - Source file name of caller 800 * Line - Line number of caller 801 * 802 * RETURN: 803 * 804 * DESCRIPTION: Deletes an element from the global allocation tracking list. 805 * 806 ******************************************************************************/ 807 808static acpi_status 809acpi_ut_remove_allocation ( 810 u32 list_id, 811 struct acpi_debug_mem_block *allocation, 812 u32 component, 813 char *module, 814 u32 line) 815{ 816 struct acpi_memory_list *mem_list; 817 acpi_status status; 818 819 820 ACPI_FUNCTION_TRACE ("ut_remove_allocation"); 821 822 823 if (list_id > ACPI_MEM_LIST_MAX) { 824 return_ACPI_STATUS (AE_BAD_PARAMETER); 825 } 826 827 mem_list = &acpi_gbl_memory_lists[list_id]; 828 if (NULL == mem_list->list_head) { 829 /* No allocations! */ 830 831 _ACPI_REPORT_ERROR (module, line, component, 832 ("ut_remove_allocation: Empty allocation list, nothing to free!\n")); 833 834 return_ACPI_STATUS (AE_OK); 835 } 836 837 status = acpi_ut_acquire_mutex (ACPI_MTX_MEMORY); 838 if (ACPI_FAILURE (status)) { 839 return_ACPI_STATUS (status); 840 } 841 842 /* Unlink */ 843 844 if (allocation->previous) { 845 (allocation->previous)->next = allocation->next; 846 } 847 else { 848 mem_list->list_head = allocation->next; 849 } 850 851 if (allocation->next) { 852 (allocation->next)->previous = allocation->previous; 853 } 854 855 /* Mark the segment as deleted */ 856 857 ACPI_MEMSET (&allocation->user_space, 0xEA, allocation->size); 858 859 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n", 860 allocation->size)); 861 862 status = acpi_ut_release_mutex (ACPI_MTX_MEMORY); 863 return_ACPI_STATUS (status); 864} 865 866 867/******************************************************************************* 868 * 869 * FUNCTION: acpi_ut_dump_allocation_info 870 * 871 * PARAMETERS: 872 * 873 * RETURN: None 874 * 875 * DESCRIPTION: Print some info about the outstanding allocations. 876 * 877 ******************************************************************************/ 878 879#ifdef ACPI_FUTURE_USAGE 880void 881acpi_ut_dump_allocation_info ( 882 void) 883{ 884/* 885 struct acpi_memory_list *mem_list; 886*/ 887 888 ACPI_FUNCTION_TRACE ("ut_dump_allocation_info"); 889 890/* 891 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 892 ("%30s: %4d (%3d Kb)\n", "Current allocations", 893 mem_list->current_count, 894 ROUND_UP_TO_1K (mem_list->current_size))); 895 896 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 897 ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations", 898 mem_list->max_concurrent_count, 899 ROUND_UP_TO_1K (mem_list->max_concurrent_size))); 900 901 902 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 903 ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects", 904 running_object_count, 905 ROUND_UP_TO_1K (running_object_size))); 906 907 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 908 ("%30s: %4d (%3d Kb)\n", "Total (all) allocations", 909 running_alloc_count, 910 ROUND_UP_TO_1K (running_alloc_size))); 911 912 913 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 914 ("%30s: %4d (%3d Kb)\n", "Current Nodes", 915 acpi_gbl_current_node_count, 916 ROUND_UP_TO_1K (acpi_gbl_current_node_size))); 917 918 ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, 919 ("%30s: %4d (%3d Kb)\n", "Max Nodes", 920 acpi_gbl_max_concurrent_node_count, 921 ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count * 922 sizeof (struct acpi_namespace_node))))); 923*/ 924 return_VOID; 925} 926#endif /* ACPI_FUTURE_USAGE */ 927 928 929/******************************************************************************* 930 * 931 * FUNCTION: acpi_ut_dump_allocations 932 * 933 * PARAMETERS: Component - Component(s) to dump info for. 934 * Module - Module to dump info for. NULL means all. 935 * 936 * RETURN: None 937 * 938 * DESCRIPTION: Print a list of all outstanding allocations. 939 * 940 ******************************************************************************/ 941 942void 943acpi_ut_dump_allocations ( 944 u32 component, 945 char *module) 946{ 947 struct acpi_debug_mem_block *element; 948 union acpi_descriptor *descriptor; 949 u32 num_outstanding = 0; 950 951 952 ACPI_FUNCTION_TRACE ("ut_dump_allocations"); 953 954 955 /* 956 * Walk the allocation list. 957 */ 958 if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_MEMORY))) { 959 return; 960 } 961 962 element = acpi_gbl_memory_lists[0].list_head; 963 while (element) { 964 if ((element->component & component) && 965 ((module == NULL) || (0 == ACPI_STRCMP (module, element->module)))) { 966 /* Ignore allocated objects that are in a cache */ 967 968 descriptor = ACPI_CAST_PTR (union acpi_descriptor, &element->user_space); 969 if (descriptor->descriptor_id != ACPI_DESC_TYPE_CACHED) { 970 acpi_os_printf ("%p Len %04X %9.9s-%d [%s] ", 971 descriptor, element->size, element->module, 972 element->line, acpi_ut_get_descriptor_name (descriptor)); 973 974 /* Most of the elements will be Operand objects. */ 975 976 switch (ACPI_GET_DESCRIPTOR_TYPE (descriptor)) { 977 case ACPI_DESC_TYPE_OPERAND: 978 acpi_os_printf ("%12.12s R%hd", 979 acpi_ut_get_type_name (descriptor->object.common.type), 980 descriptor->object.common.reference_count); 981 break; 982 983 case ACPI_DESC_TYPE_PARSER: 984 acpi_os_printf ("aml_opcode %04hX", 985 descriptor->op.asl.aml_opcode); 986 break; 987 988 case ACPI_DESC_TYPE_NAMED: 989 acpi_os_printf ("%4.4s", 990 acpi_ut_get_node_name (&descriptor->node)); 991 break; 992 993 default: 994 break; 995 } 996 997 acpi_os_printf ( "\n"); 998 num_outstanding++; 999 } 1000 } 1001 element = element->next; 1002 } 1003 1004 (void) acpi_ut_release_mutex (ACPI_MTX_MEMORY); 1005 1006 /* Print summary */ 1007 1008 if (!num_outstanding) { 1009 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 1010 "No outstanding allocations.\n")); 1011 } 1012 else { 1013 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 1014 "%d(%X) Outstanding allocations\n", 1015 num_outstanding, num_outstanding)); 1016 } 1017 1018 return_VOID; 1019} 1020 1021#endif /* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */ 1022