2012-10-31 02:25:05 +00:00
/******************************************************************************
*
* Module Name : utcache - local cache allocation routines
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
2016-01-15 08:17:03 +08:00
* Copyright ( C ) 2000 - 2016 , Intel Corp .
2012-10-31 02:25:05 +00:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions , and the following disclaimer ,
* without modification .
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the " NO WARRANTY " disclaimer below
* ( " Disclaimer " ) and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution .
* 3. Neither the names of the above - listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission .
*
* Alternatively , this software may be distributed under the terms of the
* GNU General Public License ( " GPL " ) version 2 as published by the Free
* Software Foundation .
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT ,
* STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES .
*/
# include <acpi/acpi.h>
# include "accommon.h"
# define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME ( " utcache " )
# ifdef ACPI_USE_LOCAL_CACHE
/*******************************************************************************
*
* FUNCTION : acpi_os_create_cache
*
* PARAMETERS : cache_name - Ascii name for the cache
* object_size - Size of each cached object
* max_depth - Maximum depth of the cache ( in objects )
* return_cache - Where the new cache object is returned
*
* RETURN : Status
*
* DESCRIPTION : Create a cache object
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
acpi_status
acpi_os_create_cache ( char * cache_name ,
u16 object_size ,
2013-10-29 09:30:22 +08:00
u16 max_depth , struct acpi_memory_list * * return_cache )
2012-10-31 02:25:05 +00:00
{
struct acpi_memory_list * cache ;
ACPI_FUNCTION_ENTRY ( ) ;
if ( ! cache_name | | ! return_cache | | ( object_size < 16 ) ) {
return ( AE_BAD_PARAMETER ) ;
}
/* Create the cache object */
cache = acpi_os_allocate ( sizeof ( struct acpi_memory_list ) ) ;
if ( ! cache ) {
return ( AE_NO_MEMORY ) ;
}
/* Populate the cache object and return it */
2015-07-01 14:45:11 +08:00
memset ( cache , 0 , sizeof ( struct acpi_memory_list ) ) ;
2012-10-31 02:25:05 +00:00
cache - > list_name = cache_name ;
cache - > object_size = object_size ;
cache - > max_depth = max_depth ;
* return_cache = cache ;
return ( AE_OK ) ;
}
/*******************************************************************************
*
* FUNCTION : acpi_os_purge_cache
*
* PARAMETERS : cache - Handle to cache object
*
* RETURN : Status
*
* DESCRIPTION : Free all objects within the requested cache .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-05-05 12:57:53 +08:00
acpi_status acpi_os_purge_cache ( struct acpi_memory_list * cache )
2012-10-31 02:25:05 +00:00
{
2013-03-08 09:21:02 +00:00
void * next ;
2012-10-31 02:25:05 +00:00
acpi_status status ;
ACPI_FUNCTION_ENTRY ( ) ;
if ( ! cache ) {
return ( AE_BAD_PARAMETER ) ;
}
status = acpi_ut_acquire_mutex ( ACPI_MTX_CACHES ) ;
if ( ACPI_FAILURE ( status ) ) {
return ( status ) ;
}
/* Walk the list of objects in this cache */
while ( cache - > list_head ) {
/* Delete and unlink one cached state object */
2013-03-08 09:21:54 +00:00
next = ACPI_GET_DESCRIPTOR_PTR ( cache - > list_head ) ;
2012-10-31 02:25:05 +00:00
ACPI_FREE ( cache - > list_head ) ;
cache - > list_head = next ;
cache - > current_depth - - ;
}
( void ) acpi_ut_release_mutex ( ACPI_MTX_CACHES ) ;
return ( AE_OK ) ;
}
/*******************************************************************************
*
* FUNCTION : acpi_os_delete_cache
*
* PARAMETERS : cache - Handle to cache object
*
* RETURN : Status
*
* DESCRIPTION : Free all objects within the requested cache and delete the
* cache object .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-05-05 12:57:53 +08:00
acpi_status acpi_os_delete_cache ( struct acpi_memory_list * cache )
2012-10-31 02:25:05 +00:00
{
acpi_status status ;
ACPI_FUNCTION_ENTRY ( ) ;
/* Purge all objects in the cache */
status = acpi_os_purge_cache ( cache ) ;
if ( ACPI_FAILURE ( status ) ) {
return ( status ) ;
}
/* Now we can delete the cache object */
acpi_os_free ( cache ) ;
return ( AE_OK ) ;
}
/*******************************************************************************
*
* FUNCTION : acpi_os_release_object
*
* PARAMETERS : cache - Handle to cache object
* object - The object to be released
*
* RETURN : None
*
2012-10-31 02:26:55 +00:00
* DESCRIPTION : Release an object to the specified cache . If cache is full ,
2012-10-31 02:25:05 +00:00
* the object is deleted .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-05-05 12:57:53 +08:00
acpi_status acpi_os_release_object ( struct acpi_memory_list * cache , void * object )
2012-10-31 02:25:05 +00:00
{
acpi_status status ;
ACPI_FUNCTION_ENTRY ( ) ;
if ( ! cache | | ! object ) {
return ( AE_BAD_PARAMETER ) ;
}
/* If cache is full, just free this object */
if ( cache - > current_depth > = cache - > max_depth ) {
ACPI_FREE ( object ) ;
ACPI_MEM_TRACKING ( cache - > total_freed + + ) ;
}
/* Otherwise put this object back into the cache */
else {
status = acpi_ut_acquire_mutex ( ACPI_MTX_CACHES ) ;
if ( ACPI_FAILURE ( status ) ) {
return ( status ) ;
}
/* Mark the object as cached */
2015-07-01 14:45:11 +08:00
memset ( object , 0xCA , cache - > object_size ) ;
2012-10-31 02:25:05 +00:00
ACPI_SET_DESCRIPTOR_TYPE ( object , ACPI_DESC_TYPE_CACHED ) ;
/* Put the object at the head of the cache list */
2013-03-08 09:21:54 +00:00
ACPI_SET_DESCRIPTOR_PTR ( object , cache - > list_head ) ;
2012-10-31 02:25:05 +00:00
cache - > list_head = object ;
cache - > current_depth + + ;
( void ) acpi_ut_release_mutex ( ACPI_MTX_CACHES ) ;
}
return ( AE_OK ) ;
}
/*******************************************************************************
*
* FUNCTION : acpi_os_acquire_object
*
* PARAMETERS : cache - Handle to cache object
*
2012-10-31 02:26:55 +00:00
* RETURN : the acquired object . NULL on error
2012-10-31 02:25:05 +00:00
*
2012-10-31 02:26:55 +00:00
* DESCRIPTION : Get an object from the specified cache . If cache is empty ,
2012-10-31 02:25:05 +00:00
* the object is allocated .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void * acpi_os_acquire_object ( struct acpi_memory_list * cache )
{
acpi_status status ;
void * object ;
2016-02-19 14:17:43 +08:00
ACPI_FUNCTION_TRACE ( os_acquire_object ) ;
2012-10-31 02:25:05 +00:00
if ( ! cache ) {
2014-01-08 13:43:12 +08:00
return_PTR ( NULL ) ;
2012-10-31 02:25:05 +00:00
}
status = acpi_ut_acquire_mutex ( ACPI_MTX_CACHES ) ;
if ( ACPI_FAILURE ( status ) ) {
2014-01-08 13:43:12 +08:00
return_PTR ( NULL ) ;
2012-10-31 02:25:05 +00:00
}
ACPI_MEM_TRACKING ( cache - > requests + + ) ;
/* Check the cache first */
if ( cache - > list_head ) {
/* There is an object available, use it */
object = cache - > list_head ;
2013-03-08 09:21:54 +00:00
cache - > list_head = ACPI_GET_DESCRIPTOR_PTR ( object ) ;
2012-10-31 02:25:05 +00:00
cache - > current_depth - - ;
ACPI_MEM_TRACKING ( cache - > hits + + ) ;
ACPI_DEBUG_PRINT ( ( ACPI_DB_EXEC ,
" Object %p from %s cache \n " , object ,
cache - > list_name ) ) ;
status = acpi_ut_release_mutex ( ACPI_MTX_CACHES ) ;
if ( ACPI_FAILURE ( status ) ) {
2014-01-08 13:43:12 +08:00
return_PTR ( NULL ) ;
2012-10-31 02:25:05 +00:00
}
/* Clear (zero) the previously used Object */
2015-07-01 14:45:11 +08:00
memset ( object , 0 , cache - > object_size ) ;
2012-10-31 02:25:05 +00:00
} else {
/* The cache is empty, create a new object */
ACPI_MEM_TRACKING ( cache - > total_allocated + + ) ;
# ifdef ACPI_DBG_TRACK_ALLOCATIONS
if ( ( cache - > total_allocated - cache - > total_freed ) >
cache - > max_occupied ) {
cache - > max_occupied =
cache - > total_allocated - cache - > total_freed ;
}
# endif
/* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
status = acpi_ut_release_mutex ( ACPI_MTX_CACHES ) ;
if ( ACPI_FAILURE ( status ) ) {
2014-01-08 13:43:12 +08:00
return_PTR ( NULL ) ;
2012-10-31 02:25:05 +00:00
}
object = ACPI_ALLOCATE_ZEROED ( cache - > object_size ) ;
if ( ! object ) {
2014-01-08 13:43:12 +08:00
return_PTR ( NULL ) ;
2012-10-31 02:25:05 +00:00
}
}
2014-01-08 13:43:12 +08:00
return_PTR ( object ) ;
2012-10-31 02:25:05 +00:00
}
# endif /* ACPI_USE_LOCAL_CACHE */