utcache.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Module Name: utcache - local cache allocation routines
  5. *
  6. * Copyright (C) 2000 - 2022, Intel Corp.
  7. *
  8. *****************************************************************************/
  9. #include <acpi/acpi.h>
  10. #include "accommon.h"
  11. #define _COMPONENT ACPI_UTILITIES
  12. ACPI_MODULE_NAME("utcache")
  13. #ifdef ACPI_USE_LOCAL_CACHE
  14. /*******************************************************************************
  15. *
  16. * FUNCTION: acpi_os_create_cache
  17. *
  18. * PARAMETERS: cache_name - Ascii name for the cache
  19. * object_size - Size of each cached object
  20. * max_depth - Maximum depth of the cache (in objects)
  21. * return_cache - Where the new cache object is returned
  22. *
  23. * RETURN: Status
  24. *
  25. * DESCRIPTION: Create a cache object
  26. *
  27. ******************************************************************************/
  28. acpi_status
  29. acpi_os_create_cache(char *cache_name,
  30. u16 object_size,
  31. u16 max_depth, struct acpi_memory_list **return_cache)
  32. {
  33. struct acpi_memory_list *cache;
  34. ACPI_FUNCTION_ENTRY();
  35. if (!cache_name || !return_cache || !object_size) {
  36. return (AE_BAD_PARAMETER);
  37. }
  38. /* Create the cache object */
  39. cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
  40. if (!cache) {
  41. return (AE_NO_MEMORY);
  42. }
  43. /* Populate the cache object and return it */
  44. memset(cache, 0, sizeof(struct acpi_memory_list));
  45. cache->list_name = cache_name;
  46. cache->object_size = object_size;
  47. cache->max_depth = max_depth;
  48. *return_cache = cache;
  49. return (AE_OK);
  50. }
  51. /*******************************************************************************
  52. *
  53. * FUNCTION: acpi_os_purge_cache
  54. *
  55. * PARAMETERS: cache - Handle to cache object
  56. *
  57. * RETURN: Status
  58. *
  59. * DESCRIPTION: Free all objects within the requested cache.
  60. *
  61. ******************************************************************************/
  62. acpi_status acpi_os_purge_cache(struct acpi_memory_list *cache)
  63. {
  64. void *next;
  65. acpi_status status;
  66. ACPI_FUNCTION_ENTRY();
  67. if (!cache) {
  68. return (AE_BAD_PARAMETER);
  69. }
  70. status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
  71. if (ACPI_FAILURE(status)) {
  72. return (status);
  73. }
  74. /* Walk the list of objects in this cache */
  75. while (cache->list_head) {
  76. /* Delete and unlink one cached state object */
  77. next = ACPI_GET_DESCRIPTOR_PTR(cache->list_head);
  78. ACPI_FREE(cache->list_head);
  79. cache->list_head = next;
  80. cache->current_depth--;
  81. }
  82. (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
  83. return (AE_OK);
  84. }
  85. /*******************************************************************************
  86. *
  87. * FUNCTION: acpi_os_delete_cache
  88. *
  89. * PARAMETERS: cache - Handle to cache object
  90. *
  91. * RETURN: Status
  92. *
  93. * DESCRIPTION: Free all objects within the requested cache and delete the
  94. * cache object.
  95. *
  96. ******************************************************************************/
  97. acpi_status acpi_os_delete_cache(struct acpi_memory_list *cache)
  98. {
  99. acpi_status status;
  100. ACPI_FUNCTION_ENTRY();
  101. /* Purge all objects in the cache */
  102. status = acpi_os_purge_cache(cache);
  103. if (ACPI_FAILURE(status)) {
  104. return (status);
  105. }
  106. /* Now we can delete the cache object */
  107. acpi_os_free(cache);
  108. return (AE_OK);
  109. }
  110. /*******************************************************************************
  111. *
  112. * FUNCTION: acpi_os_release_object
  113. *
  114. * PARAMETERS: cache - Handle to cache object
  115. * object - The object to be released
  116. *
  117. * RETURN: None
  118. *
  119. * DESCRIPTION: Release an object to the specified cache. If cache is full,
  120. * the object is deleted.
  121. *
  122. ******************************************************************************/
  123. acpi_status acpi_os_release_object(struct acpi_memory_list *cache, void *object)
  124. {
  125. acpi_status status;
  126. ACPI_FUNCTION_ENTRY();
  127. if (!cache || !object) {
  128. return (AE_BAD_PARAMETER);
  129. }
  130. /* If cache is full, just free this object */
  131. if (cache->current_depth >= cache->max_depth) {
  132. ACPI_FREE(object);
  133. ACPI_MEM_TRACKING(cache->total_freed++);
  134. }
  135. /* Otherwise put this object back into the cache */
  136. else {
  137. status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
  138. if (ACPI_FAILURE(status)) {
  139. return (status);
  140. }
  141. /* Mark the object as cached */
  142. memset(object, 0xCA, cache->object_size);
  143. ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED);
  144. /* Put the object at the head of the cache list */
  145. ACPI_SET_DESCRIPTOR_PTR(object, cache->list_head);
  146. cache->list_head = object;
  147. cache->current_depth++;
  148. (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
  149. }
  150. return (AE_OK);
  151. }
  152. /*******************************************************************************
  153. *
  154. * FUNCTION: acpi_os_acquire_object
  155. *
  156. * PARAMETERS: cache - Handle to cache object
  157. *
  158. * RETURN: the acquired object. NULL on error
  159. *
  160. * DESCRIPTION: Get an object from the specified cache. If cache is empty,
  161. * the object is allocated.
  162. *
  163. ******************************************************************************/
  164. void *acpi_os_acquire_object(struct acpi_memory_list *cache)
  165. {
  166. acpi_status status;
  167. void *object;
  168. ACPI_FUNCTION_TRACE(os_acquire_object);
  169. if (!cache) {
  170. return_PTR(NULL);
  171. }
  172. status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
  173. if (ACPI_FAILURE(status)) {
  174. return_PTR(NULL);
  175. }
  176. ACPI_MEM_TRACKING(cache->requests++);
  177. /* Check the cache first */
  178. if (cache->list_head) {
  179. /* There is an object available, use it */
  180. object = cache->list_head;
  181. cache->list_head = ACPI_GET_DESCRIPTOR_PTR(object);
  182. cache->current_depth--;
  183. ACPI_MEM_TRACKING(cache->hits++);
  184. ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
  185. "%s: Object %p from %s cache\n",
  186. ACPI_GET_FUNCTION_NAME, object,
  187. cache->list_name));
  188. status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
  189. if (ACPI_FAILURE(status)) {
  190. return_PTR(NULL);
  191. }
  192. /* Clear (zero) the previously used Object */
  193. memset(object, 0, cache->object_size);
  194. } else {
  195. /* The cache is empty, create a new object */
  196. ACPI_MEM_TRACKING(cache->total_allocated++);
  197. #ifdef ACPI_DBG_TRACK_ALLOCATIONS
  198. if ((cache->total_allocated - cache->total_freed) >
  199. cache->max_occupied) {
  200. cache->max_occupied =
  201. cache->total_allocated - cache->total_freed;
  202. }
  203. #endif
  204. /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
  205. status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
  206. if (ACPI_FAILURE(status)) {
  207. return_PTR(NULL);
  208. }
  209. object = ACPI_ALLOCATE_ZEROED(cache->object_size);
  210. if (!object) {
  211. return_PTR(NULL);
  212. }
  213. }
  214. return_PTR(object);
  215. }
  216. #endif /* ACPI_USE_LOCAL_CACHE */