/******************************************************************************* * * Module Name: dbstats - Generation and display of ACPI table statistics * $Revision: 47 $ * ******************************************************************************/ /* * Copyright (C) 2000, 2001 R. Byron Moore * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #ifdef ENABLE_DEBUGGER #define _COMPONENT ACPI_DEBUGGER MODULE_NAME ("dbstats") /* * Statistics subcommands */ ARGUMENT_INFO acpi_db_stat_types [] = { {"ALLOCATIONS"}, {"OBJECTS"}, {"MEMORY"}, {"MISC"}, {"TABLES"}, {"SIZES"}, {"STACK"}, {NULL} /* Must be null terminated */ }; #define CMD_ALLOCATIONS 0 #define CMD_OBJECTS 1 #define CMD_MEMORY 2 #define CMD_MISC 3 #define CMD_TABLES 4 #define CMD_SIZES 5 #define CMD_STACK 6 /******************************************************************************* * * FUNCTION: Acpi_db_enumerate_object * * PARAMETERS: Obj_desc - Object to be counted * * RETURN: None * * DESCRIPTION: Add this object to the global counts, by object type. * Recursively handles subobjects and packages. * * [TBD] Restructure - remove recursion. * ******************************************************************************/ void acpi_db_enumerate_object ( acpi_operand_object *obj_desc) { u32 type; u32 i; if (!obj_desc) { return; } /* Enumerate this object first */ acpi_gbl_num_objects++; type = obj_desc->common.type; if (type > INTERNAL_TYPE_NODE_MAX) { acpi_gbl_obj_type_count_misc++; } else { acpi_gbl_obj_type_count [type]++; } /* Count the sub-objects */ switch (type) { case ACPI_TYPE_PACKAGE: for (i = 0; i< obj_desc->package.count; i++) { acpi_db_enumerate_object (obj_desc->package.elements[i]); } break; case ACPI_TYPE_DEVICE: acpi_db_enumerate_object (obj_desc->device.sys_handler); acpi_db_enumerate_object (obj_desc->device.drv_handler); acpi_db_enumerate_object (obj_desc->device.addr_handler); break; case ACPI_TYPE_REGION: acpi_db_enumerate_object (obj_desc->region.addr_handler); break; case ACPI_TYPE_POWER: acpi_db_enumerate_object (obj_desc->power_resource.sys_handler); acpi_db_enumerate_object (obj_desc->power_resource.drv_handler); break; case ACPI_TYPE_PROCESSOR: acpi_db_enumerate_object (obj_desc->processor.sys_handler); acpi_db_enumerate_object (obj_desc->processor.drv_handler); acpi_db_enumerate_object (obj_desc->processor.addr_handler); break; case ACPI_TYPE_THERMAL: acpi_db_enumerate_object (obj_desc->thermal_zone.sys_handler); acpi_db_enumerate_object (obj_desc->thermal_zone.drv_handler); acpi_db_enumerate_object (obj_desc->thermal_zone.addr_handler); break; } } #ifndef PARSER_ONLY /******************************************************************************* * * FUNCTION: Acpi_db_classify_one_object * * PARAMETERS: Callback for Walk_namespace * * RETURN: Status * * DESCRIPTION: Enumerate both the object descriptor (including subobjects) and * the parent namespace node. * ******************************************************************************/ acpi_status acpi_db_classify_one_object ( acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { acpi_namespace_node *node; acpi_operand_object *obj_desc; u32 type; acpi_gbl_num_nodes++; node = (acpi_namespace_node *) obj_handle; obj_desc = ((acpi_namespace_node *) obj_handle)->object; acpi_db_enumerate_object (obj_desc); type = node->type; if (type > INTERNAL_TYPE_NODE_MAX) { acpi_gbl_node_type_count_misc++; } else { acpi_gbl_node_type_count [type]++; } return AE_OK; /* TBD: These need to be counted during the initial parsing phase */ /* if (Acpi_ps_is_named_op (Op->Opcode)) { Num_nodes++; } if (Is_method) { Num_method_elements++; } Num_grammar_elements++; Op = Acpi_ps_get_depth_next (Root, Op); Size_of_parse_tree = (Num_grammar_elements - Num_method_elements) * (u32) sizeof (acpi_parse_object); Size_of_method_trees = Num_method_elements * (u32) sizeof (acpi_parse_object); Size_of_node_entries = Num_nodes * (u32) sizeof (acpi_namespace_node); Size_of_acpi_objects = Num_nodes * (u32) sizeof (acpi_operand_object); */ } /******************************************************************************* * * FUNCTION: Acpi_db_count_namespace_objects * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Count and classify the entire namespace, including all * namespace nodes and attached objects. * ******************************************************************************/ acpi_status acpi_db_count_namespace_objects ( void) { u32 i; acpi_gbl_num_nodes = 0; acpi_gbl_num_objects = 0; acpi_gbl_obj_type_count_misc = 0; for (i = 0; i < (INTERNAL_TYPE_NODE_MAX -1); i++) { acpi_gbl_obj_type_count [i] = 0; acpi_gbl_node_type_count [i] = 0; } acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, FALSE, acpi_db_classify_one_object, NULL, NULL); return (AE_OK); } #endif /******************************************************************************* * * FUNCTION: Acpi_db_display_statistics * * PARAMETERS: Type_arg - Subcommand * * RETURN: Status * * DESCRIPTION: Display various statistics * ******************************************************************************/ acpi_status acpi_db_display_statistics ( NATIVE_CHAR *type_arg) { u32 i; u32 type; u32 outstanding; u32 size; if (!acpi_gbl_DSDT) { acpi_os_printf ("*** Warning: There is no DSDT loaded\n"); } if (!type_arg) { acpi_os_printf ("The following subcommands are available:\n ALLOCATIONS, OBJECTS, MEMORY, MISC, SIZES, TABLES\n"); return (AE_OK); } STRUPR (type_arg); type = acpi_db_match_argument (type_arg, acpi_db_stat_types); if (type == (u32) -1) { acpi_os_printf ("Invalid or unsupported argument\n"); return (AE_OK); } switch (type) { #ifndef PARSER_ONLY case CMD_ALLOCATIONS: #ifdef ACPI_DBG_TRACK_ALLOCATIONS acpi_ut_dump_allocation_info (); #endif break; #endif case CMD_TABLES: acpi_os_printf ("ACPI Table Information:\n\n"); if (acpi_gbl_DSDT) { acpi_os_printf ("DSDT Length:................% 7ld (%X)\n", acpi_gbl_DSDT->length, acpi_gbl_DSDT->length); } break; case CMD_OBJECTS: #ifndef PARSER_ONLY acpi_db_count_namespace_objects (); acpi_os_printf ("\n_objects defined in the current namespace:\n\n"); acpi_os_printf ("%16.16s % 10.10s % 10.10s\n", "ACPI_TYPE", "NODES", "OBJECTS"); for (i = 0; i < INTERNAL_TYPE_NODE_MAX; i++) { acpi_os_printf ("%16.16s % 10ld% 10ld\n", acpi_ut_get_type_name (i), acpi_gbl_node_type_count [i], acpi_gbl_obj_type_count [i]); } acpi_os_printf ("%16.16s % 10ld% 10ld\n", "Misc/Unknown", acpi_gbl_node_type_count_misc, acpi_gbl_obj_type_count_misc); acpi_os_printf ("%16.16s % 10ld% 10ld\n", "TOTALS:", acpi_gbl_num_nodes, acpi_gbl_num_objects); #endif break; case CMD_MEMORY: #ifdef ACPI_DBG_TRACK_ALLOCATIONS acpi_os_printf ("\n----Object and Cache Statistics---------------------------------------------\n"); for (i = 0; i < ACPI_NUM_MEM_LISTS; i++) { acpi_os_printf ("\n%s\n", acpi_gbl_memory_lists[i].list_name); if (acpi_gbl_memory_lists[i].max_cache_depth > 0) { acpi_os_printf (" Cache: [Depth Max Avail Size] % 7d % 7d % 7d % 7d B\n", acpi_gbl_memory_lists[i].cache_depth, acpi_gbl_memory_lists[i].max_cache_depth, acpi_gbl_memory_lists[i].max_cache_depth - acpi_gbl_memory_lists[i].cache_depth, (acpi_gbl_memory_lists[i].cache_depth * acpi_gbl_memory_lists[i].object_size)); acpi_os_printf (" Cache: [Requests Hits Misses Obj_size] % 7d % 7d % 7d % 7d B\n", acpi_gbl_memory_lists[i].cache_requests, acpi_gbl_memory_lists[i].cache_hits, acpi_gbl_memory_lists[i].cache_requests - acpi_gbl_memory_lists[i].cache_hits, acpi_gbl_memory_lists[i].object_size); } outstanding = acpi_gbl_memory_lists[i].total_allocated - acpi_gbl_memory_lists[i].total_freed - acpi_gbl_memory_lists[i].cache_depth; if (acpi_gbl_memory_lists[i].object_size) { size = ROUND_UP_TO_1K (outstanding * acpi_gbl_memory_lists[i].object_size); } else { size = ROUND_UP_TO_1K (acpi_gbl_memory_lists[i].current_total_size); } acpi_os_printf (" Mem: [Alloc Free Outstanding Size] % 7d % 7d % 7d % 7d Kb\n", acpi_gbl_memory_lists[i].total_allocated, acpi_gbl_memory_lists[i].total_freed, outstanding, size); } #endif break; case CMD_MISC: acpi_os_printf ("\n_miscellaneous Statistics:\n\n"); acpi_os_printf ("Calls to Acpi_ps_find:.. ........% 7ld\n", acpi_gbl_ps_find_count); acpi_os_printf ("Calls to Acpi_ns_lookup:..........% 7ld\n", acpi_gbl_ns_lookup_count); acpi_os_printf ("\n"); acpi_os_printf ("Mutex usage:\n\n"); for (i = 0; i < NUM_MTX; i++) { acpi_os_printf ("%-28s: % 7ld\n", acpi_ut_get_mutex_name (i), acpi_gbl_acpi_mutex_info[i].use_count); } break; case CMD_SIZES: acpi_os_printf ("\n_internal object sizes:\n\n"); acpi_os_printf ("Common %3d\n", sizeof (ACPI_OBJECT_COMMON)); acpi_os_printf ("Number %3d\n", sizeof (ACPI_OBJECT_INTEGER)); acpi_os_printf ("String %3d\n", sizeof (ACPI_OBJECT_STRING)); acpi_os_printf ("Buffer %3d\n", sizeof (ACPI_OBJECT_BUFFER)); acpi_os_printf ("Package %3d\n", sizeof (ACPI_OBJECT_PACKAGE)); acpi_os_printf ("Buffer_field %3d\n", sizeof (ACPI_OBJECT_BUFFER_FIELD)); acpi_os_printf ("Device %3d\n", sizeof (ACPI_OBJECT_DEVICE)); acpi_os_printf ("Event %3d\n", sizeof (ACPI_OBJECT_EVENT)); acpi_os_printf ("Method %3d\n", sizeof (ACPI_OBJECT_METHOD)); acpi_os_printf ("Mutex %3d\n", sizeof (ACPI_OBJECT_MUTEX)); acpi_os_printf ("Region %3d\n", sizeof (ACPI_OBJECT_REGION)); acpi_os_printf ("Power_resource %3d\n", sizeof (ACPI_OBJECT_POWER_RESOURCE)); acpi_os_printf ("Processor %3d\n", sizeof (ACPI_OBJECT_PROCESSOR)); acpi_os_printf ("Thermal_zone %3d\n", sizeof (ACPI_OBJECT_THERMAL_ZONE)); acpi_os_printf ("Region_field %3d\n", sizeof (ACPI_OBJECT_REGION_FIELD)); acpi_os_printf ("Bank_field %3d\n", sizeof (ACPI_OBJECT_BANK_FIELD)); acpi_os_printf ("Index_field %3d\n", sizeof (ACPI_OBJECT_INDEX_FIELD)); acpi_os_printf ("Reference %3d\n", sizeof (ACPI_OBJECT_REFERENCE)); acpi_os_printf ("Notify_handler %3d\n", sizeof (ACPI_OBJECT_NOTIFY_HANDLER)); acpi_os_printf ("Addr_handler %3d\n", sizeof (ACPI_OBJECT_ADDR_HANDLER)); acpi_os_printf ("Extra %3d\n", sizeof (ACPI_OBJECT_EXTRA)); acpi_os_printf ("\n"); acpi_os_printf ("Parse_object %3d\n", sizeof (acpi_parse_object)); acpi_os_printf ("Parse2_object %3d\n", sizeof (acpi_parse2_object)); acpi_os_printf ("Operand_object %3d\n", sizeof (acpi_operand_object)); acpi_os_printf ("Namespace_node %3d\n", sizeof (acpi_namespace_node)); break; case CMD_STACK: size = acpi_gbl_entry_stack_pointer - acpi_gbl_lowest_stack_pointer; acpi_os_printf ("\n_subsystem Stack Usage:\n\n"); acpi_os_printf ("Entry Stack Pointer %X\n", acpi_gbl_entry_stack_pointer); acpi_os_printf ("Lowest Stack Pointer %X\n", acpi_gbl_lowest_stack_pointer); acpi_os_printf ("Stack Use %X (%d)\n", size, size); acpi_os_printf ("Deepest Procedure Nesting %d\n", acpi_gbl_deepest_nesting); break; } acpi_os_printf ("\n"); return (AE_OK); } #endif /* ENABLE_DEBUGGER */