1ae115bc7Smrj /****************************************************************************** 2ae115bc7Smrj * 3ae115bc7Smrj * Module Name: utcache - local cache allocation routines 4ae115bc7Smrj * 5ae115bc7Smrj *****************************************************************************/ 6ae115bc7Smrj 726f3cdf0SGordon Ross /* 8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp. 9ae115bc7Smrj * All rights reserved. 10ae115bc7Smrj * 1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without 1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions 1326f3cdf0SGordon Ross * are met: 1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright 1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer, 1626f3cdf0SGordon Ross * without modification. 1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below 1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon 2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further 2126f3cdf0SGordon Ross * binary redistribution. 2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names 2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived 2426f3cdf0SGordon Ross * from this software without specific prior written permission. 25ae115bc7Smrj * 2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the 2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free 2826f3cdf0SGordon Ross * Software Foundation. 29ae115bc7Smrj * 3026f3cdf0SGordon Ross * NO WARRANTY 3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES. 4226f3cdf0SGordon Ross */ 43ae115bc7Smrj 44ae115bc7Smrj #include "acpi.h" 45aa2aa9a6SDana Myers #include "accommon.h" 46ae115bc7Smrj 47ae115bc7Smrj #define _COMPONENT ACPI_UTILITIES 48ae115bc7Smrj ACPI_MODULE_NAME ("utcache") 49ae115bc7Smrj 50ae115bc7Smrj 51ae115bc7Smrj #ifdef ACPI_USE_LOCAL_CACHE 52ae115bc7Smrj /******************************************************************************* 53ae115bc7Smrj * 54ae115bc7Smrj * FUNCTION: AcpiOsCreateCache 55ae115bc7Smrj * 56ae115bc7Smrj * PARAMETERS: CacheName - Ascii name for the cache 57ae115bc7Smrj * ObjectSize - Size of each cached object 58ae115bc7Smrj * MaxDepth - Maximum depth of the cache (in objects) 59ae115bc7Smrj * ReturnCache - Where the new cache object is returned 60ae115bc7Smrj * 61ae115bc7Smrj * RETURN: Status 62ae115bc7Smrj * 63ae115bc7Smrj * DESCRIPTION: Create a cache object 64ae115bc7Smrj * 65ae115bc7Smrj ******************************************************************************/ 66ae115bc7Smrj 67ae115bc7Smrj ACPI_STATUS 68ae115bc7Smrj AcpiOsCreateCache ( 69ae115bc7Smrj char *CacheName, 70ae115bc7Smrj UINT16 ObjectSize, 71ae115bc7Smrj UINT16 MaxDepth, 72ae115bc7Smrj ACPI_MEMORY_LIST **ReturnCache) 73ae115bc7Smrj { 74ae115bc7Smrj ACPI_MEMORY_LIST *Cache; 75ae115bc7Smrj 76ae115bc7Smrj 77ae115bc7Smrj ACPI_FUNCTION_ENTRY (); 78ae115bc7Smrj 79ae115bc7Smrj 80ae115bc7Smrj if (!CacheName || !ReturnCache || (ObjectSize < 16)) 81ae115bc7Smrj { 82ae115bc7Smrj return (AE_BAD_PARAMETER); 83ae115bc7Smrj } 84ae115bc7Smrj 85ae115bc7Smrj /* Create the cache object */ 86ae115bc7Smrj 87ae115bc7Smrj Cache = AcpiOsAllocate (sizeof (ACPI_MEMORY_LIST)); 88ae115bc7Smrj if (!Cache) 89ae115bc7Smrj { 90ae115bc7Smrj return (AE_NO_MEMORY); 91ae115bc7Smrj } 92ae115bc7Smrj 93ae115bc7Smrj /* Populate the cache object and return it */ 94ae115bc7Smrj 95*385cc6b4SJerry Jelinek memset (Cache, 0, sizeof (ACPI_MEMORY_LIST)); 96ae115bc7Smrj Cache->ListName = CacheName; 97ae115bc7Smrj Cache->ObjectSize = ObjectSize; 98ae115bc7Smrj Cache->MaxDepth = MaxDepth; 99ae115bc7Smrj 100ae115bc7Smrj *ReturnCache = Cache; 101ae115bc7Smrj return (AE_OK); 102ae115bc7Smrj } 103ae115bc7Smrj 104ae115bc7Smrj 105ae115bc7Smrj /******************************************************************************* 106ae115bc7Smrj * 107ae115bc7Smrj * FUNCTION: AcpiOsPurgeCache 108ae115bc7Smrj * 109ae115bc7Smrj * PARAMETERS: Cache - Handle to cache object 110ae115bc7Smrj * 111ae115bc7Smrj * RETURN: Status 112ae115bc7Smrj * 113ae115bc7Smrj * DESCRIPTION: Free all objects within the requested cache. 114ae115bc7Smrj * 115ae115bc7Smrj ******************************************************************************/ 116ae115bc7Smrj 117ae115bc7Smrj ACPI_STATUS 118ae115bc7Smrj AcpiOsPurgeCache ( 119ae115bc7Smrj ACPI_MEMORY_LIST *Cache) 120ae115bc7Smrj { 121*385cc6b4SJerry Jelinek void *Next; 122aa2aa9a6SDana Myers ACPI_STATUS Status; 123ae115bc7Smrj 124ae115bc7Smrj 125ae115bc7Smrj ACPI_FUNCTION_ENTRY (); 126ae115bc7Smrj 127ae115bc7Smrj 128ae115bc7Smrj if (!Cache) 129ae115bc7Smrj { 130ae115bc7Smrj return (AE_BAD_PARAMETER); 131ae115bc7Smrj } 132ae115bc7Smrj 133aa2aa9a6SDana Myers Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); 134aa2aa9a6SDana Myers if (ACPI_FAILURE (Status)) 135aa2aa9a6SDana Myers { 136aa2aa9a6SDana Myers return (Status); 137aa2aa9a6SDana Myers } 138aa2aa9a6SDana Myers 139ae115bc7Smrj /* Walk the list of objects in this cache */ 140ae115bc7Smrj 141ae115bc7Smrj while (Cache->ListHead) 142ae115bc7Smrj { 143ae115bc7Smrj /* Delete and unlink one cached state object */ 144ae115bc7Smrj 145*385cc6b4SJerry Jelinek Next = ACPI_GET_DESCRIPTOR_PTR (Cache->ListHead); 146ae115bc7Smrj ACPI_FREE (Cache->ListHead); 147ae115bc7Smrj 148ae115bc7Smrj Cache->ListHead = Next; 149ae115bc7Smrj Cache->CurrentDepth--; 150ae115bc7Smrj } 151ae115bc7Smrj 152aa2aa9a6SDana Myers (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); 153ae115bc7Smrj return (AE_OK); 154ae115bc7Smrj } 155ae115bc7Smrj 156ae115bc7Smrj 157ae115bc7Smrj /******************************************************************************* 158ae115bc7Smrj * 159ae115bc7Smrj * FUNCTION: AcpiOsDeleteCache 160ae115bc7Smrj * 161ae115bc7Smrj * PARAMETERS: Cache - Handle to cache object 162ae115bc7Smrj * 163ae115bc7Smrj * RETURN: Status 164ae115bc7Smrj * 165ae115bc7Smrj * DESCRIPTION: Free all objects within the requested cache and delete the 166ae115bc7Smrj * cache object. 167ae115bc7Smrj * 168ae115bc7Smrj ******************************************************************************/ 169ae115bc7Smrj 170ae115bc7Smrj ACPI_STATUS 171ae115bc7Smrj AcpiOsDeleteCache ( 172ae115bc7Smrj ACPI_MEMORY_LIST *Cache) 173ae115bc7Smrj { 174ae115bc7Smrj ACPI_STATUS Status; 175ae115bc7Smrj 176ae115bc7Smrj 177ae115bc7Smrj ACPI_FUNCTION_ENTRY (); 178ae115bc7Smrj 179ae115bc7Smrj 180ae115bc7Smrj /* Purge all objects in the cache */ 181ae115bc7Smrj 182ae115bc7Smrj Status = AcpiOsPurgeCache (Cache); 183ae115bc7Smrj if (ACPI_FAILURE (Status)) 184ae115bc7Smrj { 185ae115bc7Smrj return (Status); 186ae115bc7Smrj } 187ae115bc7Smrj 188ae115bc7Smrj /* Now we can delete the cache object */ 189ae115bc7Smrj 190ae115bc7Smrj AcpiOsFree (Cache); 191ae115bc7Smrj return (AE_OK); 192ae115bc7Smrj } 193ae115bc7Smrj 194ae115bc7Smrj 195ae115bc7Smrj /******************************************************************************* 196ae115bc7Smrj * 197ae115bc7Smrj * FUNCTION: AcpiOsReleaseObject 198ae115bc7Smrj * 199ae115bc7Smrj * PARAMETERS: Cache - Handle to cache object 200ae115bc7Smrj * Object - The object to be released 201ae115bc7Smrj * 202ae115bc7Smrj * RETURN: None 203ae115bc7Smrj * 204ae115bc7Smrj * DESCRIPTION: Release an object to the specified cache. If cache is full, 205ae115bc7Smrj * the object is deleted. 206ae115bc7Smrj * 207ae115bc7Smrj ******************************************************************************/ 208ae115bc7Smrj 209ae115bc7Smrj ACPI_STATUS 210ae115bc7Smrj AcpiOsReleaseObject ( 211ae115bc7Smrj ACPI_MEMORY_LIST *Cache, 212ae115bc7Smrj void *Object) 213ae115bc7Smrj { 214ae115bc7Smrj ACPI_STATUS Status; 215ae115bc7Smrj 216ae115bc7Smrj 217ae115bc7Smrj ACPI_FUNCTION_ENTRY (); 218ae115bc7Smrj 219ae115bc7Smrj 220ae115bc7Smrj if (!Cache || !Object) 221ae115bc7Smrj { 222ae115bc7Smrj return (AE_BAD_PARAMETER); 223ae115bc7Smrj } 224ae115bc7Smrj 225ae115bc7Smrj /* If cache is full, just free this object */ 226ae115bc7Smrj 227ae115bc7Smrj if (Cache->CurrentDepth >= Cache->MaxDepth) 228ae115bc7Smrj { 229ae115bc7Smrj ACPI_FREE (Object); 230ae115bc7Smrj ACPI_MEM_TRACKING (Cache->TotalFreed++); 231ae115bc7Smrj } 232ae115bc7Smrj 233ae115bc7Smrj /* Otherwise put this object back into the cache */ 234ae115bc7Smrj 235ae115bc7Smrj else 236ae115bc7Smrj { 237ae115bc7Smrj Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); 238ae115bc7Smrj if (ACPI_FAILURE (Status)) 239ae115bc7Smrj { 240ae115bc7Smrj return (Status); 241ae115bc7Smrj } 242ae115bc7Smrj 243ae115bc7Smrj /* Mark the object as cached */ 244ae115bc7Smrj 245*385cc6b4SJerry Jelinek memset (Object, 0xCA, Cache->ObjectSize); 246ae115bc7Smrj ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_CACHED); 247ae115bc7Smrj 248ae115bc7Smrj /* Put the object at the head of the cache list */ 249ae115bc7Smrj 250*385cc6b4SJerry Jelinek ACPI_SET_DESCRIPTOR_PTR (Object, Cache->ListHead); 251ae115bc7Smrj Cache->ListHead = Object; 252ae115bc7Smrj Cache->CurrentDepth++; 253ae115bc7Smrj 254ae115bc7Smrj (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); 255ae115bc7Smrj } 256ae115bc7Smrj 257ae115bc7Smrj return (AE_OK); 258ae115bc7Smrj } 259ae115bc7Smrj 260ae115bc7Smrj 261ae115bc7Smrj /******************************************************************************* 262ae115bc7Smrj * 263ae115bc7Smrj * FUNCTION: AcpiOsAcquireObject 264ae115bc7Smrj * 265ae115bc7Smrj * PARAMETERS: Cache - Handle to cache object 266ae115bc7Smrj * 267ae115bc7Smrj * RETURN: the acquired object. NULL on error 268ae115bc7Smrj * 269ae115bc7Smrj * DESCRIPTION: Get an object from the specified cache. If cache is empty, 270ae115bc7Smrj * the object is allocated. 271ae115bc7Smrj * 272ae115bc7Smrj ******************************************************************************/ 273ae115bc7Smrj 274ae115bc7Smrj void * 275ae115bc7Smrj AcpiOsAcquireObject ( 276ae115bc7Smrj ACPI_MEMORY_LIST *Cache) 277ae115bc7Smrj { 278ae115bc7Smrj ACPI_STATUS Status; 279ae115bc7Smrj void *Object; 280ae115bc7Smrj 281ae115bc7Smrj 282*385cc6b4SJerry Jelinek ACPI_FUNCTION_TRACE (OsAcquireObject); 283ae115bc7Smrj 284ae115bc7Smrj 285ae115bc7Smrj if (!Cache) 286ae115bc7Smrj { 287*385cc6b4SJerry Jelinek return_PTR (NULL); 288ae115bc7Smrj } 289ae115bc7Smrj 290ae115bc7Smrj Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); 291ae115bc7Smrj if (ACPI_FAILURE (Status)) 292ae115bc7Smrj { 293*385cc6b4SJerry Jelinek return_PTR (NULL); 294ae115bc7Smrj } 295ae115bc7Smrj 296ae115bc7Smrj ACPI_MEM_TRACKING (Cache->Requests++); 297ae115bc7Smrj 298ae115bc7Smrj /* Check the cache first */ 299ae115bc7Smrj 300ae115bc7Smrj if (Cache->ListHead) 301ae115bc7Smrj { 302ae115bc7Smrj /* There is an object available, use it */ 303ae115bc7Smrj 304ae115bc7Smrj Object = Cache->ListHead; 305*385cc6b4SJerry Jelinek Cache->ListHead = ACPI_GET_DESCRIPTOR_PTR (Object); 306ae115bc7Smrj 307ae115bc7Smrj Cache->CurrentDepth--; 308ae115bc7Smrj 309ae115bc7Smrj ACPI_MEM_TRACKING (Cache->Hits++); 310ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 311ae115bc7Smrj "Object %p from %s cache\n", Object, Cache->ListName)); 312ae115bc7Smrj 313ae115bc7Smrj Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); 314ae115bc7Smrj if (ACPI_FAILURE (Status)) 315ae115bc7Smrj { 316*385cc6b4SJerry Jelinek return_PTR (NULL); 317ae115bc7Smrj } 318ae115bc7Smrj 319ae115bc7Smrj /* Clear (zero) the previously used Object */ 320ae115bc7Smrj 321*385cc6b4SJerry Jelinek memset (Object, 0, Cache->ObjectSize); 322ae115bc7Smrj } 323ae115bc7Smrj else 324ae115bc7Smrj { 325ae115bc7Smrj /* The cache is empty, create a new object */ 326ae115bc7Smrj 327ae115bc7Smrj ACPI_MEM_TRACKING (Cache->TotalAllocated++); 328ae115bc7Smrj 329db2bae30SDana Myers #ifdef ACPI_DBG_TRACK_ALLOCATIONS 330db2bae30SDana Myers if ((Cache->TotalAllocated - Cache->TotalFreed) > Cache->MaxOccupied) 331db2bae30SDana Myers { 332db2bae30SDana Myers Cache->MaxOccupied = Cache->TotalAllocated - Cache->TotalFreed; 333db2bae30SDana Myers } 334db2bae30SDana Myers #endif 335db2bae30SDana Myers 336ae115bc7Smrj /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */ 337ae115bc7Smrj 338ae115bc7Smrj Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); 339ae115bc7Smrj if (ACPI_FAILURE (Status)) 340ae115bc7Smrj { 341*385cc6b4SJerry Jelinek return_PTR (NULL); 342ae115bc7Smrj } 343ae115bc7Smrj 344ae115bc7Smrj Object = ACPI_ALLOCATE_ZEROED (Cache->ObjectSize); 345ae115bc7Smrj if (!Object) 346ae115bc7Smrj { 347*385cc6b4SJerry Jelinek return_PTR (NULL); 348ae115bc7Smrj } 349ae115bc7Smrj } 350ae115bc7Smrj 351*385cc6b4SJerry Jelinek return_PTR (Object); 352ae115bc7Smrj } 353ae115bc7Smrj #endif /* ACPI_USE_LOCAL_CACHE */ 354