blob: 64ac628f6bc128ff336fae0139cb709075490d11 [file] [log] [blame]
/*******************************************************************************
*
* 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 <acpi.h>
#include <acdebug.h>
#include <amlcode.h>
#include <acparser.h>
#include <acnamesp.h>
#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 */