uttrack.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Module Name: uttrack - Memory allocation tracking routines (debug only)
  5. *
  6. * Copyright (C) 2000 - 2022, Intel Corp.
  7. *
  8. *****************************************************************************/
  9. /*
  10. * These procedures are used for tracking memory leaks in the subsystem, and
  11. * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
  12. *
  13. * Each memory allocation is tracked via a doubly linked list. Each
  14. * element contains the caller's component, module name, function name, and
  15. * line number. acpi_ut_allocate and acpi_ut_allocate_zeroed call
  16. * acpi_ut_track_allocation to add an element to the list; deletion
  17. * occurs in the body of acpi_ut_free.
  18. */
  19. #include <acpi/acpi.h>
  20. #include "accommon.h"
  21. #ifdef ACPI_DBG_TRACK_ALLOCATIONS
  22. #define _COMPONENT ACPI_UTILITIES
  23. ACPI_MODULE_NAME("uttrack")
  24. /* Local prototypes */
  25. static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
  26. acpi_debug_mem_block
  27. *allocation);
  28. static acpi_status
  29. acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
  30. acpi_size size,
  31. u8 alloc_type,
  32. u32 component, const char *module, u32 line);
  33. static acpi_status
  34. acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
  35. u32 component, const char *module, u32 line);
  36. /*******************************************************************************
  37. *
  38. * FUNCTION: acpi_ut_create_list
  39. *
  40. * PARAMETERS: cache_name - Ascii name for the cache
  41. * object_size - Size of each cached object
  42. * return_cache - Where the new cache object is returned
  43. *
  44. * RETURN: Status
  45. *
  46. * DESCRIPTION: Create a local memory list for tracking purposed
  47. *
  48. ******************************************************************************/
  49. acpi_status
  50. acpi_ut_create_list(const char *list_name,
  51. u16 object_size, struct acpi_memory_list **return_cache)
  52. {
  53. struct acpi_memory_list *cache;
  54. cache = acpi_os_allocate_zeroed(sizeof(struct acpi_memory_list));
  55. if (!cache) {
  56. return (AE_NO_MEMORY);
  57. }
  58. cache->list_name = list_name;
  59. cache->object_size = object_size;
  60. *return_cache = cache;
  61. return (AE_OK);
  62. }
  63. /*******************************************************************************
  64. *
  65. * FUNCTION: acpi_ut_allocate_and_track
  66. *
  67. * PARAMETERS: size - Size of the allocation
  68. * component - Component type of caller
  69. * module - Source file name of caller
  70. * line - Line number of caller
  71. *
  72. * RETURN: Address of the allocated memory on success, NULL on failure.
  73. *
  74. * DESCRIPTION: The subsystem's equivalent of malloc.
  75. *
  76. ******************************************************************************/
  77. void *acpi_ut_allocate_and_track(acpi_size size,
  78. u32 component, const char *module, u32 line)
  79. {
  80. struct acpi_debug_mem_block *allocation;
  81. acpi_status status;
  82. /* Check for an inadvertent size of zero bytes */
  83. if (!size) {
  84. ACPI_WARNING((module, line,
  85. "Attempt to allocate zero bytes, allocating 1 byte"));
  86. size = 1;
  87. }
  88. allocation =
  89. acpi_os_allocate(size + sizeof(struct acpi_debug_mem_header));
  90. if (!allocation) {
  91. /* Report allocation error */
  92. ACPI_WARNING((module, line,
  93. "Could not allocate size %u", (u32)size));
  94. return (NULL);
  95. }
  96. status =
  97. acpi_ut_track_allocation(allocation, size, ACPI_MEM_MALLOC,
  98. component, module, line);
  99. if (ACPI_FAILURE(status)) {
  100. acpi_os_free(allocation);
  101. return (NULL);
  102. }
  103. acpi_gbl_global_list->total_allocated++;
  104. acpi_gbl_global_list->total_size += (u32)size;
  105. acpi_gbl_global_list->current_total_size += (u32)size;
  106. if (acpi_gbl_global_list->current_total_size >
  107. acpi_gbl_global_list->max_occupied) {
  108. acpi_gbl_global_list->max_occupied =
  109. acpi_gbl_global_list->current_total_size;
  110. }
  111. return ((void *)&allocation->user_space);
  112. }
  113. /*******************************************************************************
  114. *
  115. * FUNCTION: acpi_ut_allocate_zeroed_and_track
  116. *
  117. * PARAMETERS: size - Size of the allocation
  118. * component - Component type of caller
  119. * module - Source file name of caller
  120. * line - Line number of caller
  121. *
  122. * RETURN: Address of the allocated memory on success, NULL on failure.
  123. *
  124. * DESCRIPTION: Subsystem equivalent of calloc.
  125. *
  126. ******************************************************************************/
  127. void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
  128. u32 component,
  129. const char *module, u32 line)
  130. {
  131. struct acpi_debug_mem_block *allocation;
  132. acpi_status status;
  133. /* Check for an inadvertent size of zero bytes */
  134. if (!size) {
  135. ACPI_WARNING((module, line,
  136. "Attempt to allocate zero bytes, allocating 1 byte"));
  137. size = 1;
  138. }
  139. allocation =
  140. acpi_os_allocate_zeroed(size +
  141. sizeof(struct acpi_debug_mem_header));
  142. if (!allocation) {
  143. /* Report allocation error */
  144. ACPI_ERROR((module, line,
  145. "Could not allocate size %u", (u32)size));
  146. return (NULL);
  147. }
  148. status = acpi_ut_track_allocation(allocation, size,
  149. ACPI_MEM_CALLOC, component, module,
  150. line);
  151. if (ACPI_FAILURE(status)) {
  152. acpi_os_free(allocation);
  153. return (NULL);
  154. }
  155. acpi_gbl_global_list->total_allocated++;
  156. acpi_gbl_global_list->total_size += (u32)size;
  157. acpi_gbl_global_list->current_total_size += (u32)size;
  158. if (acpi_gbl_global_list->current_total_size >
  159. acpi_gbl_global_list->max_occupied) {
  160. acpi_gbl_global_list->max_occupied =
  161. acpi_gbl_global_list->current_total_size;
  162. }
  163. return ((void *)&allocation->user_space);
  164. }
  165. /*******************************************************************************
  166. *
  167. * FUNCTION: acpi_ut_free_and_track
  168. *
  169. * PARAMETERS: allocation - Address of the memory to deallocate
  170. * component - Component type of caller
  171. * module - Source file name of caller
  172. * line - Line number of caller
  173. *
  174. * RETURN: None
  175. *
  176. * DESCRIPTION: Frees the memory at Allocation
  177. *
  178. ******************************************************************************/
  179. void
  180. acpi_ut_free_and_track(void *allocation,
  181. u32 component, const char *module, u32 line)
  182. {
  183. struct acpi_debug_mem_block *debug_block;
  184. acpi_status status;
  185. ACPI_FUNCTION_TRACE_PTR(ut_free, allocation);
  186. if (NULL == allocation) {
  187. ACPI_ERROR((module, line, "Attempt to delete a NULL address"));
  188. return_VOID;
  189. }
  190. debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block,
  191. (((char *)allocation) -
  192. sizeof(struct acpi_debug_mem_header)));
  193. acpi_gbl_global_list->total_freed++;
  194. acpi_gbl_global_list->current_total_size -= debug_block->size;
  195. status =
  196. acpi_ut_remove_allocation(debug_block, component, module, line);
  197. if (ACPI_FAILURE(status)) {
  198. ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
  199. }
  200. acpi_os_free(debug_block);
  201. ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n",
  202. allocation, debug_block));
  203. return_VOID;
  204. }
  205. /*******************************************************************************
  206. *
  207. * FUNCTION: acpi_ut_find_allocation
  208. *
  209. * PARAMETERS: allocation - Address of allocated memory
  210. *
  211. * RETURN: Three cases:
  212. * 1) List is empty, NULL is returned.
  213. * 2) Element was found. Returns Allocation parameter.
  214. * 3) Element was not found. Returns position where it should be
  215. * inserted into the list.
  216. *
  217. * DESCRIPTION: Searches for an element in the global allocation tracking list.
  218. * If the element is not found, returns the location within the
  219. * list where the element should be inserted.
  220. *
  221. * Note: The list is ordered by larger-to-smaller addresses.
  222. *
  223. * This global list is used to detect memory leaks in ACPICA as
  224. * well as other issues such as an attempt to release the same
  225. * internal object more than once. Although expensive as far
  226. * as cpu time, this list is much more helpful for finding these
  227. * types of issues than using memory leak detectors outside of
  228. * the ACPICA code.
  229. *
  230. ******************************************************************************/
  231. static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
  232. acpi_debug_mem_block
  233. *allocation)
  234. {
  235. struct acpi_debug_mem_block *element;
  236. element = acpi_gbl_global_list->list_head;
  237. if (!element) {
  238. return (NULL);
  239. }
  240. /*
  241. * Search for the address.
  242. *
  243. * Note: List is ordered by larger-to-smaller addresses, on the
  244. * assumption that a new allocation usually has a larger address
  245. * than previous allocations.
  246. */
  247. while (element > allocation) {
  248. /* Check for end-of-list */
  249. if (!element->next) {
  250. return (element);
  251. }
  252. element = element->next;
  253. }
  254. if (element == allocation) {
  255. return (element);
  256. }
  257. return (element->previous);
  258. }
  259. /*******************************************************************************
  260. *
  261. * FUNCTION: acpi_ut_track_allocation
  262. *
  263. * PARAMETERS: allocation - Address of allocated memory
  264. * size - Size of the allocation
  265. * alloc_type - MEM_MALLOC or MEM_CALLOC
  266. * component - Component type of caller
  267. * module - Source file name of caller
  268. * line - Line number of caller
  269. *
  270. * RETURN: Status
  271. *
  272. * DESCRIPTION: Inserts an element into the global allocation tracking list.
  273. *
  274. ******************************************************************************/
  275. static acpi_status
  276. acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
  277. acpi_size size,
  278. u8 alloc_type,
  279. u32 component, const char *module, u32 line)
  280. {
  281. struct acpi_memory_list *mem_list;
  282. struct acpi_debug_mem_block *element;
  283. acpi_status status = AE_OK;
  284. ACPI_FUNCTION_TRACE_PTR(ut_track_allocation, allocation);
  285. if (acpi_gbl_disable_mem_tracking) {
  286. return_ACPI_STATUS(AE_OK);
  287. }
  288. mem_list = acpi_gbl_global_list;
  289. status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
  290. if (ACPI_FAILURE(status)) {
  291. return_ACPI_STATUS(status);
  292. }
  293. /*
  294. * Search the global list for this address to make sure it is not
  295. * already present. This will catch several kinds of problems.
  296. */
  297. element = acpi_ut_find_allocation(allocation);
  298. if (element == allocation) {
  299. ACPI_ERROR((AE_INFO,
  300. "UtTrackAllocation: Allocation (%p) already present in global list!",
  301. allocation));
  302. goto unlock_and_exit;
  303. }
  304. /* Fill in the instance data */
  305. allocation->size = (u32)size;
  306. allocation->alloc_type = alloc_type;
  307. allocation->component = component;
  308. allocation->line = line;
  309. acpi_ut_safe_strncpy(allocation->module, (char *)module,
  310. ACPI_MAX_MODULE_NAME);
  311. if (!element) {
  312. /* Insert at list head */
  313. if (mem_list->list_head) {
  314. ((struct acpi_debug_mem_block *)(mem_list->list_head))->
  315. previous = allocation;
  316. }
  317. allocation->next = mem_list->list_head;
  318. allocation->previous = NULL;
  319. mem_list->list_head = allocation;
  320. } else {
  321. /* Insert after element */
  322. allocation->next = element->next;
  323. allocation->previous = element;
  324. if (element->next) {
  325. (element->next)->previous = allocation;
  326. }
  327. element->next = allocation;
  328. }
  329. unlock_and_exit:
  330. status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
  331. return_ACPI_STATUS(status);
  332. }
  333. /*******************************************************************************
  334. *
  335. * FUNCTION: acpi_ut_remove_allocation
  336. *
  337. * PARAMETERS: allocation - Address of allocated memory
  338. * component - Component type of caller
  339. * module - Source file name of caller
  340. * line - Line number of caller
  341. *
  342. * RETURN: Status
  343. *
  344. * DESCRIPTION: Deletes an element from the global allocation tracking list.
  345. *
  346. ******************************************************************************/
  347. static acpi_status
  348. acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
  349. u32 component, const char *module, u32 line)
  350. {
  351. struct acpi_memory_list *mem_list;
  352. acpi_status status;
  353. ACPI_FUNCTION_NAME(ut_remove_allocation);
  354. if (acpi_gbl_disable_mem_tracking) {
  355. return (AE_OK);
  356. }
  357. mem_list = acpi_gbl_global_list;
  358. if (NULL == mem_list->list_head) {
  359. /* No allocations! */
  360. ACPI_ERROR((module, line,
  361. "Empty allocation list, nothing to free!"));
  362. return (AE_OK);
  363. }
  364. status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
  365. if (ACPI_FAILURE(status)) {
  366. return (status);
  367. }
  368. /* Unlink */
  369. if (allocation->previous) {
  370. (allocation->previous)->next = allocation->next;
  371. } else {
  372. mem_list->list_head = allocation->next;
  373. }
  374. if (allocation->next) {
  375. (allocation->next)->previous = allocation->previous;
  376. }
  377. ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
  378. &allocation->user_space, allocation->size));
  379. /* Mark the segment as deleted */
  380. memset(&allocation->user_space, 0xEA, allocation->size);
  381. status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
  382. return (status);
  383. }
  384. /*******************************************************************************
  385. *
  386. * FUNCTION: acpi_ut_dump_allocation_info
  387. *
  388. * PARAMETERS: None
  389. *
  390. * RETURN: None
  391. *
  392. * DESCRIPTION: Print some info about the outstanding allocations.
  393. *
  394. ******************************************************************************/
  395. void acpi_ut_dump_allocation_info(void)
  396. {
  397. /*
  398. struct acpi_memory_list *mem_list;
  399. */
  400. ACPI_FUNCTION_TRACE(ut_dump_allocation_info);
  401. /*
  402. ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
  403. ("%30s: %4d (%3d Kb)\n", "Current allocations",
  404. mem_list->current_count,
  405. ROUND_UP_TO_1K (mem_list->current_size)));
  406. ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
  407. ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
  408. mem_list->max_concurrent_count,
  409. ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
  410. ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
  411. ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
  412. running_object_count,
  413. ROUND_UP_TO_1K (running_object_size)));
  414. ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
  415. ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
  416. running_alloc_count,
  417. ROUND_UP_TO_1K (running_alloc_size)));
  418. ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
  419. ("%30s: %4d (%3d Kb)\n", "Current Nodes",
  420. acpi_gbl_current_node_count,
  421. ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
  422. ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
  423. ("%30s: %4d (%3d Kb)\n", "Max Nodes",
  424. acpi_gbl_max_concurrent_node_count,
  425. ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
  426. sizeof (struct acpi_namespace_node)))));
  427. */
  428. return_VOID;
  429. }
  430. /*******************************************************************************
  431. *
  432. * FUNCTION: acpi_ut_dump_allocations
  433. *
  434. * PARAMETERS: component - Component(s) to dump info for.
  435. * module - Module to dump info for. NULL means all.
  436. *
  437. * RETURN: None
  438. *
  439. * DESCRIPTION: Print a list of all outstanding allocations.
  440. *
  441. ******************************************************************************/
  442. void acpi_ut_dump_allocations(u32 component, const char *module)
  443. {
  444. struct acpi_debug_mem_block *element;
  445. union acpi_descriptor *descriptor;
  446. u32 num_outstanding = 0;
  447. u8 descriptor_type;
  448. ACPI_FUNCTION_TRACE(ut_dump_allocations);
  449. if (acpi_gbl_disable_mem_tracking) {
  450. return_VOID;
  451. }
  452. /*
  453. * Walk the allocation list.
  454. */
  455. if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
  456. return_VOID;
  457. }
  458. if (!acpi_gbl_global_list) {
  459. goto exit;
  460. }
  461. element = acpi_gbl_global_list->list_head;
  462. while (element) {
  463. if ((element->component & component) &&
  464. ((module == NULL)
  465. || (0 == strcmp(module, element->module)))) {
  466. descriptor =
  467. ACPI_CAST_PTR(union acpi_descriptor,
  468. &element->user_space);
  469. if (element->size <
  470. sizeof(struct acpi_common_descriptor)) {
  471. acpi_os_printf("%p Length 0x%04X %9.9s-%4.4u "
  472. "[Not a Descriptor - too small]\n",
  473. descriptor, element->size,
  474. element->module, element->line);
  475. } else {
  476. /* Ignore allocated objects that are in a cache */
  477. if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) !=
  478. ACPI_DESC_TYPE_CACHED) {
  479. acpi_os_printf
  480. ("%p Length 0x%04X %9.9s-%4.4u [%s] ",
  481. descriptor, element->size,
  482. element->module, element->line,
  483. acpi_ut_get_descriptor_name
  484. (descriptor));
  485. /* Optional object hex dump */
  486. if (acpi_gbl_verbose_leak_dump) {
  487. acpi_os_printf("\n");
  488. acpi_ut_dump_buffer((u8 *)
  489. descriptor,
  490. element->
  491. size,
  492. DB_BYTE_DISPLAY,
  493. 0);
  494. }
  495. /* Validate the descriptor type using Type field and length */
  496. descriptor_type = 0; /* Not a valid descriptor type */
  497. switch (ACPI_GET_DESCRIPTOR_TYPE
  498. (descriptor)) {
  499. case ACPI_DESC_TYPE_OPERAND:
  500. if (element->size ==
  501. sizeof(union
  502. acpi_operand_object))
  503. {
  504. descriptor_type =
  505. ACPI_DESC_TYPE_OPERAND;
  506. }
  507. break;
  508. case ACPI_DESC_TYPE_PARSER:
  509. if (element->size ==
  510. sizeof(union
  511. acpi_parse_object)) {
  512. descriptor_type =
  513. ACPI_DESC_TYPE_PARSER;
  514. }
  515. break;
  516. case ACPI_DESC_TYPE_NAMED:
  517. if (element->size ==
  518. sizeof(struct
  519. acpi_namespace_node))
  520. {
  521. descriptor_type =
  522. ACPI_DESC_TYPE_NAMED;
  523. }
  524. break;
  525. default:
  526. break;
  527. }
  528. /* Display additional info for the major descriptor types */
  529. switch (descriptor_type) {
  530. case ACPI_DESC_TYPE_OPERAND:
  531. acpi_os_printf
  532. ("%12.12s RefCount 0x%04X\n",
  533. acpi_ut_get_type_name
  534. (descriptor->object.common.
  535. type),
  536. descriptor->object.common.
  537. reference_count);
  538. break;
  539. case ACPI_DESC_TYPE_PARSER:
  540. acpi_os_printf
  541. ("AmlOpcode 0x%04X\n",
  542. descriptor->op.asl.
  543. aml_opcode);
  544. break;
  545. case ACPI_DESC_TYPE_NAMED:
  546. acpi_os_printf("%4.4s\n",
  547. acpi_ut_get_node_name
  548. (&descriptor->
  549. node));
  550. break;
  551. default:
  552. acpi_os_printf("\n");
  553. break;
  554. }
  555. }
  556. }
  557. num_outstanding++;
  558. }
  559. element = element->next;
  560. }
  561. exit:
  562. (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
  563. /* Print summary */
  564. if (!num_outstanding) {
  565. ACPI_INFO(("No outstanding allocations"));
  566. } else {
  567. ACPI_ERROR((AE_INFO, "%u (0x%X) Outstanding cache allocations",
  568. num_outstanding, num_outstanding));
  569. }
  570. return_VOID;
  571. }
  572. #endif /* ACPI_DBG_TRACK_ALLOCATIONS */