Subversion Repositories Kolibri OS

Rev

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

  1. /******************************************************************************
  2.  *
  3.  * Module Name: utcache - local cache allocation routines
  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. #include <acpi/acpi.h>
  45. #include "accommon.h"
  46.  
  47. #define _COMPONENT          ACPI_UTILITIES
  48. ACPI_MODULE_NAME("utcache")
  49.  
  50. #ifdef ACPI_USE_LOCAL_CACHE
  51. /*******************************************************************************
  52.  *
  53.  * FUNCTION:    acpi_os_create_cache
  54.  *
  55.  * PARAMETERS:  cache_name      - Ascii name for the cache
  56.  *              object_size     - Size of each cached object
  57.  *              max_depth       - Maximum depth of the cache (in objects)
  58.  *              return_cache    - Where the new cache object is returned
  59.  *
  60.  * RETURN:      Status
  61.  *
  62.  * DESCRIPTION: Create a cache object
  63.  *
  64.  ******************************************************************************/
  65. acpi_status
  66. acpi_os_create_cache(char *cache_name,
  67.                      u16 object_size,
  68.                      u16 max_depth, struct acpi_memory_list **return_cache)
  69. {
  70.         struct acpi_memory_list *cache;
  71.  
  72.         ACPI_FUNCTION_ENTRY();
  73.  
  74.         if (!cache_name || !return_cache || (object_size < 16)) {
  75.                 return (AE_BAD_PARAMETER);
  76.         }
  77.  
  78.         /* Create the cache object */
  79.  
  80.         cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
  81.         if (!cache) {
  82.                 return (AE_NO_MEMORY);
  83.         }
  84.  
  85.         /* Populate the cache object and return it */
  86.  
  87.         memset(cache, 0, sizeof(struct acpi_memory_list));
  88.         cache->list_name = cache_name;
  89.         cache->object_size = object_size;
  90.         cache->max_depth = max_depth;
  91.  
  92.         *return_cache = cache;
  93.         return (AE_OK);
  94. }
  95.  
  96. /*******************************************************************************
  97.  *
  98.  * FUNCTION:    acpi_os_purge_cache
  99.  *
  100.  * PARAMETERS:  cache           - Handle to cache object
  101.  *
  102.  * RETURN:      Status
  103.  *
  104.  * DESCRIPTION: Free all objects within the requested cache.
  105.  *
  106.  ******************************************************************************/
  107.  
  108. acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
  109. {
  110.         void *next;
  111.         acpi_status status;
  112.  
  113.         ACPI_FUNCTION_ENTRY();
  114.  
  115.         if (!cache) {
  116.                 return (AE_BAD_PARAMETER);
  117.         }
  118.  
  119.         status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
  120.         if (ACPI_FAILURE(status)) {
  121.                 return (status);
  122.         }
  123.  
  124.         /* Walk the list of objects in this cache */
  125.  
  126.         while (cache->list_head) {
  127.  
  128.                 /* Delete and unlink one cached state object */
  129.  
  130.                 next = ACPI_GET_DESCRIPTOR_PTR(cache->list_head);
  131.                 ACPI_FREE(cache->list_head);
  132.  
  133.                 cache->list_head = next;
  134.                 cache->current_depth--;
  135.         }
  136.  
  137.         (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
  138.         return (AE_OK);
  139. }
  140.  
  141. /*******************************************************************************
  142.  *
  143.  * FUNCTION:    acpi_os_delete_cache
  144.  *
  145.  * PARAMETERS:  cache           - Handle to cache object
  146.  *
  147.  * RETURN:      Status
  148.  *
  149.  * DESCRIPTION: Free all objects within the requested cache and delete the
  150.  *              cache object.
  151.  *
  152.  ******************************************************************************/
  153.  
  154. acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache)
  155. {
  156.         acpi_status status;
  157.  
  158.         ACPI_FUNCTION_ENTRY();
  159.  
  160.         /* Purge all objects in the cache */
  161.  
  162.         status = acpi_os_purge_cache(cache);
  163.         if (ACPI_FAILURE(status)) {
  164.                 return (status);
  165.         }
  166.  
  167.         /* Now we can delete the cache object */
  168.  
  169.         acpi_os_free(cache);
  170.         return (AE_OK);
  171. }
  172.  
  173. /*******************************************************************************
  174.  *
  175.  * FUNCTION:    acpi_os_release_object
  176.  *
  177.  * PARAMETERS:  cache       - Handle to cache object
  178.  *              object      - The object to be released
  179.  *
  180.  * RETURN:      None
  181.  *
  182.  * DESCRIPTION: Release an object to the specified cache. If cache is full,
  183.  *              the object is deleted.
  184.  *
  185.  ******************************************************************************/
  186.  
  187. acpi_status
  188. acpi_os_release_object(struct acpi_memory_list * cache, void *object)
  189. {
  190.         acpi_status status;
  191.  
  192.         ACPI_FUNCTION_ENTRY();
  193.  
  194.         if (!cache || !object) {
  195.                 return (AE_BAD_PARAMETER);
  196.         }
  197.  
  198.         /* If cache is full, just free this object */
  199.  
  200.         if (cache->current_depth >= cache->max_depth) {
  201.                 ACPI_FREE(object);
  202.                 ACPI_MEM_TRACKING(cache->total_freed++);
  203.         }
  204.  
  205.         /* Otherwise put this object back into the cache */
  206.  
  207.         else {
  208.                 status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
  209.                 if (ACPI_FAILURE(status)) {
  210.                         return (status);
  211.                 }
  212.  
  213.                 /* Mark the object as cached */
  214.  
  215.                 memset(object, 0xCA, cache->object_size);
  216.                 ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED);
  217.  
  218.                 /* Put the object at the head of the cache list */
  219.  
  220.                 ACPI_SET_DESCRIPTOR_PTR(object, cache->list_head);
  221.                 cache->list_head = object;
  222.                 cache->current_depth++;
  223.  
  224.                 (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
  225.         }
  226.  
  227.         return (AE_OK);
  228. }
  229.  
  230. /*******************************************************************************
  231.  *
  232.  * FUNCTION:    acpi_os_acquire_object
  233.  *
  234.  * PARAMETERS:  cache           - Handle to cache object
  235.  *
  236.  * RETURN:      the acquired object. NULL on error
  237.  *
  238.  * DESCRIPTION: Get an object from the specified cache. If cache is empty,
  239.  *              the object is allocated.
  240.  *
  241.  ******************************************************************************/
  242.  
  243. void *acpi_os_acquire_object(struct acpi_memory_list *cache)
  244. {
  245.         acpi_status status;
  246.         void *object;
  247.  
  248.         ACPI_FUNCTION_NAME(os_acquire_object);
  249.  
  250.         if (!cache) {
  251.                 return_PTR(NULL);
  252.         }
  253.  
  254.         status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
  255.         if (ACPI_FAILURE(status)) {
  256.                 return_PTR(NULL);
  257.         }
  258.  
  259.         ACPI_MEM_TRACKING(cache->requests++);
  260.  
  261.         /* Check the cache first */
  262.  
  263.         if (cache->list_head) {
  264.  
  265.                 /* There is an object available, use it */
  266.  
  267.                 object = cache->list_head;
  268.                 cache->list_head = ACPI_GET_DESCRIPTOR_PTR(object);
  269.  
  270.                 cache->current_depth--;
  271.  
  272.                 ACPI_MEM_TRACKING(cache->hits++);
  273.                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
  274.                                   "Object %p from %s cache\n", object,
  275.                                   cache->list_name));
  276.  
  277.                 status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
  278.                 if (ACPI_FAILURE(status)) {
  279.                         return_PTR(NULL);
  280.                 }
  281.  
  282.                 /* Clear (zero) the previously used Object */
  283.  
  284.                 memset(object, 0, cache->object_size);
  285.         } else {
  286.                 /* The cache is empty, create a new object */
  287.  
  288.                 ACPI_MEM_TRACKING(cache->total_allocated++);
  289.  
  290. #ifdef ACPI_DBG_TRACK_ALLOCATIONS
  291.                 if ((cache->total_allocated - cache->total_freed) >
  292.                     cache->max_occupied) {
  293.                         cache->max_occupied =
  294.                             cache->total_allocated - cache->total_freed;
  295.                 }
  296. #endif
  297.  
  298.                 /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
  299.  
  300.                 status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
  301.                 if (ACPI_FAILURE(status)) {
  302.                         return_PTR(NULL);
  303.                 }
  304.  
  305.                 object = ACPI_ALLOCATE_ZEROED(cache->object_size);
  306.                 if (!object) {
  307.                         return_PTR(NULL);
  308.                 }
  309.         }
  310.  
  311.         return_PTR(object);
  312. }
  313. #endif                          /* ACPI_USE_LOCAL_CACHE */
  314.