1 /******************************************************************************* 2 * 3 * Module Name: dbstats - Generation and display of ACPI table statistics 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2011, 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 #include "acpi.h" 46 #include "accommon.h" 47 #include "acdebug.h" 48 #include "acnamesp.h" 49 50 #ifdef ACPI_DEBUGGER 51 52 #define _COMPONENT ACPI_CA_DEBUGGER 53 ACPI_MODULE_NAME ("dbstats") 54 55 /* Local prototypes */ 56 57 static void 58 AcpiDbCountNamespaceObjects ( 59 void); 60 61 static void 62 AcpiDbEnumerateObject ( 63 ACPI_OPERAND_OBJECT *ObjDesc); 64 65 static ACPI_STATUS 66 AcpiDbClassifyOneObject ( 67 ACPI_HANDLE ObjHandle, 68 UINT32 NestingLevel, 69 void *Context, 70 void **ReturnValue); 71 72 #if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE 73 static void 74 AcpiDbListInfo ( 75 ACPI_MEMORY_LIST *List); 76 #endif 77 78 79 /* 80 * Statistics subcommands 81 */ 82 static ARGUMENT_INFO AcpiDbStatTypes [] = 83 { 84 {"ALLOCATIONS"}, 85 {"OBJECTS"}, 86 {"MEMORY"}, 87 {"MISC"}, 88 {"TABLES"}, 89 {"SIZES"}, 90 {"STACK"}, 91 {NULL} /* Must be null terminated */ 92 }; 93 94 #define CMD_STAT_ALLOCATIONS 0 95 #define CMD_STAT_OBJECTS 1 96 #define CMD_STAT_MEMORY 2 97 #define CMD_STAT_MISC 3 98 #define CMD_STAT_TABLES 4 99 #define CMD_STAT_SIZES 5 100 #define CMD_STAT_STACK 6 101 102 103 #if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE 104 /******************************************************************************* 105 * 106 * FUNCTION: AcpiDbListInfo 107 * 108 * PARAMETERS: List - Memory list/cache to be displayed 109 * 110 * RETURN: None 111 * 112 * DESCRIPTION: Display information about the input memory list or cache. 113 * 114 ******************************************************************************/ 115 116 static void 117 AcpiDbListInfo ( 118 ACPI_MEMORY_LIST *List) 119 { 120 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 121 UINT32 Outstanding; 122 #endif 123 124 AcpiOsPrintf ("\n%s\n", List->ListName); 125 126 /* MaxDepth > 0 indicates a cache object */ 127 128 if (List->MaxDepth > 0) 129 { 130 AcpiOsPrintf ( 131 " Cache: [Depth MaxD Avail Size] %8.2X %8.2X %8.2X %8.2X\n", 132 List->CurrentDepth, 133 List->MaxDepth, 134 List->MaxDepth - List->CurrentDepth, 135 (List->CurrentDepth * List->ObjectSize)); 136 } 137 138 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 139 if (List->MaxDepth > 0) 140 { 141 AcpiOsPrintf ( 142 " Cache: [Requests Hits Misses ObjSize] %8.2X %8.2X %8.2X %8.2X\n", 143 List->Requests, 144 List->Hits, 145 List->Requests - List->Hits, 146 List->ObjectSize); 147 } 148 149 Outstanding = AcpiDbGetCacheInfo (List); 150 151 if (List->ObjectSize) 152 { 153 AcpiOsPrintf ( 154 " Mem: [Alloc Free Max CurSize Outstanding] %8.2X %8.2X %8.2X %8.2X %8.2X\n", 155 List->TotalAllocated, 156 List->TotalFreed, 157 List->MaxOccupied, 158 Outstanding * List->ObjectSize, 159 Outstanding); 160 } 161 else 162 { 163 AcpiOsPrintf ( 164 " Mem: [Alloc Free Max CurSize Outstanding Total] %8.2X %8.2X %8.2X %8.2X %8.2X %8.2X\n", 165 List->TotalAllocated, 166 List->TotalFreed, 167 List->MaxOccupied, 168 List->CurrentTotalSize, 169 Outstanding, 170 List->TotalSize); 171 } 172 #endif 173 } 174 #endif 175 176 177 /******************************************************************************* 178 * 179 * FUNCTION: AcpiDbEnumerateObject 180 * 181 * PARAMETERS: ObjDesc - Object to be counted 182 * 183 * RETURN: None 184 * 185 * DESCRIPTION: Add this object to the global counts, by object type. 186 * Limited recursion handles subobjects and packages, and this 187 * is probably acceptable within the AML debugger only. 188 * 189 ******************************************************************************/ 190 191 static void 192 AcpiDbEnumerateObject ( 193 ACPI_OPERAND_OBJECT *ObjDesc) 194 { 195 UINT32 i; 196 197 198 if (!ObjDesc) 199 { 200 return; 201 } 202 203 /* Enumerate this object first */ 204 205 AcpiGbl_NumObjects++; 206 207 if (ObjDesc->Common.Type > ACPI_TYPE_NS_NODE_MAX) 208 { 209 AcpiGbl_ObjTypeCountMisc++; 210 } 211 else 212 { 213 AcpiGbl_ObjTypeCount [ObjDesc->Common.Type]++; 214 } 215 216 /* Count the sub-objects */ 217 218 switch (ObjDesc->Common.Type) 219 { 220 case ACPI_TYPE_PACKAGE: 221 222 for (i = 0; i < ObjDesc->Package.Count; i++) 223 { 224 AcpiDbEnumerateObject (ObjDesc->Package.Elements[i]); 225 } 226 break; 227 228 case ACPI_TYPE_DEVICE: 229 230 AcpiDbEnumerateObject (ObjDesc->Device.SystemNotify); 231 AcpiDbEnumerateObject (ObjDesc->Device.DeviceNotify); 232 AcpiDbEnumerateObject (ObjDesc->Device.Handler); 233 break; 234 235 case ACPI_TYPE_BUFFER_FIELD: 236 237 if (AcpiNsGetSecondaryObject (ObjDesc)) 238 { 239 AcpiGbl_ObjTypeCount [ACPI_TYPE_BUFFER_FIELD]++; 240 } 241 break; 242 243 case ACPI_TYPE_REGION: 244 245 AcpiGbl_ObjTypeCount [ACPI_TYPE_LOCAL_REGION_FIELD ]++; 246 AcpiDbEnumerateObject (ObjDesc->Region.Handler); 247 break; 248 249 case ACPI_TYPE_POWER: 250 251 AcpiDbEnumerateObject (ObjDesc->PowerResource.SystemNotify); 252 AcpiDbEnumerateObject (ObjDesc->PowerResource.DeviceNotify); 253 break; 254 255 case ACPI_TYPE_PROCESSOR: 256 257 AcpiDbEnumerateObject (ObjDesc->Processor.SystemNotify); 258 AcpiDbEnumerateObject (ObjDesc->Processor.DeviceNotify); 259 AcpiDbEnumerateObject (ObjDesc->Processor.Handler); 260 break; 261 262 case ACPI_TYPE_THERMAL: 263 264 AcpiDbEnumerateObject (ObjDesc->ThermalZone.SystemNotify); 265 AcpiDbEnumerateObject (ObjDesc->ThermalZone.DeviceNotify); 266 AcpiDbEnumerateObject (ObjDesc->ThermalZone.Handler); 267 break; 268 269 default: 270 break; 271 } 272 } 273 274 275 /******************************************************************************* 276 * 277 * FUNCTION: AcpiDbClassifyOneObject 278 * 279 * PARAMETERS: Callback for WalkNamespace 280 * 281 * RETURN: Status 282 * 283 * DESCRIPTION: Enumerate both the object descriptor (including subobjects) and 284 * the parent namespace node. 285 * 286 ******************************************************************************/ 287 288 static ACPI_STATUS 289 AcpiDbClassifyOneObject ( 290 ACPI_HANDLE ObjHandle, 291 UINT32 NestingLevel, 292 void *Context, 293 void **ReturnValue) 294 { 295 ACPI_NAMESPACE_NODE *Node; 296 ACPI_OPERAND_OBJECT *ObjDesc; 297 UINT32 Type; 298 299 300 AcpiGbl_NumNodes++; 301 302 Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 303 ObjDesc = AcpiNsGetAttachedObject (Node); 304 305 AcpiDbEnumerateObject (ObjDesc); 306 307 Type = Node->Type; 308 if (Type > ACPI_TYPE_NS_NODE_MAX) 309 { 310 AcpiGbl_NodeTypeCountMisc++; 311 } 312 else 313 { 314 AcpiGbl_NodeTypeCount [Type]++; 315 } 316 317 return AE_OK; 318 319 320 #ifdef ACPI_FUTURE_IMPLEMENTATION 321 322 /* TBD: These need to be counted during the initial parsing phase */ 323 324 if (AcpiPsIsNamedOp (Op->Opcode)) 325 { 326 NumNodes++; 327 } 328 329 if (IsMethod) 330 { 331 NumMethodElements++; 332 } 333 334 NumGrammarElements++; 335 Op = AcpiPsGetDepthNext (Root, Op); 336 337 SizeOfParseTree = (NumGrammarElements - NumMethodElements) * 338 (UINT32) sizeof (ACPI_PARSE_OBJECT); 339 SizeOfMethodTrees = NumMethodElements * (UINT32) sizeof (ACPI_PARSE_OBJECT); 340 SizeOfNodeEntries = NumNodes * (UINT32) sizeof (ACPI_NAMESPACE_NODE); 341 SizeOfAcpiObjects = NumNodes * (UINT32) sizeof (ACPI_OPERAND_OBJECT); 342 #endif 343 } 344 345 346 /******************************************************************************* 347 * 348 * FUNCTION: AcpiDbCountNamespaceObjects 349 * 350 * PARAMETERS: None 351 * 352 * RETURN: None 353 * 354 * DESCRIPTION: Count and classify the entire namespace, including all 355 * namespace nodes and attached objects. 356 * 357 ******************************************************************************/ 358 359 static void 360 AcpiDbCountNamespaceObjects ( 361 void) 362 { 363 UINT32 i; 364 365 366 AcpiGbl_NumNodes = 0; 367 AcpiGbl_NumObjects = 0; 368 369 AcpiGbl_ObjTypeCountMisc = 0; 370 for (i = 0; i < (ACPI_TYPE_NS_NODE_MAX -1); i++) 371 { 372 AcpiGbl_ObjTypeCount [i] = 0; 373 AcpiGbl_NodeTypeCount [i] = 0; 374 } 375 376 (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 377 ACPI_UINT32_MAX, FALSE, AcpiDbClassifyOneObject, NULL, NULL, NULL); 378 } 379 380 381 /******************************************************************************* 382 * 383 * FUNCTION: AcpiDbDisplayStatistics 384 * 385 * PARAMETERS: TypeArg - Subcommand 386 * 387 * RETURN: Status 388 * 389 * DESCRIPTION: Display various statistics 390 * 391 ******************************************************************************/ 392 393 ACPI_STATUS 394 AcpiDbDisplayStatistics ( 395 char *TypeArg) 396 { 397 UINT32 i; 398 UINT32 Temp; 399 400 401 if (!TypeArg) 402 { 403 AcpiOsPrintf ("The following subcommands are available:\n ALLOCATIONS, OBJECTS, MEMORY, MISC, SIZES, TABLES\n"); 404 return (AE_OK); 405 } 406 407 AcpiUtStrupr (TypeArg); 408 Temp = AcpiDbMatchArgument (TypeArg, AcpiDbStatTypes); 409 if (Temp == (UINT32) -1) 410 { 411 AcpiOsPrintf ("Invalid or unsupported argument\n"); 412 return (AE_OK); 413 } 414 415 416 switch (Temp) 417 { 418 case CMD_STAT_ALLOCATIONS: 419 420 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 421 AcpiUtDumpAllocationInfo (); 422 #endif 423 break; 424 425 case CMD_STAT_TABLES: 426 427 AcpiOsPrintf ("ACPI Table Information (not implemented):\n\n"); 428 break; 429 430 case CMD_STAT_OBJECTS: 431 432 AcpiDbCountNamespaceObjects (); 433 434 AcpiOsPrintf ("\nObjects defined in the current namespace:\n\n"); 435 436 AcpiOsPrintf ("%16.16s %10.10s %10.10s\n", 437 "ACPI_TYPE", "NODES", "OBJECTS"); 438 439 for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++) 440 { 441 AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", AcpiUtGetTypeName (i), 442 AcpiGbl_NodeTypeCount [i], AcpiGbl_ObjTypeCount [i]); 443 } 444 AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", "Misc/Unknown", 445 AcpiGbl_NodeTypeCountMisc, AcpiGbl_ObjTypeCountMisc); 446 447 AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", "TOTALS:", 448 AcpiGbl_NumNodes, AcpiGbl_NumObjects); 449 break; 450 451 case CMD_STAT_MEMORY: 452 453 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 454 AcpiOsPrintf ("\n----Object Statistics (all in hex)---------\n"); 455 456 AcpiDbListInfo (AcpiGbl_GlobalList); 457 AcpiDbListInfo (AcpiGbl_NsNodeList); 458 #endif 459 460 #ifdef ACPI_USE_LOCAL_CACHE 461 AcpiOsPrintf ("\n----Cache Statistics (all in hex)---------\n"); 462 AcpiDbListInfo (AcpiGbl_OperandCache); 463 AcpiDbListInfo (AcpiGbl_PsNodeCache); 464 AcpiDbListInfo (AcpiGbl_PsNodeExtCache); 465 AcpiDbListInfo (AcpiGbl_StateCache); 466 #endif 467 468 break; 469 470 case CMD_STAT_MISC: 471 472 AcpiOsPrintf ("\nMiscellaneous Statistics:\n\n"); 473 AcpiOsPrintf ("Calls to AcpiPsFind:.. ........% 7ld\n", 474 AcpiGbl_PsFindCount); 475 AcpiOsPrintf ("Calls to AcpiNsLookup:..........% 7ld\n", 476 AcpiGbl_NsLookupCount); 477 478 AcpiOsPrintf ("\n"); 479 480 AcpiOsPrintf ("Mutex usage:\n\n"); 481 for (i = 0; i < ACPI_NUM_MUTEX; i++) 482 { 483 AcpiOsPrintf ("%-28s: % 7ld\n", 484 AcpiUtGetMutexName (i), AcpiGbl_MutexInfo[i].UseCount); 485 } 486 break; 487 488 489 case CMD_STAT_SIZES: 490 491 AcpiOsPrintf ("\nInternal object sizes:\n\n"); 492 493 AcpiOsPrintf ("Common %3d\n", sizeof (ACPI_OBJECT_COMMON)); 494 AcpiOsPrintf ("Number %3d\n", sizeof (ACPI_OBJECT_INTEGER)); 495 AcpiOsPrintf ("String %3d\n", sizeof (ACPI_OBJECT_STRING)); 496 AcpiOsPrintf ("Buffer %3d\n", sizeof (ACPI_OBJECT_BUFFER)); 497 AcpiOsPrintf ("Package %3d\n", sizeof (ACPI_OBJECT_PACKAGE)); 498 AcpiOsPrintf ("BufferField %3d\n", sizeof (ACPI_OBJECT_BUFFER_FIELD)); 499 AcpiOsPrintf ("Device %3d\n", sizeof (ACPI_OBJECT_DEVICE)); 500 AcpiOsPrintf ("Event %3d\n", sizeof (ACPI_OBJECT_EVENT)); 501 AcpiOsPrintf ("Method %3d\n", sizeof (ACPI_OBJECT_METHOD)); 502 AcpiOsPrintf ("Mutex %3d\n", sizeof (ACPI_OBJECT_MUTEX)); 503 AcpiOsPrintf ("Region %3d\n", sizeof (ACPI_OBJECT_REGION)); 504 AcpiOsPrintf ("PowerResource %3d\n", sizeof (ACPI_OBJECT_POWER_RESOURCE)); 505 AcpiOsPrintf ("Processor %3d\n", sizeof (ACPI_OBJECT_PROCESSOR)); 506 AcpiOsPrintf ("ThermalZone %3d\n", sizeof (ACPI_OBJECT_THERMAL_ZONE)); 507 AcpiOsPrintf ("RegionField %3d\n", sizeof (ACPI_OBJECT_REGION_FIELD)); 508 AcpiOsPrintf ("BankField %3d\n", sizeof (ACPI_OBJECT_BANK_FIELD)); 509 AcpiOsPrintf ("IndexField %3d\n", sizeof (ACPI_OBJECT_INDEX_FIELD)); 510 AcpiOsPrintf ("Reference %3d\n", sizeof (ACPI_OBJECT_REFERENCE)); 511 AcpiOsPrintf ("Notify %3d\n", sizeof (ACPI_OBJECT_NOTIFY_HANDLER)); 512 AcpiOsPrintf ("AddressSpace %3d\n", sizeof (ACPI_OBJECT_ADDR_HANDLER)); 513 AcpiOsPrintf ("Extra %3d\n", sizeof (ACPI_OBJECT_EXTRA)); 514 AcpiOsPrintf ("Data %3d\n", sizeof (ACPI_OBJECT_DATA)); 515 516 AcpiOsPrintf ("\n"); 517 518 AcpiOsPrintf ("ParseObject %3d\n", sizeof (ACPI_PARSE_OBJ_COMMON)); 519 AcpiOsPrintf ("ParseObjectNamed %3d\n", sizeof (ACPI_PARSE_OBJ_NAMED)); 520 AcpiOsPrintf ("ParseObjectAsl %3d\n", sizeof (ACPI_PARSE_OBJ_ASL)); 521 AcpiOsPrintf ("OperandObject %3d\n", sizeof (ACPI_OPERAND_OBJECT)); 522 AcpiOsPrintf ("NamespaceNode %3d\n", sizeof (ACPI_NAMESPACE_NODE)); 523 AcpiOsPrintf ("AcpiObject %3d\n", sizeof (ACPI_OBJECT)); 524 525 break; 526 527 528 case CMD_STAT_STACK: 529 #if defined(ACPI_DEBUG_OUTPUT) 530 531 Temp = (UINT32) ACPI_PTR_DIFF (AcpiGbl_EntryStackPointer, AcpiGbl_LowestStackPointer); 532 533 AcpiOsPrintf ("\nSubsystem Stack Usage:\n\n"); 534 AcpiOsPrintf ("Entry Stack Pointer %p\n", AcpiGbl_EntryStackPointer); 535 AcpiOsPrintf ("Lowest Stack Pointer %p\n", AcpiGbl_LowestStackPointer); 536 AcpiOsPrintf ("Stack Use %X (%u)\n", Temp, Temp); 537 AcpiOsPrintf ("Deepest Procedure Nesting %u\n", AcpiGbl_DeepestNesting); 538 #endif 539 break; 540 541 default: 542 break; 543 } 544 545 AcpiOsPrintf ("\n"); 546 return (AE_OK); 547 } 548 549 #endif /* ACPI_DEBUGGER */