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