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