dbstats.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /*******************************************************************************
  3. *
  4. * Module Name: dbstats - Generation and display of ACPI table statistics
  5. *
  6. ******************************************************************************/
  7. #include <acpi/acpi.h>
  8. #include "accommon.h"
  9. #include "acdebug.h"
  10. #include "acnamesp.h"
  11. #define _COMPONENT ACPI_CA_DEBUGGER
  12. ACPI_MODULE_NAME("dbstats")
  13. /* Local prototypes */
  14. static void acpi_db_count_namespace_objects(void);
  15. static void acpi_db_enumerate_object(union acpi_operand_object *obj_desc);
  16. static acpi_status
  17. acpi_db_classify_one_object(acpi_handle obj_handle,
  18. u32 nesting_level,
  19. void *context, void **return_value);
  20. #if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE
  21. static void acpi_db_list_info(struct acpi_memory_list *list);
  22. #endif
  23. /*
  24. * Statistics subcommands
  25. */
  26. static struct acpi_db_argument_info acpi_db_stat_types[] = {
  27. {"ALLOCATIONS"},
  28. {"OBJECTS"},
  29. {"MEMORY"},
  30. {"MISC"},
  31. {"TABLES"},
  32. {"SIZES"},
  33. {"STACK"},
  34. {NULL} /* Must be null terminated */
  35. };
  36. #define CMD_STAT_ALLOCATIONS 0
  37. #define CMD_STAT_OBJECTS 1
  38. #define CMD_STAT_MEMORY 2
  39. #define CMD_STAT_MISC 3
  40. #define CMD_STAT_TABLES 4
  41. #define CMD_STAT_SIZES 5
  42. #define CMD_STAT_STACK 6
  43. #if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE
  44. /*******************************************************************************
  45. *
  46. * FUNCTION: acpi_db_list_info
  47. *
  48. * PARAMETERS: list - Memory list/cache to be displayed
  49. *
  50. * RETURN: None
  51. *
  52. * DESCRIPTION: Display information about the input memory list or cache.
  53. *
  54. ******************************************************************************/
  55. static void acpi_db_list_info(struct acpi_memory_list *list)
  56. {
  57. #ifdef ACPI_DBG_TRACK_ALLOCATIONS
  58. u32 outstanding;
  59. #endif
  60. acpi_os_printf("\n%s\n", list->list_name);
  61. /* max_depth > 0 indicates a cache object */
  62. if (list->max_depth > 0) {
  63. acpi_os_printf
  64. (" Cache: [Depth MaxD Avail Size] "
  65. "%8.2X %8.2X %8.2X %8.2X\n", list->current_depth,
  66. list->max_depth, list->max_depth - list->current_depth,
  67. (list->current_depth * list->object_size));
  68. }
  69. #ifdef ACPI_DBG_TRACK_ALLOCATIONS
  70. if (list->max_depth > 0) {
  71. acpi_os_printf
  72. (" Cache: [Requests Hits Misses ObjSize] "
  73. "%8.2X %8.2X %8.2X %8.2X\n", list->requests, list->hits,
  74. list->requests - list->hits, list->object_size);
  75. }
  76. outstanding = acpi_db_get_cache_info(list);
  77. if (list->object_size) {
  78. acpi_os_printf
  79. (" Mem: [Alloc Free Max CurSize Outstanding] "
  80. "%8.2X %8.2X %8.2X %8.2X %8.2X\n", list->total_allocated,
  81. list->total_freed, list->max_occupied,
  82. outstanding * list->object_size, outstanding);
  83. } else {
  84. acpi_os_printf
  85. (" Mem: [Alloc Free Max CurSize Outstanding Total] "
  86. "%8.2X %8.2X %8.2X %8.2X %8.2X %8.2X\n",
  87. list->total_allocated, list->total_freed,
  88. list->max_occupied, list->current_total_size, outstanding,
  89. list->total_size);
  90. }
  91. #endif
  92. }
  93. #endif
  94. /*******************************************************************************
  95. *
  96. * FUNCTION: acpi_db_enumerate_object
  97. *
  98. * PARAMETERS: obj_desc - Object to be counted
  99. *
  100. * RETURN: None
  101. *
  102. * DESCRIPTION: Add this object to the global counts, by object type.
  103. * Limited recursion handles subobjects and packages, and this
  104. * is probably acceptable within the AML debugger only.
  105. *
  106. ******************************************************************************/
  107. static void acpi_db_enumerate_object(union acpi_operand_object *obj_desc)
  108. {
  109. u32 i;
  110. if (!obj_desc) {
  111. return;
  112. }
  113. /* Enumerate this object first */
  114. acpi_gbl_num_objects++;
  115. if (obj_desc->common.type > ACPI_TYPE_NS_NODE_MAX) {
  116. acpi_gbl_obj_type_count_misc++;
  117. } else {
  118. acpi_gbl_obj_type_count[obj_desc->common.type]++;
  119. }
  120. /* Count the sub-objects */
  121. switch (obj_desc->common.type) {
  122. case ACPI_TYPE_PACKAGE:
  123. for (i = 0; i < obj_desc->package.count; i++) {
  124. acpi_db_enumerate_object(obj_desc->package.elements[i]);
  125. }
  126. break;
  127. case ACPI_TYPE_DEVICE:
  128. acpi_db_enumerate_object(obj_desc->device.notify_list[0]);
  129. acpi_db_enumerate_object(obj_desc->device.notify_list[1]);
  130. acpi_db_enumerate_object(obj_desc->device.handler);
  131. break;
  132. case ACPI_TYPE_BUFFER_FIELD:
  133. if (acpi_ns_get_secondary_object(obj_desc)) {
  134. acpi_gbl_obj_type_count[ACPI_TYPE_BUFFER_FIELD]++;
  135. }
  136. break;
  137. case ACPI_TYPE_REGION:
  138. acpi_gbl_obj_type_count[ACPI_TYPE_LOCAL_REGION_FIELD]++;
  139. acpi_db_enumerate_object(obj_desc->region.handler);
  140. break;
  141. case ACPI_TYPE_POWER:
  142. acpi_db_enumerate_object(obj_desc->power_resource.
  143. notify_list[0]);
  144. acpi_db_enumerate_object(obj_desc->power_resource.
  145. notify_list[1]);
  146. break;
  147. case ACPI_TYPE_PROCESSOR:
  148. acpi_db_enumerate_object(obj_desc->processor.notify_list[0]);
  149. acpi_db_enumerate_object(obj_desc->processor.notify_list[1]);
  150. acpi_db_enumerate_object(obj_desc->processor.handler);
  151. break;
  152. case ACPI_TYPE_THERMAL:
  153. acpi_db_enumerate_object(obj_desc->thermal_zone.notify_list[0]);
  154. acpi_db_enumerate_object(obj_desc->thermal_zone.notify_list[1]);
  155. acpi_db_enumerate_object(obj_desc->thermal_zone.handler);
  156. break;
  157. default:
  158. break;
  159. }
  160. }
  161. /*******************************************************************************
  162. *
  163. * FUNCTION: acpi_db_classify_one_object
  164. *
  165. * PARAMETERS: Callback for walk_namespace
  166. *
  167. * RETURN: Status
  168. *
  169. * DESCRIPTION: Enumerate both the object descriptor (including subobjects) and
  170. * the parent namespace node.
  171. *
  172. ******************************************************************************/
  173. static acpi_status
  174. acpi_db_classify_one_object(acpi_handle obj_handle,
  175. u32 nesting_level,
  176. void *context, void **return_value)
  177. {
  178. struct acpi_namespace_node *node;
  179. union acpi_operand_object *obj_desc;
  180. u32 type;
  181. acpi_gbl_num_nodes++;
  182. node = (struct acpi_namespace_node *)obj_handle;
  183. obj_desc = acpi_ns_get_attached_object(node);
  184. acpi_db_enumerate_object(obj_desc);
  185. type = node->type;
  186. if (type > ACPI_TYPE_NS_NODE_MAX) {
  187. acpi_gbl_node_type_count_misc++;
  188. } else {
  189. acpi_gbl_node_type_count[type]++;
  190. }
  191. return (AE_OK);
  192. #ifdef ACPI_FUTURE_IMPLEMENTATION
  193. /* TBD: These need to be counted during the initial parsing phase */
  194. if (acpi_ps_is_named_op(op->opcode)) {
  195. num_nodes++;
  196. }
  197. if (is_method) {
  198. num_method_elements++;
  199. }
  200. num_grammar_elements++;
  201. op = acpi_ps_get_depth_next(root, op);
  202. size_of_parse_tree = (num_grammar_elements - num_method_elements) *
  203. (u32)sizeof(union acpi_parse_object);
  204. size_of_method_trees =
  205. num_method_elements * (u32)sizeof(union acpi_parse_object);
  206. size_of_node_entries =
  207. num_nodes * (u32)sizeof(struct acpi_namespace_node);
  208. size_of_acpi_objects =
  209. num_nodes * (u32)sizeof(union acpi_operand_object);
  210. #endif
  211. }
  212. /*******************************************************************************
  213. *
  214. * FUNCTION: acpi_db_count_namespace_objects
  215. *
  216. * PARAMETERS: None
  217. *
  218. * RETURN: None
  219. *
  220. * DESCRIPTION: Count and classify the entire namespace, including all
  221. * namespace nodes and attached objects.
  222. *
  223. ******************************************************************************/
  224. static void acpi_db_count_namespace_objects(void)
  225. {
  226. u32 i;
  227. acpi_gbl_num_nodes = 0;
  228. acpi_gbl_num_objects = 0;
  229. acpi_gbl_obj_type_count_misc = 0;
  230. for (i = 0; i < (ACPI_TYPE_NS_NODE_MAX - 1); i++) {
  231. acpi_gbl_obj_type_count[i] = 0;
  232. acpi_gbl_node_type_count[i] = 0;
  233. }
  234. (void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
  235. ACPI_UINT32_MAX, FALSE,
  236. acpi_db_classify_one_object, NULL, NULL,
  237. NULL);
  238. }
  239. /*******************************************************************************
  240. *
  241. * FUNCTION: acpi_db_display_statistics
  242. *
  243. * PARAMETERS: type_arg - Subcommand
  244. *
  245. * RETURN: Status
  246. *
  247. * DESCRIPTION: Display various statistics
  248. *
  249. ******************************************************************************/
  250. acpi_status acpi_db_display_statistics(char *type_arg)
  251. {
  252. u32 i;
  253. u32 temp;
  254. acpi_ut_strupr(type_arg);
  255. temp = acpi_db_match_argument(type_arg, acpi_db_stat_types);
  256. if (temp == ACPI_TYPE_NOT_FOUND) {
  257. acpi_os_printf("Invalid or unsupported argument\n");
  258. return (AE_OK);
  259. }
  260. switch (temp) {
  261. case CMD_STAT_ALLOCATIONS:
  262. #ifdef ACPI_DBG_TRACK_ALLOCATIONS
  263. acpi_ut_dump_allocation_info();
  264. #endif
  265. break;
  266. case CMD_STAT_TABLES:
  267. acpi_os_printf("ACPI Table Information (not implemented):\n\n");
  268. break;
  269. case CMD_STAT_OBJECTS:
  270. acpi_db_count_namespace_objects();
  271. acpi_os_printf
  272. ("\nObjects defined in the current namespace:\n\n");
  273. acpi_os_printf("%16.16s %10.10s %10.10s\n",
  274. "ACPI_TYPE", "NODES", "OBJECTS");
  275. for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++) {
  276. acpi_os_printf("%16.16s %10u %10u\n",
  277. acpi_ut_get_type_name(i),
  278. acpi_gbl_node_type_count[i],
  279. acpi_gbl_obj_type_count[i]);
  280. }
  281. acpi_os_printf("%16.16s %10u %10u\n", "Misc/Unknown",
  282. acpi_gbl_node_type_count_misc,
  283. acpi_gbl_obj_type_count_misc);
  284. acpi_os_printf("%16.16s %10u %10u\n", "TOTALS:",
  285. acpi_gbl_num_nodes, acpi_gbl_num_objects);
  286. break;
  287. case CMD_STAT_MEMORY:
  288. #ifdef ACPI_DBG_TRACK_ALLOCATIONS
  289. acpi_os_printf
  290. ("\n----Object Statistics (all in hex)---------\n");
  291. acpi_db_list_info(acpi_gbl_global_list);
  292. acpi_db_list_info(acpi_gbl_ns_node_list);
  293. #endif
  294. #ifdef ACPI_USE_LOCAL_CACHE
  295. acpi_os_printf
  296. ("\n----Cache Statistics (all in hex)---------\n");
  297. acpi_db_list_info(acpi_gbl_operand_cache);
  298. acpi_db_list_info(acpi_gbl_ps_node_cache);
  299. acpi_db_list_info(acpi_gbl_ps_node_ext_cache);
  300. acpi_db_list_info(acpi_gbl_state_cache);
  301. #endif
  302. break;
  303. case CMD_STAT_MISC:
  304. acpi_os_printf("\nMiscellaneous Statistics:\n\n");
  305. acpi_os_printf("%-28s: %7u\n", "Calls to AcpiPsFind",
  306. acpi_gbl_ps_find_count);
  307. acpi_os_printf("%-28s: %7u\n", "Calls to AcpiNsLookup",
  308. acpi_gbl_ns_lookup_count);
  309. acpi_os_printf("\nMutex usage:\n\n");
  310. for (i = 0; i < ACPI_NUM_MUTEX; i++) {
  311. acpi_os_printf("%-28s: %7u\n",
  312. acpi_ut_get_mutex_name(i),
  313. acpi_gbl_mutex_info[i].use_count);
  314. }
  315. break;
  316. case CMD_STAT_SIZES:
  317. acpi_os_printf("\nInternal object sizes:\n\n");
  318. acpi_os_printf("Common %3d\n",
  319. (u32)sizeof(struct acpi_object_common));
  320. acpi_os_printf("Number %3d\n",
  321. (u32)sizeof(struct acpi_object_integer));
  322. acpi_os_printf("String %3d\n",
  323. (u32)sizeof(struct acpi_object_string));
  324. acpi_os_printf("Buffer %3d\n",
  325. (u32)sizeof(struct acpi_object_buffer));
  326. acpi_os_printf("Package %3d\n",
  327. (u32)sizeof(struct acpi_object_package));
  328. acpi_os_printf("BufferField %3d\n",
  329. (u32)sizeof(struct acpi_object_buffer_field));
  330. acpi_os_printf("Device %3d\n",
  331. (u32)sizeof(struct acpi_object_device));
  332. acpi_os_printf("Event %3d\n",
  333. (u32)sizeof(struct acpi_object_event));
  334. acpi_os_printf("Method %3d\n",
  335. (u32)sizeof(struct acpi_object_method));
  336. acpi_os_printf("Mutex %3d\n",
  337. (u32)sizeof(struct acpi_object_mutex));
  338. acpi_os_printf("Region %3d\n",
  339. (u32)sizeof(struct acpi_object_region));
  340. acpi_os_printf("PowerResource %3d\n",
  341. (u32)sizeof(struct acpi_object_power_resource));
  342. acpi_os_printf("Processor %3d\n",
  343. (u32)sizeof(struct acpi_object_processor));
  344. acpi_os_printf("ThermalZone %3d\n",
  345. (u32)sizeof(struct acpi_object_thermal_zone));
  346. acpi_os_printf("RegionField %3d\n",
  347. (u32)sizeof(struct acpi_object_region_field));
  348. acpi_os_printf("BankField %3d\n",
  349. (u32)sizeof(struct acpi_object_bank_field));
  350. acpi_os_printf("IndexField %3d\n",
  351. (u32)sizeof(struct acpi_object_index_field));
  352. acpi_os_printf("Reference %3d\n",
  353. (u32)sizeof(struct acpi_object_reference));
  354. acpi_os_printf("Notify %3d\n",
  355. (u32)sizeof(struct acpi_object_notify_handler));
  356. acpi_os_printf("AddressSpace %3d\n",
  357. (u32)sizeof(struct acpi_object_addr_handler));
  358. acpi_os_printf("Extra %3d\n",
  359. (u32)sizeof(struct acpi_object_extra));
  360. acpi_os_printf("Data %3d\n",
  361. (u32)sizeof(struct acpi_object_data));
  362. acpi_os_printf("\n");
  363. acpi_os_printf("ParseObject %3d\n",
  364. (u32)sizeof(struct acpi_parse_obj_common));
  365. acpi_os_printf("ParseObjectNamed %3d\n",
  366. (u32)sizeof(struct acpi_parse_obj_named));
  367. acpi_os_printf("ParseObjectAsl %3d\n",
  368. (u32)sizeof(struct acpi_parse_obj_asl));
  369. acpi_os_printf("OperandObject %3d\n",
  370. (u32)sizeof(union acpi_operand_object));
  371. acpi_os_printf("NamespaceNode %3d\n",
  372. (u32)sizeof(struct acpi_namespace_node));
  373. acpi_os_printf("AcpiObject %3d\n",
  374. (u32)sizeof(union acpi_object));
  375. acpi_os_printf("\n");
  376. acpi_os_printf("Generic State %3d\n",
  377. (u32)sizeof(union acpi_generic_state));
  378. acpi_os_printf("Common State %3d\n",
  379. (u32)sizeof(struct acpi_common_state));
  380. acpi_os_printf("Control State %3d\n",
  381. (u32)sizeof(struct acpi_control_state));
  382. acpi_os_printf("Update State %3d\n",
  383. (u32)sizeof(struct acpi_update_state));
  384. acpi_os_printf("Scope State %3d\n",
  385. (u32)sizeof(struct acpi_scope_state));
  386. acpi_os_printf("Parse Scope %3d\n",
  387. (u32)sizeof(struct acpi_pscope_state));
  388. acpi_os_printf("Package State %3d\n",
  389. (u32)sizeof(struct acpi_pkg_state));
  390. acpi_os_printf("Thread State %3d\n",
  391. (u32)sizeof(struct acpi_thread_state));
  392. acpi_os_printf("Result Values %3d\n",
  393. (u32)sizeof(struct acpi_result_values));
  394. acpi_os_printf("Notify Info %3d\n",
  395. (u32)sizeof(struct acpi_notify_info));
  396. break;
  397. case CMD_STAT_STACK:
  398. #if defined(ACPI_DEBUG_OUTPUT)
  399. temp =
  400. (u32)ACPI_PTR_DIFF(acpi_gbl_entry_stack_pointer,
  401. acpi_gbl_lowest_stack_pointer);
  402. acpi_os_printf("\nSubsystem Stack Usage:\n\n");
  403. acpi_os_printf("Entry Stack Pointer %p\n",
  404. acpi_gbl_entry_stack_pointer);
  405. acpi_os_printf("Lowest Stack Pointer %p\n",
  406. acpi_gbl_lowest_stack_pointer);
  407. acpi_os_printf("Stack Use %X (%u)\n", temp,
  408. temp);
  409. acpi_os_printf("Deepest Procedure Nesting %u\n",
  410. acpi_gbl_deepest_nesting);
  411. #endif
  412. break;
  413. default:
  414. break;
  415. }
  416. acpi_os_printf("\n");
  417. return (AE_OK);
  418. }