123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- /*
- * Copyright 2021 Rockchip Electronics Co. LTD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #define MODULE_TAG "mpp_mem_pool"
- #include <string.h>
- #include "mpp_err.h"
- #include "mpp_env.h"
- #include "mpp_mem.h"
- #include "mpp_list.h"
- #include "mpp_debug.h"
- #include "mpp_mem_pool.h"
- #define MPP_MEM_POOL_DBG_FLOW (0x00000001)
- #define mem_pool_dbg(flag, fmt, ...) _mpp_dbg(mpp_mem_pool_debug, flag, fmt, ## __VA_ARGS__)
- #define mem_pool_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpp_mem_pool_debug, flag, fmt, ## __VA_ARGS__)
- #define mem_pool_dbg_flow(fmt, ...) mem_pool_dbg(MPP_MEM_POOL_DBG_FLOW, fmt, ## __VA_ARGS__)
- RK_U32 mpp_mem_pool_debug = 0;
- typedef struct MppMemPoolNode_t {
- void *check;
- struct list_head list;
- void *ptr;
- size_t size;
- } MppMemPoolNode;
- typedef struct MppMemPoolImpl_t {
- void *check;
- const char *caller;
- size_t size;
- pthread_mutex_t lock;
- struct list_head service_link;
- struct list_head used;
- struct list_head unused;
- RK_S32 used_count;
- RK_S32 unused_count;
- /* extra flag for C++ static destruction order error */
- RK_S32 finalized;
- } MppMemPoolImpl;
- class MppMemPoolService
- {
- public:
- static MppMemPoolService* getInstance() {
- AutoMutex auto_lock(get_lock());
- static MppMemPoolService pool_service;
- return &pool_service;
- }
- static Mutex *get_lock() {
- static Mutex lock;
- return &lock;
- }
- MppMemPoolImpl *get_pool(const char *caller, size_t size);
- void put_pool(MppMemPoolImpl *impl);
- private:
- MppMemPoolService();
- ~MppMemPoolService();
- struct list_head mLink;
- };
- MppMemPoolService::MppMemPoolService()
- {
- INIT_LIST_HEAD(&mLink);
- mpp_env_get_u32("mpp_mem_pool_debug", &mpp_mem_pool_debug, 0);
- }
- MppMemPoolService::~MppMemPoolService()
- {
- if (!list_empty(&mLink)) {
- MppMemPoolImpl *pos, *n;
- list_for_each_entry_safe(pos, n, &mLink, MppMemPoolImpl, service_link) {
- put_pool(pos);
- }
- }
- }
- MppMemPoolImpl *MppMemPoolService::get_pool(const char *caller, size_t size)
- {
- MppMemPoolImpl *pool = mpp_malloc(MppMemPoolImpl, 1);
- if (NULL == pool)
- return NULL;
- pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&pool->lock, &attr);
- pthread_mutexattr_destroy(&attr);
- pool->check = pool;
- pool->caller = caller;
- pool->size = size;
- pool->used_count = 0;
- pool->unused_count = 0;
- pool->finalized = 0;
- INIT_LIST_HEAD(&pool->used);
- INIT_LIST_HEAD(&pool->unused);
- INIT_LIST_HEAD(&pool->service_link);
- AutoMutex auto_lock(get_lock());
- list_add_tail(&pool->service_link, &mLink);
- return pool;
- }
- void MppMemPoolService::put_pool(MppMemPoolImpl *impl)
- {
- MppMemPoolNode *node, *m;
- if (impl != impl->check) {
- mpp_err_f("invalid mem impl %p check %p\n", impl, impl->check);
- return;
- }
- if (impl->finalized)
- return;
- pthread_mutex_lock(&impl->lock);
- if (!list_empty(&impl->unused)) {
- list_for_each_entry_safe(node, m, &impl->unused, MppMemPoolNode, list) {
- MPP_FREE(node);
- impl->unused_count--;
- }
- }
- if (!list_empty(&impl->used)) {
- mpp_err_f("pool %s found %d used buffer size %d\n",
- impl->caller, impl->used_count, impl->size);
- list_for_each_entry_safe(node, m, &impl->used, MppMemPoolNode, list) {
- MPP_FREE(node);
- impl->used_count--;
- }
- }
- if (impl->used_count || impl->unused_count)
- mpp_err_f("pool %s size %d found leaked buffer used:unused [%d:%d]\n",
- impl->caller, impl->size, impl->used_count, impl->unused_count);
- pthread_mutex_unlock(&impl->lock);
- {
- AutoMutex auto_lock(get_lock());
- list_del_init(&impl->service_link);
- }
- impl->finalized = 1;
- mpp_free(impl);
- }
- MppMemPool mpp_mem_pool_init_f(const char *caller, size_t size)
- {
- mem_pool_dbg_flow("pool %d init from %s", size, caller);
- return (MppMemPool)MppMemPoolService::getInstance()->get_pool(caller, size);
- }
- void mpp_mem_pool_deinit_f(const char *caller, MppMemPool pool)
- {
- MppMemPoolImpl *impl = (MppMemPoolImpl *)pool;
- mem_pool_dbg_flow("pool %d deinit from %s", impl->size, caller);
- MppMemPoolService::getInstance()->put_pool(impl);
- }
- void *mpp_mem_pool_get_f(const char *caller, MppMemPool pool)
- {
- MppMemPoolImpl *impl = (MppMemPoolImpl *)pool;
- MppMemPoolNode *node = NULL;
- void* ptr = NULL;
- pthread_mutex_lock(&impl->lock);
- mem_pool_dbg_flow("pool %d get used:unused [%d:%d] from %s", impl->size,
- impl->used_count, impl->unused_count, caller);
- if (!list_empty(&impl->unused)) {
- node = list_first_entry(&impl->unused, MppMemPoolNode, list);
- if (node) {
- list_del_init(&node->list);
- list_add_tail(&node->list, &impl->used);
- impl->unused_count--;
- impl->used_count++;
- ptr = node->ptr;
- node->check = node;
- goto DONE;
- }
- }
- node = mpp_malloc_size(MppMemPoolNode, sizeof(MppMemPoolNode) + impl->size);
- if (NULL == node) {
- mpp_err_f("failed to create node from size %d pool\n", impl->size);
- goto DONE;
- }
- node->check = node;
- node->ptr = (void *)(node + 1);
- node->size = impl->size;
- INIT_LIST_HEAD(&node->list);
- list_add_tail(&node->list, &impl->used);
- impl->used_count++;
- ptr = node->ptr;
- DONE:
- pthread_mutex_unlock(&impl->lock);
- if (node)
- memset(node->ptr, 0 , node->size);
- return ptr;
- }
- void mpp_mem_pool_put_f(const char *caller, MppMemPool pool, void *p)
- {
- MppMemPoolImpl *impl = (MppMemPoolImpl *)pool;
- MppMemPoolNode *node = (MppMemPoolNode *)((RK_U8 *)p - sizeof(MppMemPoolNode));
- if (impl != impl->check) {
- mpp_err_f("invalid mem pool %p check %p\n", impl, impl->check);
- return ;
- }
- if (node != node->check) {
- mpp_err_f("invalid mem pool ptr %p node %p check %p\n",
- p, node, node->check);
- return ;
- }
- pthread_mutex_lock(&impl->lock);
- mem_pool_dbg_flow("pool %d put used:unused [%d:%d] from %s", impl->size,
- impl->used_count, impl->unused_count, caller);
- list_del_init(&node->list);
- list_add(&node->list, &impl->unused);
- impl->used_count--;
- impl->unused_count++;
- node->check = NULL;
- pthread_mutex_unlock(&impl->lock);
- }
|