Home | History | Annotate | Line # | Download | only in utilities
utcache.c revision 1.1.1.5
      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.h"
     45 #include "accommon.h"
     46 
     47 #define _COMPONENT          ACPI_UTILITIES
     48         ACPI_MODULE_NAME    ("utcache")
     49 
     50 
     51 #ifdef ACPI_USE_LOCAL_CACHE
     52 /*******************************************************************************
     53  *
     54  * FUNCTION:    AcpiOsCreateCache
     55  *
     56  * PARAMETERS:  CacheName       - Ascii name for the cache
     57  *              ObjectSize      - Size of each cached object
     58  *              MaxDepth        - Maximum depth of the cache (in objects)
     59  *              ReturnCache     - Where the new cache object is returned
     60  *
     61  * RETURN:      Status
     62  *
     63  * DESCRIPTION: Create a cache object
     64  *
     65  ******************************************************************************/
     66 
     67 ACPI_STATUS
     68 AcpiOsCreateCache (
     69     char                    *CacheName,
     70     UINT16                  ObjectSize,
     71     UINT16                  MaxDepth,
     72     ACPI_MEMORY_LIST        **ReturnCache)
     73 {
     74     ACPI_MEMORY_LIST        *Cache;
     75 
     76 
     77     ACPI_FUNCTION_ENTRY ();
     78 
     79 
     80     if (!CacheName || !ReturnCache || (ObjectSize < 16))
     81     {
     82         return (AE_BAD_PARAMETER);
     83     }
     84 
     85     /* Create the cache object */
     86 
     87     Cache = AcpiOsAllocate (sizeof (ACPI_MEMORY_LIST));
     88     if (!Cache)
     89     {
     90         return (AE_NO_MEMORY);
     91     }
     92 
     93     /* Populate the cache object and return it */
     94 
     95     ACPI_MEMSET (Cache, 0, sizeof (ACPI_MEMORY_LIST));
     96     Cache->ListName   = CacheName;
     97     Cache->ObjectSize = ObjectSize;
     98     Cache->MaxDepth   = MaxDepth;
     99 
    100     *ReturnCache = Cache;
    101     return (AE_OK);
    102 }
    103 
    104 
    105 /*******************************************************************************
    106  *
    107  * FUNCTION:    AcpiOsPurgeCache
    108  *
    109  * PARAMETERS:  Cache           - Handle to cache object
    110  *
    111  * RETURN:      Status
    112  *
    113  * DESCRIPTION: Free all objects within the requested cache.
    114  *
    115  ******************************************************************************/
    116 
    117 ACPI_STATUS
    118 AcpiOsPurgeCache (
    119     ACPI_MEMORY_LIST        *Cache)
    120 {
    121     void                    *Next;
    122     ACPI_STATUS             Status;
    123 
    124 
    125     ACPI_FUNCTION_ENTRY ();
    126 
    127 
    128     if (!Cache)
    129     {
    130         return (AE_BAD_PARAMETER);
    131     }
    132 
    133     Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
    134     if (ACPI_FAILURE (Status))
    135     {
    136         return (Status);
    137     }
    138 
    139     /* Walk the list of objects in this cache */
    140 
    141     while (Cache->ListHead)
    142     {
    143         /* Delete and unlink one cached state object */
    144 
    145         Next = ACPI_GET_DESCRIPTOR_PTR (Cache->ListHead);
    146         ACPI_FREE (Cache->ListHead);
    147 
    148         Cache->ListHead = Next;
    149         Cache->CurrentDepth--;
    150     }
    151 
    152     (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
    153     return (AE_OK);
    154 }
    155 
    156 
    157 /*******************************************************************************
    158  *
    159  * FUNCTION:    AcpiOsDeleteCache
    160  *
    161  * PARAMETERS:  Cache           - Handle to cache object
    162  *
    163  * RETURN:      Status
    164  *
    165  * DESCRIPTION: Free all objects within the requested cache and delete the
    166  *              cache object.
    167  *
    168  ******************************************************************************/
    169 
    170 ACPI_STATUS
    171 AcpiOsDeleteCache (
    172     ACPI_MEMORY_LIST        *Cache)
    173 {
    174     ACPI_STATUS             Status;
    175 
    176 
    177     ACPI_FUNCTION_ENTRY ();
    178 
    179 
    180    /* Purge all objects in the cache */
    181 
    182     Status = AcpiOsPurgeCache (Cache);
    183     if (ACPI_FAILURE (Status))
    184     {
    185         return (Status);
    186     }
    187 
    188     /* Now we can delete the cache object */
    189 
    190     AcpiOsFree (Cache);
    191     return (AE_OK);
    192 }
    193 
    194 
    195 /*******************************************************************************
    196  *
    197  * FUNCTION:    AcpiOsReleaseObject
    198  *
    199  * PARAMETERS:  Cache       - Handle to cache object
    200  *              Object      - The object to be released
    201  *
    202  * RETURN:      None
    203  *
    204  * DESCRIPTION: Release an object to the specified cache. If cache is full,
    205  *              the object is deleted.
    206  *
    207  ******************************************************************************/
    208 
    209 ACPI_STATUS
    210 AcpiOsReleaseObject (
    211     ACPI_MEMORY_LIST        *Cache,
    212     void                    *Object)
    213 {
    214     ACPI_STATUS             Status;
    215 
    216 
    217     ACPI_FUNCTION_ENTRY ();
    218 
    219 
    220     if (!Cache || !Object)
    221     {
    222         return (AE_BAD_PARAMETER);
    223     }
    224 
    225     /* If cache is full, just free this object */
    226 
    227     if (Cache->CurrentDepth >= Cache->MaxDepth)
    228     {
    229         ACPI_FREE (Object);
    230         ACPI_MEM_TRACKING (Cache->TotalFreed++);
    231     }
    232 
    233     /* Otherwise put this object back into the cache */
    234 
    235     else
    236     {
    237         Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
    238         if (ACPI_FAILURE (Status))
    239         {
    240             return (Status);
    241         }
    242 
    243         /* Mark the object as cached */
    244 
    245         ACPI_MEMSET (Object, 0xCA, Cache->ObjectSize);
    246         ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_CACHED);
    247 
    248         /* Put the object at the head of the cache list */
    249 
    250         ACPI_SET_DESCRIPTOR_PTR (Object, Cache->ListHead);
    251         Cache->ListHead = Object;
    252         Cache->CurrentDepth++;
    253 
    254         (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
    255     }
    256 
    257     return (AE_OK);
    258 }
    259 
    260 
    261 /*******************************************************************************
    262  *
    263  * FUNCTION:    AcpiOsAcquireObject
    264  *
    265  * PARAMETERS:  Cache           - Handle to cache object
    266  *
    267  * RETURN:      the acquired object. NULL on error
    268  *
    269  * DESCRIPTION: Get an object from the specified cache. If cache is empty,
    270  *              the object is allocated.
    271  *
    272  ******************************************************************************/
    273 
    274 void *
    275 AcpiOsAcquireObject (
    276     ACPI_MEMORY_LIST        *Cache)
    277 {
    278     ACPI_STATUS             Status;
    279     void                    *Object;
    280 
    281 
    282     ACPI_FUNCTION_NAME (OsAcquireObject);
    283 
    284 
    285     if (!Cache)
    286     {
    287         return_PTR (NULL);
    288     }
    289 
    290     Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
    291     if (ACPI_FAILURE (Status))
    292     {
    293         return_PTR (NULL);
    294     }
    295 
    296     ACPI_MEM_TRACKING (Cache->Requests++);
    297 
    298     /* Check the cache first */
    299 
    300     if (Cache->ListHead)
    301     {
    302         /* There is an object available, use it */
    303 
    304         Object = Cache->ListHead;
    305         Cache->ListHead = ACPI_GET_DESCRIPTOR_PTR (Object);
    306 
    307         Cache->CurrentDepth--;
    308 
    309         ACPI_MEM_TRACKING (Cache->Hits++);
    310         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    311             "Object %p from %s cache\n", Object, Cache->ListName));
    312 
    313         Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES);
    314         if (ACPI_FAILURE (Status))
    315         {
    316             return_PTR (NULL);
    317         }
    318 
    319         /* Clear (zero) the previously used Object */
    320 
    321         ACPI_MEMSET (Object, 0, Cache->ObjectSize);
    322     }
    323     else
    324     {
    325         /* The cache is empty, create a new object */
    326 
    327         ACPI_MEM_TRACKING (Cache->TotalAllocated++);
    328 
    329 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
    330         if ((Cache->TotalAllocated - Cache->TotalFreed) > Cache->MaxOccupied)
    331         {
    332             Cache->MaxOccupied = Cache->TotalAllocated - Cache->TotalFreed;
    333         }
    334 #endif
    335 
    336         /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
    337 
    338         Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES);
    339         if (ACPI_FAILURE (Status))
    340         {
    341             return_PTR (NULL);
    342         }
    343 
    344         Object = ACPI_ALLOCATE_ZEROED (Cache->ObjectSize);
    345         if (!Object)
    346         {
    347             return_PTR (NULL);
    348         }
    349     }
    350 
    351     return_PTR (Object);
    352 }
    353 #endif /* ACPI_USE_LOCAL_CACHE */
    354