root/drivers/acpi/acpica/utcache.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_os_purge_cache
  3. acpi_os_delete_cache
  4. acpi_os_release_object
  5. acpi_os_acquire_object

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

/* [<][>][^][v][top][bottom][index][help] */