Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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