dbstats.c revision 229989
1/*******************************************************************************
2 *
3 * Module Name: dbstats - Generation and display of ACPI table statistics
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2012, 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 <contrib/dev/acpica/include/acpi.h>
46#include <contrib/dev/acpica/include/accommon.h>
47#include <contrib/dev/acpica/include/acdebug.h>
48#include <contrib/dev/acpica/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
57static void
58AcpiDbCountNamespaceObjects (
59    void);
60
61static void
62AcpiDbEnumerateObject (
63    ACPI_OPERAND_OBJECT     *ObjDesc);
64
65static ACPI_STATUS
66AcpiDbClassifyOneObject (
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
73static void
74AcpiDbListInfo (
75    ACPI_MEMORY_LIST        *List);
76#endif
77
78
79/*
80 * Statistics subcommands
81 */
82static 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
116static void
117AcpiDbListInfo (
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
191static void
192AcpiDbEnumerateObject (
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
288static ACPI_STATUS
289AcpiDbClassifyOneObject (
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
359static void
360AcpiDbCountNamespaceObjects (
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
393ACPI_STATUS
394AcpiDbDisplayStatistics (
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  */
550