mpp_mem_pool.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. * Copyright 2021 Rockchip Electronics Co. LTD
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #define MODULE_TAG "mpp_mem_pool"
  17. #include <string.h>
  18. #include "mpp_err.h"
  19. #include "mpp_env.h"
  20. #include "mpp_mem.h"
  21. #include "mpp_list.h"
  22. #include "mpp_debug.h"
  23. #include "mpp_mem_pool.h"
  24. #define MPP_MEM_POOL_DBG_FLOW (0x00000001)
  25. #define mem_pool_dbg(flag, fmt, ...) _mpp_dbg(mpp_mem_pool_debug, flag, fmt, ## __VA_ARGS__)
  26. #define mem_pool_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpp_mem_pool_debug, flag, fmt, ## __VA_ARGS__)
  27. #define mem_pool_dbg_flow(fmt, ...) mem_pool_dbg(MPP_MEM_POOL_DBG_FLOW, fmt, ## __VA_ARGS__)
  28. RK_U32 mpp_mem_pool_debug = 0;
  29. typedef struct MppMemPoolNode_t {
  30. void *check;
  31. struct list_head list;
  32. void *ptr;
  33. size_t size;
  34. } MppMemPoolNode;
  35. typedef struct MppMemPoolImpl_t {
  36. void *check;
  37. const char *caller;
  38. size_t size;
  39. pthread_mutex_t lock;
  40. struct list_head service_link;
  41. struct list_head used;
  42. struct list_head unused;
  43. RK_S32 used_count;
  44. RK_S32 unused_count;
  45. /* extra flag for C++ static destruction order error */
  46. RK_S32 finalized;
  47. } MppMemPoolImpl;
  48. class MppMemPoolService
  49. {
  50. public:
  51. static MppMemPoolService* getInstance() {
  52. AutoMutex auto_lock(get_lock());
  53. static MppMemPoolService pool_service;
  54. return &pool_service;
  55. }
  56. static Mutex *get_lock() {
  57. static Mutex lock;
  58. return &lock;
  59. }
  60. MppMemPoolImpl *get_pool(const char *caller, size_t size);
  61. void put_pool(MppMemPoolImpl *impl);
  62. private:
  63. MppMemPoolService();
  64. ~MppMemPoolService();
  65. struct list_head mLink;
  66. };
  67. MppMemPoolService::MppMemPoolService()
  68. {
  69. INIT_LIST_HEAD(&mLink);
  70. mpp_env_get_u32("mpp_mem_pool_debug", &mpp_mem_pool_debug, 0);
  71. }
  72. MppMemPoolService::~MppMemPoolService()
  73. {
  74. if (!list_empty(&mLink)) {
  75. MppMemPoolImpl *pos, *n;
  76. list_for_each_entry_safe(pos, n, &mLink, MppMemPoolImpl, service_link) {
  77. put_pool(pos);
  78. }
  79. }
  80. }
  81. MppMemPoolImpl *MppMemPoolService::get_pool(const char *caller, size_t size)
  82. {
  83. MppMemPoolImpl *pool = mpp_malloc(MppMemPoolImpl, 1);
  84. if (NULL == pool)
  85. return NULL;
  86. pthread_mutexattr_t attr;
  87. pthread_mutexattr_init(&attr);
  88. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  89. pthread_mutex_init(&pool->lock, &attr);
  90. pthread_mutexattr_destroy(&attr);
  91. pool->check = pool;
  92. pool->caller = caller;
  93. pool->size = size;
  94. pool->used_count = 0;
  95. pool->unused_count = 0;
  96. pool->finalized = 0;
  97. INIT_LIST_HEAD(&pool->used);
  98. INIT_LIST_HEAD(&pool->unused);
  99. INIT_LIST_HEAD(&pool->service_link);
  100. AutoMutex auto_lock(get_lock());
  101. list_add_tail(&pool->service_link, &mLink);
  102. return pool;
  103. }
  104. void MppMemPoolService::put_pool(MppMemPoolImpl *impl)
  105. {
  106. MppMemPoolNode *node, *m;
  107. if (impl != impl->check) {
  108. mpp_err_f("invalid mem impl %p check %p\n", impl, impl->check);
  109. return;
  110. }
  111. if (impl->finalized)
  112. return;
  113. pthread_mutex_lock(&impl->lock);
  114. if (!list_empty(&impl->unused)) {
  115. list_for_each_entry_safe(node, m, &impl->unused, MppMemPoolNode, list) {
  116. MPP_FREE(node);
  117. impl->unused_count--;
  118. }
  119. }
  120. if (!list_empty(&impl->used)) {
  121. mpp_err_f("pool %s found %d used buffer size %d\n",
  122. impl->caller, impl->used_count, impl->size);
  123. list_for_each_entry_safe(node, m, &impl->used, MppMemPoolNode, list) {
  124. MPP_FREE(node);
  125. impl->used_count--;
  126. }
  127. }
  128. if (impl->used_count || impl->unused_count)
  129. mpp_err_f("pool %s size %d found leaked buffer used:unused [%d:%d]\n",
  130. impl->caller, impl->size, impl->used_count, impl->unused_count);
  131. pthread_mutex_unlock(&impl->lock);
  132. {
  133. AutoMutex auto_lock(get_lock());
  134. list_del_init(&impl->service_link);
  135. }
  136. impl->finalized = 1;
  137. mpp_free(impl);
  138. }
  139. MppMemPool mpp_mem_pool_init_f(const char *caller, size_t size)
  140. {
  141. mem_pool_dbg_flow("pool %d init from %s", size, caller);
  142. return (MppMemPool)MppMemPoolService::getInstance()->get_pool(caller, size);
  143. }
  144. void mpp_mem_pool_deinit_f(const char *caller, MppMemPool pool)
  145. {
  146. MppMemPoolImpl *impl = (MppMemPoolImpl *)pool;
  147. mem_pool_dbg_flow("pool %d deinit from %s", impl->size, caller);
  148. MppMemPoolService::getInstance()->put_pool(impl);
  149. }
  150. void *mpp_mem_pool_get_f(const char *caller, MppMemPool pool)
  151. {
  152. MppMemPoolImpl *impl = (MppMemPoolImpl *)pool;
  153. MppMemPoolNode *node = NULL;
  154. void* ptr = NULL;
  155. pthread_mutex_lock(&impl->lock);
  156. mem_pool_dbg_flow("pool %d get used:unused [%d:%d] from %s", impl->size,
  157. impl->used_count, impl->unused_count, caller);
  158. if (!list_empty(&impl->unused)) {
  159. node = list_first_entry(&impl->unused, MppMemPoolNode, list);
  160. if (node) {
  161. list_del_init(&node->list);
  162. list_add_tail(&node->list, &impl->used);
  163. impl->unused_count--;
  164. impl->used_count++;
  165. ptr = node->ptr;
  166. node->check = node;
  167. goto DONE;
  168. }
  169. }
  170. node = mpp_malloc_size(MppMemPoolNode, sizeof(MppMemPoolNode) + impl->size);
  171. if (NULL == node) {
  172. mpp_err_f("failed to create node from size %d pool\n", impl->size);
  173. goto DONE;
  174. }
  175. node->check = node;
  176. node->ptr = (void *)(node + 1);
  177. node->size = impl->size;
  178. INIT_LIST_HEAD(&node->list);
  179. list_add_tail(&node->list, &impl->used);
  180. impl->used_count++;
  181. ptr = node->ptr;
  182. DONE:
  183. pthread_mutex_unlock(&impl->lock);
  184. if (node)
  185. memset(node->ptr, 0 , node->size);
  186. return ptr;
  187. }
  188. void mpp_mem_pool_put_f(const char *caller, MppMemPool pool, void *p)
  189. {
  190. MppMemPoolImpl *impl = (MppMemPoolImpl *)pool;
  191. MppMemPoolNode *node = (MppMemPoolNode *)((RK_U8 *)p - sizeof(MppMemPoolNode));
  192. if (impl != impl->check) {
  193. mpp_err_f("invalid mem pool %p check %p\n", impl, impl->check);
  194. return ;
  195. }
  196. if (node != node->check) {
  197. mpp_err_f("invalid mem pool ptr %p node %p check %p\n",
  198. p, node, node->check);
  199. return ;
  200. }
  201. pthread_mutex_lock(&impl->lock);
  202. mem_pool_dbg_flow("pool %d put used:unused [%d:%d] from %s", impl->size,
  203. impl->used_count, impl->unused_count, caller);
  204. list_del_init(&node->list);
  205. list_add(&node->list, &impl->unused);
  206. impl->used_count--;
  207. impl->unused_count++;
  208. node->check = NULL;
  209. pthread_mutex_unlock(&impl->lock);
  210. }