brintos

brintos / linux-shallow public Read only

0
0
Text · 6.6 KiB · 85a85f7 Raw
280 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: utcache - local cache allocation routines5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12 13#define _COMPONENT          ACPI_UTILITIES14ACPI_MODULE_NAME("utcache")15 16#ifdef ACPI_USE_LOCAL_CACHE17/*******************************************************************************18 *19 * FUNCTION:    acpi_os_create_cache20 *21 * PARAMETERS:  cache_name      - Ascii name for the cache22 *              object_size     - Size of each cached object23 *              max_depth       - Maximum depth of the cache (in objects)24 *              return_cache    - Where the new cache object is returned25 *26 * RETURN:      Status27 *28 * DESCRIPTION: Create a cache object29 *30 ******************************************************************************/31acpi_status32acpi_os_create_cache(char *cache_name,33		     u16 object_size,34		     u16 max_depth, struct acpi_memory_list **return_cache)35{36	struct acpi_memory_list *cache;37 38	ACPI_FUNCTION_ENTRY();39 40	if (!cache_name || !return_cache || !object_size) {41		return (AE_BAD_PARAMETER);42	}43 44	/* Create the cache object */45 46	cache = acpi_os_allocate(sizeof(struct acpi_memory_list));47	if (!cache) {48		return (AE_NO_MEMORY);49	}50 51	/* Populate the cache object and return it */52 53	memset(cache, 0, sizeof(struct acpi_memory_list));54	cache->list_name = cache_name;55	cache->object_size = object_size;56	cache->max_depth = max_depth;57 58	*return_cache = cache;59	return (AE_OK);60}61 62/*******************************************************************************63 *64 * FUNCTION:    acpi_os_purge_cache65 *66 * PARAMETERS:  cache           - Handle to cache object67 *68 * RETURN:      Status69 *70 * DESCRIPTION: Free all objects within the requested cache.71 *72 ******************************************************************************/73 74acpi_status acpi_os_purge_cache(struct acpi_memory_list *cache)75{76	void *next;77	acpi_status status;78 79	ACPI_FUNCTION_ENTRY();80 81	if (!cache) {82		return (AE_BAD_PARAMETER);83	}84 85	status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);86	if (ACPI_FAILURE(status)) {87		return (status);88	}89 90	/* Walk the list of objects in this cache */91 92	while (cache->list_head) {93 94		/* Delete and unlink one cached state object */95 96		next = ACPI_GET_DESCRIPTOR_PTR(cache->list_head);97		ACPI_FREE(cache->list_head);98 99		cache->list_head = next;100		cache->current_depth--;101	}102 103	(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);104	return (AE_OK);105}106 107/*******************************************************************************108 *109 * FUNCTION:    acpi_os_delete_cache110 *111 * PARAMETERS:  cache           - Handle to cache object112 *113 * RETURN:      Status114 *115 * DESCRIPTION: Free all objects within the requested cache and delete the116 *              cache object.117 *118 ******************************************************************************/119 120acpi_status acpi_os_delete_cache(struct acpi_memory_list *cache)121{122	acpi_status status;123 124	ACPI_FUNCTION_ENTRY();125 126	/* Purge all objects in the cache */127 128	status = acpi_os_purge_cache(cache);129	if (ACPI_FAILURE(status)) {130		return (status);131	}132 133	/* Now we can delete the cache object */134 135	acpi_os_free(cache);136	return (AE_OK);137}138 139/*******************************************************************************140 *141 * FUNCTION:    acpi_os_release_object142 *143 * PARAMETERS:  cache       - Handle to cache object144 *              object      - The object to be released145 *146 * RETURN:      None147 *148 * DESCRIPTION: Release an object to the specified cache. If cache is full,149 *              the object is deleted.150 *151 ******************************************************************************/152 153acpi_status acpi_os_release_object(struct acpi_memory_list *cache, void *object)154{155	acpi_status status;156 157	ACPI_FUNCTION_ENTRY();158 159	if (!cache || !object) {160		return (AE_BAD_PARAMETER);161	}162 163	/* If cache is full, just free this object */164 165	if (cache->current_depth >= cache->max_depth) {166		ACPI_FREE(object);167		ACPI_MEM_TRACKING(cache->total_freed++);168	}169 170	/* Otherwise put this object back into the cache */171 172	else {173		status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);174		if (ACPI_FAILURE(status)) {175			return (status);176		}177 178		/* Mark the object as cached */179 180		memset(object, 0xCA, cache->object_size);181		ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED);182 183		/* Put the object at the head of the cache list */184 185		ACPI_SET_DESCRIPTOR_PTR(object, cache->list_head);186		cache->list_head = object;187		cache->current_depth++;188 189		(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);190	}191 192	return (AE_OK);193}194 195/*******************************************************************************196 *197 * FUNCTION:    acpi_os_acquire_object198 *199 * PARAMETERS:  cache           - Handle to cache object200 *201 * RETURN:      the acquired object. NULL on error202 *203 * DESCRIPTION: Get an object from the specified cache. If cache is empty,204 *              the object is allocated.205 *206 ******************************************************************************/207 208void *acpi_os_acquire_object(struct acpi_memory_list *cache)209{210	acpi_status status;211	void *object;212 213	ACPI_FUNCTION_TRACE(os_acquire_object);214 215	if (!cache) {216		return_PTR(NULL);217	}218 219	status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);220	if (ACPI_FAILURE(status)) {221		return_PTR(NULL);222	}223 224	ACPI_MEM_TRACKING(cache->requests++);225 226	/* Check the cache first */227 228	if (cache->list_head) {229 230		/* There is an object available, use it */231 232		object = cache->list_head;233		cache->list_head = ACPI_GET_DESCRIPTOR_PTR(object);234 235		cache->current_depth--;236 237		ACPI_MEM_TRACKING(cache->hits++);238		ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,239				      "%s: Object %p from %s cache\n",240				      ACPI_GET_FUNCTION_NAME, object,241				      cache->list_name));242 243		status = acpi_ut_release_mutex(ACPI_MTX_CACHES);244		if (ACPI_FAILURE(status)) {245			return_PTR(NULL);246		}247 248		/* Clear (zero) the previously used Object */249 250		memset(object, 0, cache->object_size);251	} else {252		/* The cache is empty, create a new object */253 254		ACPI_MEM_TRACKING(cache->total_allocated++);255 256#ifdef ACPI_DBG_TRACK_ALLOCATIONS257		if ((cache->total_allocated - cache->total_freed) >258		    cache->max_occupied) {259			cache->max_occupied =260			    cache->total_allocated - cache->total_freed;261		}262#endif263 264		/* Avoid deadlock with ACPI_ALLOCATE_ZEROED */265 266		status = acpi_ut_release_mutex(ACPI_MTX_CACHES);267		if (ACPI_FAILURE(status)) {268			return_PTR(NULL);269		}270 271		object = ACPI_ALLOCATE_ZEROED(cache->object_size);272		if (!object) {273			return_PTR(NULL);274		}275	}276 277	return_PTR(object);278}279#endif				/* ACPI_USE_LOCAL_CACHE */280