From c822e92b19971f5923a472115595185e851497f2 Mon Sep 17 00:00:00 2001 From: YuQing <384681@qq.com> Date: Thu, 14 Jan 2021 15:25:37 +0800 Subject: [PATCH] fast_mblock.[hc]: support wait with element limit --- HISTORY | 3 +- src/fast_mblock.c | 130 +++++++++++++++++++++++++++++----------------- src/fast_mblock.h | 31 +++++++++-- 3 files changed, 112 insertions(+), 52 deletions(-) diff --git a/HISTORY b/HISTORY index 72d0ab9..68729cd 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,7 @@ -Version 1.47 2021-01-11 +Version 1.47 2021-01-14 * fc_atomic.h: add FC_ATOMIC_SET + * fast_mblock.[hc]: support wait with element limit Version 1.46 2020-12-29 * add function get_time_item_from_conf_ex diff --git a/src/fast_mblock.c b/src/fast_mblock.c index 8bfe98a..43f687e 100644 --- a/src/fast_mblock.c +++ b/src/fast_mblock.c @@ -18,11 +18,10 @@ #include #include #include -#include -#include "logger.h" #include "shared_func.h" #include "pthread_func.h" #include "sched_thread.h" +#include "pthread_func.h" #include "fast_mblock.h" struct _fast_mblock_manager @@ -402,7 +401,7 @@ int fast_mblock_init_ex2(struct fast_mblock_man *mblock, const char *name, mblock->alloc_elements.once = mblock->alloc_elements.limit; } - if (need_lock && (result=init_pthread_lock(&(mblock->lock))) != 0) + if (need_lock && (result=init_pthread_lock_cond_pair(&(mblock->lcp))) != 0) { logError("file: "__FILE__", line: %d, " \ "init_pthread_lock fail, errno: %d, error info: %s", \ @@ -425,7 +424,9 @@ int fast_mblock_init_ex2(struct fast_mblock_man *mblock, const char *name, mblock->info.trunk_size = fast_mblock_get_trunk_size(mblock, block_size, mblock->alloc_elements.once); mblock->need_lock = need_lock; - mblock->exceed_log_level = LOG_ERR; + mblock->alloc_elements.need_wait = false; + mblock->alloc_elements.pcontinue_flag = NULL; + mblock->alloc_elements.exceed_log_level = LOG_ERR; mblock->malloc_trunk_callback.check_func = malloc_trunk_check; mblock->malloc_trunk_callback.notify_func = malloc_trunk_notify; mblock->malloc_trunk_callback.args = malloc_trunk_args; @@ -464,10 +465,13 @@ static int fast_mblock_prealloc(struct fast_mblock_man *mblock) mblock->info.element_total_count; if (avail_count <= 0) { - log_it_ex(&g_log_context, mblock->exceed_log_level, - "file: "__FILE__", line: %d, " - "allocated elements exceed limit: %"PRId64, - __LINE__, mblock->alloc_elements.limit); + if (FC_LOG_BY_LEVEL(mblock->alloc_elements.exceed_log_level)) + { + log_it_ex(&g_log_context, mblock->alloc_elements. + exceed_log_level, "file: "__FILE__", line: %d, " + "allocated elements exceed limit: %"PRId64, + __LINE__, mblock->alloc_elements.limit); + } return EOVERFLOW; } @@ -615,7 +619,7 @@ void fast_mblock_destroy(struct fast_mblock_man *mblock) mblock->info.delay_free_elements = 0; mblock->info.element_total_count = 0; - if (mblock->need_lock) pthread_mutex_destroy(&(mblock->lock)); + if (mblock->need_lock) destroy_pthread_lock_cond_pair(&(mblock->lcp)); delete_from_mblock_list(mblock); } @@ -624,7 +628,8 @@ struct fast_mblock_node *fast_mblock_alloc(struct fast_mblock_man *mblock) struct fast_mblock_node *pNode; int result; - if (mblock->need_lock && (result=pthread_mutex_lock(&(mblock->lock))) != 0) + if (mblock->need_lock && (result=pthread_mutex_lock( + &mblock->lcp.lock)) != 0) { logError("file: "__FILE__", line: %d, " "call pthread_mutex_lock fail, " @@ -633,15 +638,18 @@ struct fast_mblock_node *fast_mblock_alloc(struct fast_mblock_man *mblock) return NULL; } - if (mblock->free_chain_head != NULL) - { - pNode = mblock->free_chain_head; - mblock->free_chain_head = pNode->next; - } - else - { + while (1) + { + if (mblock->free_chain_head != NULL) + { + pNode = mblock->free_chain_head; + mblock->free_chain_head = pNode->next; + break; + } + if (mblock->delay_free_chain.head != NULL && - mblock->delay_free_chain.head->recycle_timestamp <= get_current_time()) + mblock->delay_free_chain.head-> + recycle_timestamp <= get_current_time()) { pNode = mblock->delay_free_chain.head; mblock->delay_free_chain.head = pNode->next; @@ -651,24 +659,37 @@ struct fast_mblock_node *fast_mblock_alloc(struct fast_mblock_man *mblock) } mblock->info.delay_free_elements--; + break; } - else if ((result=fast_mblock_prealloc(mblock)) == 0) - { - pNode = mblock->free_chain_head; - mblock->free_chain_head = pNode->next; - } - else - { - pNode = NULL; - } - } + + if ((result=fast_mblock_prealloc(mblock)) == 0) + { + pNode = mblock->free_chain_head; + mblock->free_chain_head = pNode->next; + break; + } + + if (!mblock->alloc_elements.need_wait) + { + pNode = NULL; + break; + } + + pthread_cond_wait(&mblock->lcp.cond, &mblock->lcp.lock); + if (!*(mblock->alloc_elements.pcontinue_flag)) + { + pNode = NULL; + break; + } + } if (pNode != NULL) { mblock->info.element_used_count++; fast_mblock_ref_counter_inc(mblock, pNode); } - if (mblock->need_lock && (result=pthread_mutex_unlock(&(mblock->lock))) != 0) + if (mblock->need_lock && (result=pthread_mutex_unlock( + &mblock->lcp.lock)) != 0) { logError("file: "__FILE__", line: %d, " \ "call pthread_mutex_unlock fail, " \ @@ -683,8 +704,10 @@ int fast_mblock_free(struct fast_mblock_man *mblock, \ struct fast_mblock_node *pNode) { int result; + bool notify; - if (mblock->need_lock && (result=pthread_mutex_lock(&(mblock->lock))) != 0) + if (mblock->need_lock && (result=pthread_mutex_lock( + &mblock->lcp.lock)) != 0) { logError("file: "__FILE__", line: %d, " \ "call pthread_mutex_lock fail, " \ @@ -693,16 +716,23 @@ int fast_mblock_free(struct fast_mblock_man *mblock, \ return result; } + notify = (mblock->free_chain_head == NULL); pNode->next = mblock->free_chain_head; mblock->free_chain_head = pNode; mblock->info.element_used_count--; fast_mblock_ref_counter_dec(mblock, pNode); - if (mblock->need_lock && (result=pthread_mutex_unlock(&(mblock->lock))) != 0) + if (mblock->alloc_elements.need_wait && notify) + { + pthread_cond_signal(&mblock->lcp.cond); + } + + if (mblock->need_lock && (result=pthread_mutex_unlock( + &mblock->lcp.lock)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "call pthread_mutex_unlock fail, " \ - "errno: %d, error info: %s", \ + logError("file: "__FILE__", line: %d, " + "call pthread_mutex_unlock fail, " + "errno: %d, error info: %s", __LINE__, result, STRERROR(result)); } @@ -714,7 +744,8 @@ int fast_mblock_delay_free(struct fast_mblock_man *mblock, { int result; - if (mblock->need_lock && (result=pthread_mutex_lock(&(mblock->lock))) != 0) + if (mblock->need_lock && (result=pthread_mutex_lock( + &mblock->lcp.lock)) != 0) { logError("file: "__FILE__", line: %d, " \ "call pthread_mutex_lock fail, " \ @@ -739,7 +770,8 @@ int fast_mblock_delay_free(struct fast_mblock_man *mblock, mblock->info.delay_free_elements++; fast_mblock_ref_counter_dec(mblock, pNode); - if (mblock->need_lock && (result=pthread_mutex_unlock(&(mblock->lock))) != 0) + if (mblock->need_lock && (result=pthread_mutex_unlock( + &mblock->lcp.lock)) != 0) { logError("file: "__FILE__", line: %d, " \ "call pthread_mutex_unlock fail, " \ @@ -757,7 +789,8 @@ static int fast_mblock_chain_count(struct fast_mblock_man *mblock, int count; int result; - if (mblock->need_lock && (result=pthread_mutex_lock(&(mblock->lock))) != 0) + if (mblock->need_lock && (result=pthread_mutex_lock( + &mblock->lcp.lock)) != 0) { logError("file: "__FILE__", line: %d, " \ "call pthread_mutex_lock fail, " \ @@ -774,7 +807,8 @@ static int fast_mblock_chain_count(struct fast_mblock_man *mblock, count++; } - if (mblock->need_lock && (result=pthread_mutex_unlock(&(mblock->lock))) != 0) + if (mblock->need_lock && (result=pthread_mutex_unlock( + &mblock->lcp.lock)) != 0) { logError("file: "__FILE__", line: %d, " \ "call pthread_mutex_unlock fail, " \ @@ -929,15 +963,16 @@ int fast_mblock_reclaim(struct fast_mblock_man *mblock, return EINVAL; } - if (mblock->need_lock && (result=pthread_mutex_lock(&(mblock->lock))) != 0) - { - logError("file: "__FILE__", line: %d, " \ - "call pthread_mutex_lock fail, " \ - "errno: %d, error info: %s", \ - __LINE__, result, STRERROR(result)); + if (mblock->need_lock && (result=pthread_mutex_lock( + &mblock->lcp.lock)) != 0) + { + logError("file: "__FILE__", line: %d, " \ + "call pthread_mutex_lock fail, " \ + "errno: %d, error info: %s", \ + __LINE__, result, STRERROR(result)); *reclaim_count = 0; - return result; - } + return result; + } if (reclaim_target > 0 && mblock->info.trunk_total_count - mblock->info.trunk_used_count < reclaim_target) @@ -952,7 +987,8 @@ int fast_mblock_reclaim(struct fast_mblock_man *mblock, reclaim_count, &freelist); } - if (mblock->need_lock && (result=pthread_mutex_unlock(&(mblock->lock))) != 0) + if (mblock->need_lock && (result=pthread_mutex_unlock( + &mblock->lcp.lock)) != 0) { logError("file: "__FILE__", line: %d, " \ "call pthread_mutex_unlock fail, " \ diff --git a/src/fast_mblock.h b/src/fast_mblock.h index 907e2dd..441ce17 100644 --- a/src/fast_mblock.h +++ b/src/fast_mblock.h @@ -25,6 +25,7 @@ #include "common_define.h" #include "fc_memory.h" #include "chain.h" +#include "logger.h" #define FAST_MBLOCK_NAME_SIZE 32 @@ -92,8 +93,11 @@ struct fast_mblock_man { struct fast_mblock_info info; struct { - int once; //alloc elements once - int64_t limit; //<= 0 for no limit + bool need_wait; + int exceed_log_level; //for exceed limit + int once; //alloc elements once + int64_t limit; //<= 0 for no limit + bool *pcontinue_flag; } alloc_elements; struct fast_mblock_node *free_chain_head; //free node chain struct fast_mblock_trunks trunks; @@ -103,8 +107,7 @@ struct fast_mblock_man struct fast_mblock_malloc_trunk_callback malloc_trunk_callback; bool need_lock; //if need mutex lock - int exceed_log_level; //log level for exceed limit - pthread_mutex_t lock; //the lock for read / write free node chain + pthread_lock_cond_pair_t lcp; //for read / write free node chain struct fast_mblock_man *prev; //for stat manager struct fast_mblock_man *next; //for stat manager void *init_args; //args for alloc_init_func @@ -202,6 +205,26 @@ parameters: */ void fast_mblock_destroy(struct fast_mblock_man *mblock); +static inline int fast_mblock_set_need_wait(struct fast_mblock_man *mblock, + const bool need_wait, bool * volatile pcontinue_flag) +{ + if (!mblock->need_lock || mblock->alloc_elements.limit <= 0) + { + logError("file: "__FILE__", line: %d, " + "need_lock: %d != 1 or alloc_elements.limit: %"PRId64" <= 0", + __LINE__, mblock->need_lock, mblock->alloc_elements.limit); + return EINVAL; + } + + mblock->alloc_elements.need_wait = need_wait; + mblock->alloc_elements.pcontinue_flag = pcontinue_flag; + if (need_wait) + { + mblock->alloc_elements.exceed_log_level = LOG_NOTHING; + } + return 0; +} + /** alloc a node from the mblock parameters: