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