Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: utcache - local cache allocation routines
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 
0013 #define _COMPONENT          ACPI_UTILITIES
0014 ACPI_MODULE_NAME("utcache")
0015 
0016 #ifdef ACPI_USE_LOCAL_CACHE
0017 /*******************************************************************************
0018  *
0019  * FUNCTION:    acpi_os_create_cache
0020  *
0021  * PARAMETERS:  cache_name      - Ascii name for the cache
0022  *              object_size     - Size of each cached object
0023  *              max_depth       - Maximum depth of the cache (in objects)
0024  *              return_cache    - Where the new cache object is returned
0025  *
0026  * RETURN:      Status
0027  *
0028  * DESCRIPTION: Create a cache object
0029  *
0030  ******************************************************************************/
0031 acpi_status
0032 acpi_os_create_cache(char *cache_name,
0033              u16 object_size,
0034              u16 max_depth, struct acpi_memory_list **return_cache)
0035 {
0036     struct acpi_memory_list *cache;
0037 
0038     ACPI_FUNCTION_ENTRY();
0039 
0040     if (!cache_name || !return_cache || !object_size) {
0041         return (AE_BAD_PARAMETER);
0042     }
0043 
0044     /* Create the cache object */
0045 
0046     cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
0047     if (!cache) {
0048         return (AE_NO_MEMORY);
0049     }
0050 
0051     /* Populate the cache object and return it */
0052 
0053     memset(cache, 0, sizeof(struct acpi_memory_list));
0054     cache->list_name = cache_name;
0055     cache->object_size = object_size;
0056     cache->max_depth = max_depth;
0057 
0058     *return_cache = cache;
0059     return (AE_OK);
0060 }
0061 
0062 /*******************************************************************************
0063  *
0064  * FUNCTION:    acpi_os_purge_cache
0065  *
0066  * PARAMETERS:  cache           - Handle to cache object
0067  *
0068  * RETURN:      Status
0069  *
0070  * DESCRIPTION: Free all objects within the requested cache.
0071  *
0072  ******************************************************************************/
0073 
0074 acpi_status acpi_os_purge_cache(struct acpi_memory_list *cache)
0075 {
0076     void *next;
0077     acpi_status status;
0078 
0079     ACPI_FUNCTION_ENTRY();
0080 
0081     if (!cache) {
0082         return (AE_BAD_PARAMETER);
0083     }
0084 
0085     status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
0086     if (ACPI_FAILURE(status)) {
0087         return (status);
0088     }
0089 
0090     /* Walk the list of objects in this cache */
0091 
0092     while (cache->list_head) {
0093 
0094         /* Delete and unlink one cached state object */
0095 
0096         next = ACPI_GET_DESCRIPTOR_PTR(cache->list_head);
0097         ACPI_FREE(cache->list_head);
0098 
0099         cache->list_head = next;
0100         cache->current_depth--;
0101     }
0102 
0103     (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
0104     return (AE_OK);
0105 }
0106 
0107 /*******************************************************************************
0108  *
0109  * FUNCTION:    acpi_os_delete_cache
0110  *
0111  * PARAMETERS:  cache           - Handle to cache object
0112  *
0113  * RETURN:      Status
0114  *
0115  * DESCRIPTION: Free all objects within the requested cache and delete the
0116  *              cache object.
0117  *
0118  ******************************************************************************/
0119 
0120 acpi_status acpi_os_delete_cache(struct acpi_memory_list *cache)
0121 {
0122     acpi_status status;
0123 
0124     ACPI_FUNCTION_ENTRY();
0125 
0126     /* Purge all objects in the cache */
0127 
0128     status = acpi_os_purge_cache(cache);
0129     if (ACPI_FAILURE(status)) {
0130         return (status);
0131     }
0132 
0133     /* Now we can delete the cache object */
0134 
0135     acpi_os_free(cache);
0136     return (AE_OK);
0137 }
0138 
0139 /*******************************************************************************
0140  *
0141  * FUNCTION:    acpi_os_release_object
0142  *
0143  * PARAMETERS:  cache       - Handle to cache object
0144  *              object      - The object to be released
0145  *
0146  * RETURN:      None
0147  *
0148  * DESCRIPTION: Release an object to the specified cache. If cache is full,
0149  *              the object is deleted.
0150  *
0151  ******************************************************************************/
0152 
0153 acpi_status acpi_os_release_object(struct acpi_memory_list *cache, void *object)
0154 {
0155     acpi_status status;
0156 
0157     ACPI_FUNCTION_ENTRY();
0158 
0159     if (!cache || !object) {
0160         return (AE_BAD_PARAMETER);
0161     }
0162 
0163     /* If cache is full, just free this object */
0164 
0165     if (cache->current_depth >= cache->max_depth) {
0166         ACPI_FREE(object);
0167         ACPI_MEM_TRACKING(cache->total_freed++);
0168     }
0169 
0170     /* Otherwise put this object back into the cache */
0171 
0172     else {
0173         status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
0174         if (ACPI_FAILURE(status)) {
0175             return (status);
0176         }
0177 
0178         /* Mark the object as cached */
0179 
0180         memset(object, 0xCA, cache->object_size);
0181         ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED);
0182 
0183         /* Put the object at the head of the cache list */
0184 
0185         ACPI_SET_DESCRIPTOR_PTR(object, cache->list_head);
0186         cache->list_head = object;
0187         cache->current_depth++;
0188 
0189         (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
0190     }
0191 
0192     return (AE_OK);
0193 }
0194 
0195 /*******************************************************************************
0196  *
0197  * FUNCTION:    acpi_os_acquire_object
0198  *
0199  * PARAMETERS:  cache           - Handle to cache object
0200  *
0201  * RETURN:      the acquired object. NULL on error
0202  *
0203  * DESCRIPTION: Get an object from the specified cache. If cache is empty,
0204  *              the object is allocated.
0205  *
0206  ******************************************************************************/
0207 
0208 void *acpi_os_acquire_object(struct acpi_memory_list *cache)
0209 {
0210     acpi_status status;
0211     void *object;
0212 
0213     ACPI_FUNCTION_TRACE(os_acquire_object);
0214 
0215     if (!cache) {
0216         return_PTR(NULL);
0217     }
0218 
0219     status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
0220     if (ACPI_FAILURE(status)) {
0221         return_PTR(NULL);
0222     }
0223 
0224     ACPI_MEM_TRACKING(cache->requests++);
0225 
0226     /* Check the cache first */
0227 
0228     if (cache->list_head) {
0229 
0230         /* There is an object available, use it */
0231 
0232         object = cache->list_head;
0233         cache->list_head = ACPI_GET_DESCRIPTOR_PTR(object);
0234 
0235         cache->current_depth--;
0236 
0237         ACPI_MEM_TRACKING(cache->hits++);
0238         ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
0239                       "%s: Object %p from %s cache\n",
0240                       ACPI_GET_FUNCTION_NAME, object,
0241                       cache->list_name));
0242 
0243         status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
0244         if (ACPI_FAILURE(status)) {
0245             return_PTR(NULL);
0246         }
0247 
0248         /* Clear (zero) the previously used Object */
0249 
0250         memset(object, 0, cache->object_size);
0251     } else {
0252         /* The cache is empty, create a new object */
0253 
0254         ACPI_MEM_TRACKING(cache->total_allocated++);
0255 
0256 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
0257         if ((cache->total_allocated - cache->total_freed) >
0258             cache->max_occupied) {
0259             cache->max_occupied =
0260                 cache->total_allocated - cache->total_freed;
0261         }
0262 #endif
0263 
0264         /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
0265 
0266         status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
0267         if (ACPI_FAILURE(status)) {
0268             return_PTR(NULL);
0269         }
0270 
0271         object = ACPI_ALLOCATE_ZEROED(cache->object_size);
0272         if (!object) {
0273             return_PTR(NULL);
0274         }
0275     }
0276 
0277     return_PTR(object);
0278 }
0279 #endif              /* ACPI_USE_LOCAL_CACHE */