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