1151937Sjkim/****************************************************************************** 2151937Sjkim * 3151937Sjkim * Module Name: utcache - local cache allocation routines 4151937Sjkim * 5151937Sjkim *****************************************************************************/ 6151937Sjkim 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, 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 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 46151937Sjkim 47151937Sjkim#define _COMPONENT ACPI_UTILITIES 48151937Sjkim ACPI_MODULE_NAME ("utcache") 49151937Sjkim 50151937Sjkim 51151937Sjkim#ifdef ACPI_USE_LOCAL_CACHE 52151937Sjkim/******************************************************************************* 53151937Sjkim * 54151937Sjkim * FUNCTION: AcpiOsCreateCache 55151937Sjkim * 56151937Sjkim * PARAMETERS: CacheName - Ascii name for the cache 57151937Sjkim * ObjectSize - Size of each cached object 58151937Sjkim * MaxDepth - Maximum depth of the cache (in objects) 59151937Sjkim * ReturnCache - Where the new cache object is returned 60151937Sjkim * 61151937Sjkim * RETURN: Status 62151937Sjkim * 63151937Sjkim * DESCRIPTION: Create a cache object 64151937Sjkim * 65151937Sjkim ******************************************************************************/ 66151937Sjkim 67151937SjkimACPI_STATUS 68151937SjkimAcpiOsCreateCache ( 69151937Sjkim char *CacheName, 70151937Sjkim UINT16 ObjectSize, 71151937Sjkim UINT16 MaxDepth, 72151937Sjkim ACPI_MEMORY_LIST **ReturnCache) 73151937Sjkim{ 74151937Sjkim ACPI_MEMORY_LIST *Cache; 75151937Sjkim 76151937Sjkim 77151937Sjkim ACPI_FUNCTION_ENTRY (); 78151937Sjkim 79151937Sjkim 80151937Sjkim if (!CacheName || !ReturnCache || (ObjectSize < 16)) 81151937Sjkim { 82151937Sjkim return (AE_BAD_PARAMETER); 83151937Sjkim } 84151937Sjkim 85151937Sjkim /* Create the cache object */ 86151937Sjkim 87151937Sjkim Cache = AcpiOsAllocate (sizeof (ACPI_MEMORY_LIST)); 88151937Sjkim if (!Cache) 89151937Sjkim { 90151937Sjkim return (AE_NO_MEMORY); 91151937Sjkim } 92151937Sjkim 93151937Sjkim /* Populate the cache object and return it */ 94151937Sjkim 95306536Sjkim memset (Cache, 0, sizeof (ACPI_MEMORY_LIST)); 96306536Sjkim Cache->ListName = CacheName; 97151937Sjkim Cache->ObjectSize = ObjectSize; 98306536Sjkim Cache->MaxDepth = MaxDepth; 99151937Sjkim 100151937Sjkim *ReturnCache = Cache; 101151937Sjkim return (AE_OK); 102151937Sjkim} 103151937Sjkim 104151937Sjkim 105151937Sjkim/******************************************************************************* 106151937Sjkim * 107151937Sjkim * FUNCTION: AcpiOsPurgeCache 108151937Sjkim * 109151937Sjkim * PARAMETERS: Cache - Handle to cache object 110151937Sjkim * 111151937Sjkim * RETURN: Status 112151937Sjkim * 113151937Sjkim * DESCRIPTION: Free all objects within the requested cache. 114151937Sjkim * 115151937Sjkim ******************************************************************************/ 116151937Sjkim 117151937SjkimACPI_STATUS 118151937SjkimAcpiOsPurgeCache ( 119151937Sjkim ACPI_MEMORY_LIST *Cache) 120151937Sjkim{ 121246040Sjkim void *Next; 122193267Sjkim ACPI_STATUS Status; 123151937Sjkim 124151937Sjkim 125151937Sjkim ACPI_FUNCTION_ENTRY (); 126151937Sjkim 127151937Sjkim 128151937Sjkim if (!Cache) 129151937Sjkim { 130151937Sjkim return (AE_BAD_PARAMETER); 131151937Sjkim } 132151937Sjkim 133193267Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); 134193267Sjkim if (ACPI_FAILURE (Status)) 135193267Sjkim { 136193267Sjkim return (Status); 137193267Sjkim } 138193267Sjkim 139151937Sjkim /* Walk the list of objects in this cache */ 140151937Sjkim 141151937Sjkim while (Cache->ListHead) 142151937Sjkim { 143151937Sjkim /* Delete and unlink one cached state object */ 144151937Sjkim 145246040Sjkim Next = ACPI_GET_DESCRIPTOR_PTR (Cache->ListHead); 146167802Sjkim ACPI_FREE (Cache->ListHead); 147151937Sjkim 148151937Sjkim Cache->ListHead = Next; 149151937Sjkim Cache->CurrentDepth--; 150151937Sjkim } 151151937Sjkim 152193267Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); 153151937Sjkim return (AE_OK); 154151937Sjkim} 155151937Sjkim 156151937Sjkim 157151937Sjkim/******************************************************************************* 158151937Sjkim * 159151937Sjkim * FUNCTION: AcpiOsDeleteCache 160151937Sjkim * 161151937Sjkim * PARAMETERS: Cache - Handle to cache object 162151937Sjkim * 163151937Sjkim * RETURN: Status 164151937Sjkim * 165151937Sjkim * DESCRIPTION: Free all objects within the requested cache and delete the 166151937Sjkim * cache object. 167151937Sjkim * 168151937Sjkim ******************************************************************************/ 169151937Sjkim 170151937SjkimACPI_STATUS 171151937SjkimAcpiOsDeleteCache ( 172151937Sjkim ACPI_MEMORY_LIST *Cache) 173151937Sjkim{ 174151937Sjkim ACPI_STATUS Status; 175151937Sjkim 176151937Sjkim 177151937Sjkim ACPI_FUNCTION_ENTRY (); 178151937Sjkim 179151937Sjkim 180151937Sjkim /* Purge all objects in the cache */ 181151937Sjkim 182151937Sjkim Status = AcpiOsPurgeCache (Cache); 183151937Sjkim if (ACPI_FAILURE (Status)) 184151937Sjkim { 185151937Sjkim return (Status); 186151937Sjkim } 187151937Sjkim 188151937Sjkim /* Now we can delete the cache object */ 189151937Sjkim 190151937Sjkim AcpiOsFree (Cache); 191151937Sjkim return (AE_OK); 192151937Sjkim} 193151937Sjkim 194151937Sjkim 195151937Sjkim/******************************************************************************* 196151937Sjkim * 197151937Sjkim * FUNCTION: AcpiOsReleaseObject 198151937Sjkim * 199151937Sjkim * PARAMETERS: Cache - Handle to cache object 200151937Sjkim * Object - The object to be released 201151937Sjkim * 202151937Sjkim * RETURN: None 203151937Sjkim * 204241973Sjkim * DESCRIPTION: Release an object to the specified cache. If cache is full, 205151937Sjkim * the object is deleted. 206151937Sjkim * 207151937Sjkim ******************************************************************************/ 208151937Sjkim 209151937SjkimACPI_STATUS 210151937SjkimAcpiOsReleaseObject ( 211151937Sjkim ACPI_MEMORY_LIST *Cache, 212151937Sjkim void *Object) 213151937Sjkim{ 214151937Sjkim ACPI_STATUS Status; 215151937Sjkim 216151937Sjkim 217151937Sjkim ACPI_FUNCTION_ENTRY (); 218151937Sjkim 219151937Sjkim 220151937Sjkim if (!Cache || !Object) 221151937Sjkim { 222151937Sjkim return (AE_BAD_PARAMETER); 223151937Sjkim } 224151937Sjkim 225151937Sjkim /* If cache is full, just free this object */ 226151937Sjkim 227151937Sjkim if (Cache->CurrentDepth >= Cache->MaxDepth) 228151937Sjkim { 229167802Sjkim ACPI_FREE (Object); 230151937Sjkim ACPI_MEM_TRACKING (Cache->TotalFreed++); 231151937Sjkim } 232151937Sjkim 233151937Sjkim /* Otherwise put this object back into the cache */ 234151937Sjkim 235151937Sjkim else 236151937Sjkim { 237151937Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); 238151937Sjkim if (ACPI_FAILURE (Status)) 239151937Sjkim { 240151937Sjkim return (Status); 241151937Sjkim } 242151937Sjkim 243151937Sjkim /* Mark the object as cached */ 244151937Sjkim 245306536Sjkim memset (Object, 0xCA, Cache->ObjectSize); 246151937Sjkim ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_CACHED); 247151937Sjkim 248151937Sjkim /* Put the object at the head of the cache list */ 249151937Sjkim 250246040Sjkim ACPI_SET_DESCRIPTOR_PTR (Object, Cache->ListHead); 251151937Sjkim Cache->ListHead = Object; 252151937Sjkim Cache->CurrentDepth++; 253151937Sjkim 254151937Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); 255151937Sjkim } 256151937Sjkim 257151937Sjkim return (AE_OK); 258151937Sjkim} 259151937Sjkim 260151937Sjkim 261151937Sjkim/******************************************************************************* 262151937Sjkim * 263151937Sjkim * FUNCTION: AcpiOsAcquireObject 264151937Sjkim * 265151937Sjkim * PARAMETERS: Cache - Handle to cache object 266151937Sjkim * 267241973Sjkim * RETURN: the acquired object. NULL on error 268151937Sjkim * 269241973Sjkim * DESCRIPTION: Get an object from the specified cache. If cache is empty, 270151937Sjkim * the object is allocated. 271151937Sjkim * 272151937Sjkim ******************************************************************************/ 273151937Sjkim 274151937Sjkimvoid * 275151937SjkimAcpiOsAcquireObject ( 276151937Sjkim ACPI_MEMORY_LIST *Cache) 277151937Sjkim{ 278151937Sjkim ACPI_STATUS Status; 279151937Sjkim void *Object; 280151937Sjkim 281151937Sjkim 282306536Sjkim ACPI_FUNCTION_TRACE (OsAcquireObject); 283151937Sjkim 284151937Sjkim 285151937Sjkim if (!Cache) 286151937Sjkim { 287281075Sdim return_PTR (NULL); 288151937Sjkim } 289151937Sjkim 290151937Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); 291151937Sjkim if (ACPI_FAILURE (Status)) 292151937Sjkim { 293281075Sdim return_PTR (NULL); 294151937Sjkim } 295151937Sjkim 296151937Sjkim ACPI_MEM_TRACKING (Cache->Requests++); 297151937Sjkim 298151937Sjkim /* Check the cache first */ 299151937Sjkim 300151937Sjkim if (Cache->ListHead) 301151937Sjkim { 302151937Sjkim /* There is an object available, use it */ 303151937Sjkim 304151937Sjkim Object = Cache->ListHead; 305246040Sjkim Cache->ListHead = ACPI_GET_DESCRIPTOR_PTR (Object); 306151937Sjkim 307151937Sjkim Cache->CurrentDepth--; 308151937Sjkim 309151937Sjkim ACPI_MEM_TRACKING (Cache->Hits++); 310167802Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 311167802Sjkim "Object %p from %s cache\n", Object, Cache->ListName)); 312151937Sjkim 313151937Sjkim Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); 314151937Sjkim if (ACPI_FAILURE (Status)) 315151937Sjkim { 316281075Sdim return_PTR (NULL); 317151937Sjkim } 318151937Sjkim 319151937Sjkim /* Clear (zero) the previously used Object */ 320151937Sjkim 321306536Sjkim memset (Object, 0, Cache->ObjectSize); 322151937Sjkim } 323151937Sjkim else 324151937Sjkim { 325151937Sjkim /* The cache is empty, create a new object */ 326151937Sjkim 327151937Sjkim ACPI_MEM_TRACKING (Cache->TotalAllocated++); 328151937Sjkim 329167802Sjkim#ifdef ACPI_DBG_TRACK_ALLOCATIONS 330167802Sjkim if ((Cache->TotalAllocated - Cache->TotalFreed) > Cache->MaxOccupied) 331167802Sjkim { 332167802Sjkim Cache->MaxOccupied = Cache->TotalAllocated - Cache->TotalFreed; 333167802Sjkim } 334167802Sjkim#endif 335151937Sjkim 336167802Sjkim /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */ 337167802Sjkim 338151937Sjkim Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); 339151937Sjkim if (ACPI_FAILURE (Status)) 340151937Sjkim { 341281075Sdim return_PTR (NULL); 342151937Sjkim } 343151937Sjkim 344167802Sjkim Object = ACPI_ALLOCATE_ZEROED (Cache->ObjectSize); 345151937Sjkim if (!Object) 346151937Sjkim { 347281075Sdim return_PTR (NULL); 348151937Sjkim } 349151937Sjkim } 350151937Sjkim 351281075Sdim return_PTR (Object); 352151937Sjkim} 353151937Sjkim#endif /* ACPI_USE_LOCAL_CACHE */ 354