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