utcache.c revision 1.13
1/****************************************************************************** 2 * 3 * Module Name: utcache - local cache allocation routines 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2019, 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 67ACPI_STATUS 68AcpiOsCreateCache ( 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 116ACPI_STATUS 117AcpiOsPurgeCache ( 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 169ACPI_STATUS 170AcpiOsDeleteCache ( 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 208ACPI_STATUS 209AcpiOsReleaseObject ( 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 273void * 274AcpiOsAcquireObject ( 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_RAW ((ACPI_DB_EXEC, 310 "%s: Object %p from %s cache\n", 311 ACPI_GET_FUNCTION_NAME, 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 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