1151937Sjkim/****************************************************************************** 2151937Sjkim * 3151937Sjkim * Module Name: utcache - local cache allocation routines 4151937Sjkim * 5151937Sjkim *****************************************************************************/ 6151937Sjkim 7217365Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp. 9151937Sjkim * All rights reserved. 10151937Sjkim * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 25151937Sjkim * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 29151937Sjkim * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 43151937Sjkim 44151937Sjkim#define __UTCACHE_C__ 45151937Sjkim 46193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 47193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 48151937Sjkim 49151937Sjkim#define _COMPONENT ACPI_UTILITIES 50151937Sjkim ACPI_MODULE_NAME ("utcache") 51151937Sjkim 52151937Sjkim 53151937Sjkim#ifdef ACPI_USE_LOCAL_CACHE 54151937Sjkim/******************************************************************************* 55151937Sjkim * 56151937Sjkim * FUNCTION: AcpiOsCreateCache 57151937Sjkim * 58151937Sjkim * PARAMETERS: CacheName - Ascii name for the cache 59151937Sjkim * ObjectSize - Size of each cached object 60151937Sjkim * MaxDepth - Maximum depth of the cache (in objects) 61151937Sjkim * ReturnCache - Where the new cache object is returned 62151937Sjkim * 63151937Sjkim * RETURN: Status 64151937Sjkim * 65151937Sjkim * DESCRIPTION: Create a cache object 66151937Sjkim * 67151937Sjkim ******************************************************************************/ 68151937Sjkim 69151937SjkimACPI_STATUS 70151937SjkimAcpiOsCreateCache ( 71151937Sjkim char *CacheName, 72151937Sjkim UINT16 ObjectSize, 73151937Sjkim UINT16 MaxDepth, 74151937Sjkim ACPI_MEMORY_LIST **ReturnCache) 75151937Sjkim{ 76151937Sjkim ACPI_MEMORY_LIST *Cache; 77151937Sjkim 78151937Sjkim 79151937Sjkim ACPI_FUNCTION_ENTRY (); 80151937Sjkim 81151937Sjkim 82151937Sjkim if (!CacheName || !ReturnCache || (ObjectSize < 16)) 83151937Sjkim { 84151937Sjkim return (AE_BAD_PARAMETER); 85151937Sjkim } 86151937Sjkim 87151937Sjkim /* Create the cache object */ 88151937Sjkim 89151937Sjkim Cache = AcpiOsAllocate (sizeof (ACPI_MEMORY_LIST)); 90151937Sjkim if (!Cache) 91151937Sjkim { 92151937Sjkim return (AE_NO_MEMORY); 93151937Sjkim } 94151937Sjkim 95151937Sjkim /* Populate the cache object and return it */ 96151937Sjkim 97151937Sjkim ACPI_MEMSET (Cache, 0, sizeof (ACPI_MEMORY_LIST)); 98151937Sjkim Cache->ListName = CacheName; 99151937Sjkim Cache->ObjectSize = ObjectSize; 100151937Sjkim Cache->MaxDepth = MaxDepth; 101151937Sjkim 102151937Sjkim *ReturnCache = Cache; 103151937Sjkim return (AE_OK); 104151937Sjkim} 105151937Sjkim 106151937Sjkim 107151937Sjkim/******************************************************************************* 108151937Sjkim * 109151937Sjkim * FUNCTION: AcpiOsPurgeCache 110151937Sjkim * 111151937Sjkim * PARAMETERS: Cache - Handle to cache object 112151937Sjkim * 113151937Sjkim * RETURN: Status 114151937Sjkim * 115151937Sjkim * DESCRIPTION: Free all objects within the requested cache. 116151937Sjkim * 117151937Sjkim ******************************************************************************/ 118151937Sjkim 119151937SjkimACPI_STATUS 120151937SjkimAcpiOsPurgeCache ( 121151937Sjkim ACPI_MEMORY_LIST *Cache) 122151937Sjkim{ 123246040Sjkim void *Next; 124193267Sjkim ACPI_STATUS Status; 125151937Sjkim 126151937Sjkim 127151937Sjkim ACPI_FUNCTION_ENTRY (); 128151937Sjkim 129151937Sjkim 130151937Sjkim if (!Cache) 131151937Sjkim { 132151937Sjkim return (AE_BAD_PARAMETER); 133151937Sjkim } 134151937Sjkim 135193267Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); 136193267Sjkim if (ACPI_FAILURE (Status)) 137193267Sjkim { 138193267Sjkim return (Status); 139193267Sjkim } 140193267Sjkim 141151937Sjkim /* Walk the list of objects in this cache */ 142151937Sjkim 143151937Sjkim while (Cache->ListHead) 144151937Sjkim { 145151937Sjkim /* Delete and unlink one cached state object */ 146151937Sjkim 147246040Sjkim Next = ACPI_GET_DESCRIPTOR_PTR (Cache->ListHead); 148167802Sjkim ACPI_FREE (Cache->ListHead); 149151937Sjkim 150151937Sjkim Cache->ListHead = Next; 151151937Sjkim Cache->CurrentDepth--; 152151937Sjkim } 153151937Sjkim 154193267Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); 155151937Sjkim return (AE_OK); 156151937Sjkim} 157151937Sjkim 158151937Sjkim 159151937Sjkim/******************************************************************************* 160151937Sjkim * 161151937Sjkim * FUNCTION: AcpiOsDeleteCache 162151937Sjkim * 163151937Sjkim * PARAMETERS: Cache - Handle to cache object 164151937Sjkim * 165151937Sjkim * RETURN: Status 166151937Sjkim * 167151937Sjkim * DESCRIPTION: Free all objects within the requested cache and delete the 168151937Sjkim * cache object. 169151937Sjkim * 170151937Sjkim ******************************************************************************/ 171151937Sjkim 172151937SjkimACPI_STATUS 173151937SjkimAcpiOsDeleteCache ( 174151937Sjkim ACPI_MEMORY_LIST *Cache) 175151937Sjkim{ 176151937Sjkim ACPI_STATUS Status; 177151937Sjkim 178151937Sjkim 179151937Sjkim ACPI_FUNCTION_ENTRY (); 180151937Sjkim 181151937Sjkim 182151937Sjkim /* Purge all objects in the cache */ 183151937Sjkim 184151937Sjkim Status = AcpiOsPurgeCache (Cache); 185151937Sjkim if (ACPI_FAILURE (Status)) 186151937Sjkim { 187151937Sjkim return (Status); 188151937Sjkim } 189151937Sjkim 190151937Sjkim /* Now we can delete the cache object */ 191151937Sjkim 192151937Sjkim AcpiOsFree (Cache); 193151937Sjkim return (AE_OK); 194151937Sjkim} 195151937Sjkim 196151937Sjkim 197151937Sjkim/******************************************************************************* 198151937Sjkim * 199151937Sjkim * FUNCTION: AcpiOsReleaseObject 200151937Sjkim * 201151937Sjkim * PARAMETERS: Cache - Handle to cache object 202151937Sjkim * Object - The object to be released 203151937Sjkim * 204151937Sjkim * RETURN: None 205151937Sjkim * 206241973Sjkim * DESCRIPTION: Release an object to the specified cache. If cache is full, 207151937Sjkim * the object is deleted. 208151937Sjkim * 209151937Sjkim ******************************************************************************/ 210151937Sjkim 211151937SjkimACPI_STATUS 212151937SjkimAcpiOsReleaseObject ( 213151937Sjkim ACPI_MEMORY_LIST *Cache, 214151937Sjkim void *Object) 215151937Sjkim{ 216151937Sjkim ACPI_STATUS Status; 217151937Sjkim 218151937Sjkim 219151937Sjkim ACPI_FUNCTION_ENTRY (); 220151937Sjkim 221151937Sjkim 222151937Sjkim if (!Cache || !Object) 223151937Sjkim { 224151937Sjkim return (AE_BAD_PARAMETER); 225151937Sjkim } 226151937Sjkim 227151937Sjkim /* If cache is full, just free this object */ 228151937Sjkim 229151937Sjkim if (Cache->CurrentDepth >= Cache->MaxDepth) 230151937Sjkim { 231167802Sjkim ACPI_FREE (Object); 232151937Sjkim ACPI_MEM_TRACKING (Cache->TotalFreed++); 233151937Sjkim } 234151937Sjkim 235151937Sjkim /* Otherwise put this object back into the cache */ 236151937Sjkim 237151937Sjkim else 238151937Sjkim { 239151937Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); 240151937Sjkim if (ACPI_FAILURE (Status)) 241151937Sjkim { 242151937Sjkim return (Status); 243151937Sjkim } 244151937Sjkim 245151937Sjkim /* Mark the object as cached */ 246151937Sjkim 247151937Sjkim ACPI_MEMSET (Object, 0xCA, Cache->ObjectSize); 248151937Sjkim ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_CACHED); 249151937Sjkim 250151937Sjkim /* Put the object at the head of the cache list */ 251151937Sjkim 252246040Sjkim ACPI_SET_DESCRIPTOR_PTR (Object, Cache->ListHead); 253151937Sjkim Cache->ListHead = Object; 254151937Sjkim Cache->CurrentDepth++; 255151937Sjkim 256151937Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); 257151937Sjkim } 258151937Sjkim 259151937Sjkim return (AE_OK); 260151937Sjkim} 261151937Sjkim 262151937Sjkim 263151937Sjkim/******************************************************************************* 264151937Sjkim * 265151937Sjkim * FUNCTION: AcpiOsAcquireObject 266151937Sjkim * 267151937Sjkim * PARAMETERS: Cache - Handle to cache object 268151937Sjkim * 269241973Sjkim * RETURN: the acquired object. NULL on error 270151937Sjkim * 271241973Sjkim * DESCRIPTION: Get an object from the specified cache. If cache is empty, 272151937Sjkim * the object is allocated. 273151937Sjkim * 274151937Sjkim ******************************************************************************/ 275151937Sjkim 276151937Sjkimvoid * 277151937SjkimAcpiOsAcquireObject ( 278151937Sjkim ACPI_MEMORY_LIST *Cache) 279151937Sjkim{ 280151937Sjkim ACPI_STATUS Status; 281151937Sjkim void *Object; 282151937Sjkim 283151937Sjkim 284167802Sjkim ACPI_FUNCTION_NAME (OsAcquireObject); 285151937Sjkim 286151937Sjkim 287151937Sjkim if (!Cache) 288151937Sjkim { 289151937Sjkim return (NULL); 290151937Sjkim } 291151937Sjkim 292151937Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); 293151937Sjkim if (ACPI_FAILURE (Status)) 294151937Sjkim { 295151937Sjkim return (NULL); 296151937Sjkim } 297151937Sjkim 298151937Sjkim ACPI_MEM_TRACKING (Cache->Requests++); 299151937Sjkim 300151937Sjkim /* Check the cache first */ 301151937Sjkim 302151937Sjkim if (Cache->ListHead) 303151937Sjkim { 304151937Sjkim /* There is an object available, use it */ 305151937Sjkim 306151937Sjkim Object = Cache->ListHead; 307246040Sjkim Cache->ListHead = ACPI_GET_DESCRIPTOR_PTR (Object); 308151937Sjkim 309151937Sjkim Cache->CurrentDepth--; 310151937Sjkim 311151937Sjkim ACPI_MEM_TRACKING (Cache->Hits++); 312167802Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 313167802Sjkim "Object %p from %s cache\n", Object, Cache->ListName)); 314151937Sjkim 315151937Sjkim Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); 316151937Sjkim if (ACPI_FAILURE (Status)) 317151937Sjkim { 318151937Sjkim return (NULL); 319151937Sjkim } 320151937Sjkim 321151937Sjkim /* Clear (zero) the previously used Object */ 322151937Sjkim 323151937Sjkim ACPI_MEMSET (Object, 0, Cache->ObjectSize); 324151937Sjkim } 325151937Sjkim else 326151937Sjkim { 327151937Sjkim /* The cache is empty, create a new object */ 328151937Sjkim 329151937Sjkim ACPI_MEM_TRACKING (Cache->TotalAllocated++); 330151937Sjkim 331167802Sjkim#ifdef ACPI_DBG_TRACK_ALLOCATIONS 332167802Sjkim if ((Cache->TotalAllocated - Cache->TotalFreed) > Cache->MaxOccupied) 333167802Sjkim { 334167802Sjkim Cache->MaxOccupied = Cache->TotalAllocated - Cache->TotalFreed; 335167802Sjkim } 336167802Sjkim#endif 337151937Sjkim 338167802Sjkim /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */ 339167802Sjkim 340151937Sjkim Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); 341151937Sjkim if (ACPI_FAILURE (Status)) 342151937Sjkim { 343151937Sjkim return (NULL); 344151937Sjkim } 345151937Sjkim 346167802Sjkim Object = ACPI_ALLOCATE_ZEROED (Cache->ObjectSize); 347151937Sjkim if (!Object) 348151937Sjkim { 349151937Sjkim return (NULL); 350151937Sjkim } 351151937Sjkim } 352151937Sjkim 353151937Sjkim return (Object); 354151937Sjkim} 355151937Sjkim#endif /* ACPI_USE_LOCAL_CACHE */ 356