at v2.6.21 8.5 kB view raw
1/****************************************************************************** 2 * 3 * Module Name: utcache - local cache allocation routines 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2007, R. Byron Moore 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/acpi.h> 45 46#define _COMPONENT ACPI_UTILITIES 47ACPI_MODULE_NAME("utcache") 48 49#ifdef ACPI_USE_LOCAL_CACHE 50/******************************************************************************* 51 * 52 * FUNCTION: acpi_os_create_cache 53 * 54 * PARAMETERS: cache_name - Ascii name for the cache 55 * object_size - Size of each cached object 56 * max_depth - Maximum depth of the cache (in objects) 57 * return_cache - Where the new cache object is returned 58 * 59 * RETURN: Status 60 * 61 * DESCRIPTION: Create a cache object 62 * 63 ******************************************************************************/ 64acpi_status 65acpi_os_create_cache(char *cache_name, 66 u16 object_size, 67 u16 max_depth, struct acpi_memory_list **return_cache) 68{ 69 struct acpi_memory_list *cache; 70 71 ACPI_FUNCTION_ENTRY(); 72 73 if (!cache_name || !return_cache || (object_size < 16)) { 74 return (AE_BAD_PARAMETER); 75 } 76 77 /* Create the cache object */ 78 79 cache = acpi_os_allocate(sizeof(struct acpi_memory_list)); 80 if (!cache) { 81 return (AE_NO_MEMORY); 82 } 83 84 /* Populate the cache object and return it */ 85 86 ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list)); 87 cache->link_offset = 8; 88 cache->list_name = cache_name; 89 cache->object_size = object_size; 90 cache->max_depth = max_depth; 91 92 *return_cache = cache; 93 return (AE_OK); 94} 95 96/******************************************************************************* 97 * 98 * FUNCTION: acpi_os_purge_cache 99 * 100 * PARAMETERS: Cache - Handle to cache object 101 * 102 * RETURN: Status 103 * 104 * DESCRIPTION: Free all objects within the requested cache. 105 * 106 ******************************************************************************/ 107 108acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache) 109{ 110 char *next; 111 112 ACPI_FUNCTION_ENTRY(); 113 114 if (!cache) { 115 return (AE_BAD_PARAMETER); 116 } 117 118 /* Walk the list of objects in this cache */ 119 120 while (cache->list_head) { 121 122 /* Delete and unlink one cached state object */ 123 124 next = *(ACPI_CAST_INDIRECT_PTR(char, 125 &(((char *)cache-> 126 list_head)[cache-> 127 link_offset]))); 128 ACPI_FREE(cache->list_head); 129 130 cache->list_head = next; 131 cache->current_depth--; 132 } 133 134 return (AE_OK); 135} 136 137/******************************************************************************* 138 * 139 * FUNCTION: acpi_os_delete_cache 140 * 141 * PARAMETERS: Cache - Handle to cache object 142 * 143 * RETURN: Status 144 * 145 * DESCRIPTION: Free all objects within the requested cache and delete the 146 * cache object. 147 * 148 ******************************************************************************/ 149 150acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache) 151{ 152 acpi_status status; 153 154 ACPI_FUNCTION_ENTRY(); 155 156 /* Purge all objects in the cache */ 157 158 status = acpi_os_purge_cache(cache); 159 if (ACPI_FAILURE(status)) { 160 return (status); 161 } 162 163 /* Now we can delete the cache object */ 164 165 ACPI_FREE(cache); 166 return (AE_OK); 167} 168 169/******************************************************************************* 170 * 171 * FUNCTION: acpi_os_release_object 172 * 173 * PARAMETERS: Cache - Handle to cache object 174 * Object - The object to be released 175 * 176 * RETURN: None 177 * 178 * DESCRIPTION: Release an object to the specified cache. If cache is full, 179 * the object is deleted. 180 * 181 ******************************************************************************/ 182 183acpi_status 184acpi_os_release_object(struct acpi_memory_list * cache, void *object) 185{ 186 acpi_status status; 187 188 ACPI_FUNCTION_ENTRY(); 189 190 if (!cache || !object) { 191 return (AE_BAD_PARAMETER); 192 } 193 194 /* If cache is full, just free this object */ 195 196 if (cache->current_depth >= cache->max_depth) { 197 ACPI_FREE(object); 198 ACPI_MEM_TRACKING(cache->total_freed++); 199 } 200 201 /* Otherwise put this object back into the cache */ 202 203 else { 204 status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); 205 if (ACPI_FAILURE(status)) { 206 return (status); 207 } 208 209 /* Mark the object as cached */ 210 211 ACPI_MEMSET(object, 0xCA, cache->object_size); 212 ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED); 213 214 /* Put the object at the head of the cache list */ 215 216 *(ACPI_CAST_INDIRECT_PTR(char, 217 &(((char *)object)[cache-> 218 link_offset]))) = 219 cache->list_head; 220 cache->list_head = object; 221 cache->current_depth++; 222 223 (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); 224 } 225 226 return (AE_OK); 227} 228 229/******************************************************************************* 230 * 231 * FUNCTION: acpi_os_acquire_object 232 * 233 * PARAMETERS: Cache - Handle to cache object 234 * 235 * RETURN: the acquired object. NULL on error 236 * 237 * DESCRIPTION: Get an object from the specified cache. If cache is empty, 238 * the object is allocated. 239 * 240 ******************************************************************************/ 241 242void *acpi_os_acquire_object(struct acpi_memory_list *cache) 243{ 244 acpi_status status; 245 void *object; 246 247 ACPI_FUNCTION_NAME(os_acquire_object); 248 249 if (!cache) { 250 return (NULL); 251 } 252 253 status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); 254 if (ACPI_FAILURE(status)) { 255 return (NULL); 256 } 257 258 ACPI_MEM_TRACKING(cache->requests++); 259 260 /* Check the cache first */ 261 262 if (cache->list_head) { 263 264 /* There is an object available, use it */ 265 266 object = cache->list_head; 267 cache->list_head = *(ACPI_CAST_INDIRECT_PTR(char, 268 &(((char *) 269 object)[cache-> 270 link_offset]))); 271 272 cache->current_depth--; 273 274 ACPI_MEM_TRACKING(cache->hits++); 275 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 276 "Object %p from %s cache\n", object, 277 cache->list_name)); 278 279 status = acpi_ut_release_mutex(ACPI_MTX_CACHES); 280 if (ACPI_FAILURE(status)) { 281 return (NULL); 282 } 283 284 /* Clear (zero) the previously used Object */ 285 286 ACPI_MEMSET(object, 0, cache->object_size); 287 } else { 288 /* The cache is empty, create a new object */ 289 290 ACPI_MEM_TRACKING(cache->total_allocated++); 291 292#ifdef ACPI_DBG_TRACK_ALLOCATIONS 293 if ((cache->total_allocated - cache->total_freed) > 294 cache->max_occupied) { 295 cache->max_occupied = 296 cache->total_allocated - cache->total_freed; 297 } 298#endif 299 300 /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */ 301 302 status = acpi_ut_release_mutex(ACPI_MTX_CACHES); 303 if (ACPI_FAILURE(status)) { 304 return (NULL); 305 } 306 307 object = ACPI_ALLOCATE_ZEROED(cache->object_size); 308 if (!object) { 309 return (NULL); 310 } 311 } 312 313 return (object); 314} 315#endif /* ACPI_USE_LOCAL_CACHE */