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