diff --git a/src/Makefile.in b/src/Makefile.in index 78b7975..df33213 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -8,19 +8,22 @@ FAST_SHARED_OBJS = hash.lo chain.lo shared_func.lo ini_file_reader.lo \ logger.lo sockopt.lo base64.lo sched_thread.lo \ http_func.lo md5.lo pthread_func.lo local_ip_func.lo \ avl_tree.lo ioevent.lo ioevent_loop.lo fast_task_queue.lo \ - fast_timer.lo process_ctrl.lo fast_mblock.lo connection_pool.lo + fast_timer.lo process_ctrl.lo fast_mblock.lo \ + connection_pool.lo fast_mpool.lo FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \ logger.o sockopt.o base64.o sched_thread.o \ http_func.o md5.o pthread_func.o local_ip_func.o \ avl_tree.o ioevent.o ioevent_loop.o fast_task_queue.o \ - fast_timer.o process_ctrl.o fast_mblock.o connection_pool.o + fast_timer.o process_ctrl.o fast_mblock.o \ + connection_pool.o fast_mpool.o HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \ shared_func.h pthread_func.h ini_file_reader.h _os_bits.h \ sockopt.h sched_thread.h http_func.h md5.h local_ip_func.h \ avl_tree.h ioevent.h ioevent_loop.h fast_task_queue.h \ - fast_timer.h process_ctrl.h fast_mblock.h connection_pool.h + fast_timer.h process_ctrl.h fast_mblock.h \ + connection_pool.h fast_mpool.h ALL_OBJS = $(STATIC_OBJS) $(FAST_SHARED_OBJS) diff --git a/src/fast_mpool.c b/src/fast_mpool.c new file mode 100644 index 0000000..b101a0d --- /dev/null +++ b/src/fast_mpool.c @@ -0,0 +1,211 @@ +//fast_mpool.c + +#include +#include +#include +#include +#include "fast_mpool.h" +#include "logger.h" +#include "shared_func.h" +#include "pthread_func.h" +#include "sched_thread.h" + +int fast_mpool_init(struct fast_mpool_man *mpool, + const int alloc_size_once, const int discard_size) +{ + if (alloc_size_once > 0) + { + mpool->alloc_size_once = alloc_size_once; + } + else + { + mpool->alloc_size_once = 1024 * 1024; + } + + if (discard_size > 0) + { + mpool->discard_size = discard_size; + } + else + { + mpool->discard_size = 64; + } + + mpool->malloc_chain_head = NULL; + mpool->free_chain_head = NULL; + + return 0; +} + +static int fast_mpool_prealloc(struct fast_mpool_man *mpool, + const int alloc_size) +{ + struct fast_mpool_malloc *pMallocNode; + int bytes; + + bytes = sizeof(struct fast_mpool_malloc) + alloc_size; + pMallocNode = (struct fast_mpool_malloc *)malloc(bytes); + if (pMallocNode == NULL) + { + logError("file: "__FILE__", line: %d, " \ + "malloc %d bytes fail, " \ + "errno: %d, error info: %s", \ + __LINE__, bytes, errno, STRERROR(errno)); + return errno != 0 ? errno : ENOMEM; + } + + pMallocNode->alloc_size = alloc_size; + pMallocNode->base_ptr = (char *)(pMallocNode + 1); + pMallocNode->end_ptr = pMallocNode->base_ptr + alloc_size; + pMallocNode->free_ptr = pMallocNode->base_ptr; + + pMallocNode->free_next = mpool->free_chain_head; + mpool->free_chain_head = pMallocNode; + + pMallocNode->malloc_next = mpool->malloc_chain_head; + mpool->malloc_chain_head = pMallocNode; + + return 0; +} + +void fast_mpool_destroy(struct fast_mpool_man *mpool) +{ + struct fast_mpool_malloc *pMallocNode; + struct fast_mpool_malloc *pMallocTmp; + + if (mpool->malloc_chain_head == NULL) + { + return; + } + + pMallocNode = mpool->malloc_chain_head; + while (pMallocNode != NULL) + { + pMallocTmp = pMallocNode; + pMallocNode = pMallocNode->malloc_next; + + free(pMallocTmp); + } + mpool->malloc_chain_head = NULL; + mpool->free_chain_head = NULL; +} + +static void fast_mpool_remove_free_node(struct fast_mpool_man *mpool, + struct fast_mpool_malloc *pMallocNode) +{ + struct fast_mpool_malloc *previous; + + if (mpool->free_chain_head == pMallocNode) + { + mpool->free_chain_head = pMallocNode->free_next; + return; + } + + previous = mpool->free_chain_head; + while (previous->free_next != NULL) + { + if (previous->free_next == pMallocNode) + { + previous->free_next = pMallocNode->free_next; + return; + } + previous = previous->free_next; + } +} + +static inline void *fast_mpool_do_alloc(struct fast_mpool_man *mpool, + struct fast_mpool_malloc *pMallocNode, const int size) +{ + void *ptr; + if ((int)(pMallocNode->end_ptr - pMallocNode->free_ptr) >= size) + { + ptr = pMallocNode->free_ptr; + pMallocNode->free_ptr += size; + if ((int)(pMallocNode->end_ptr - pMallocNode->free_ptr) <= + mpool->discard_size) + { + fast_mpool_remove_free_node(mpool, pMallocNode); + } + + return ptr; + } + return NULL; +} + +void *fast_mpool_alloc(struct fast_mpool_man *mpool, const int size) +{ + struct fast_mpool_malloc *pMallocNode; + void *ptr; + int result; + int alloc_size; + + pMallocNode = mpool->free_chain_head; + while (pMallocNode != NULL) + { + if ((ptr=fast_mpool_do_alloc(mpool, pMallocNode, size)) != NULL) + { + return ptr; + } + pMallocNode = pMallocNode->free_next; + } + + if (size < mpool->alloc_size_once) + { + alloc_size = mpool->alloc_size_once; + } + else + { + alloc_size = size; + } + if ((result=fast_mpool_prealloc(mpool, alloc_size)) == 0) + { + return fast_mpool_do_alloc(mpool, mpool->free_chain_head, size); + } + + return NULL; +} + +void fast_mpool_reset(struct fast_mpool_man *mpool) +{ + struct fast_mpool_malloc *pMallocNode; + + mpool->free_chain_head = NULL; + pMallocNode = mpool->malloc_chain_head; + while (pMallocNode != NULL) + { + pMallocNode->free_ptr = pMallocNode->base_ptr; + + pMallocNode->free_next = mpool->free_chain_head; + mpool->free_chain_head = pMallocNode; + + pMallocNode = pMallocNode->malloc_next; + } +} + +void fast_mpool_stats(struct fast_mpool_man *mpool, struct fast_mpool_stats *stats) +{ + struct fast_mpool_malloc *pMallocNode; + + stats->total_bytes = 0; + stats->free_bytes = 0; + stats->total_trunk_count = 0; + stats->free_trunk_count = 0; + + pMallocNode = mpool->malloc_chain_head; + while (pMallocNode != NULL) + { + stats->total_bytes += pMallocNode->alloc_size; + stats->free_bytes += (int)(pMallocNode->end_ptr - pMallocNode->free_ptr); + stats->total_trunk_count++; + + pMallocNode = pMallocNode->malloc_next; + } + + pMallocNode = mpool->free_chain_head; + while (pMallocNode != NULL) + { + stats->free_trunk_count++; + pMallocNode = pMallocNode->free_next; + } +} + diff --git a/src/fast_mpool.h b/src/fast_mpool.h new file mode 100644 index 0000000..2f0a563 --- /dev/null +++ b/src/fast_mpool.h @@ -0,0 +1,97 @@ +/** +* Copyright (C) 2008 Happy Fish / YuQing +* +* FastDFS may be copied only under the terms of the GNU General +* Public License V3, which may be found in the FastDFS source kit. +* Please visit the FastDFS Home Page http://www.csource.org/ for more detail. +**/ + +//fast_mpool.h + +#ifndef _FAST_MPOOL_H +#define _FAST_MPOOL_H + +#include +#include +#include +#include +#include "common_define.h" + +/* malloc chain */ +struct fast_mpool_malloc +{ + int alloc_size; + char *base_ptr; + char *end_ptr; + char *free_ptr; + struct fast_mpool_malloc *malloc_next; + struct fast_mpool_malloc *free_next; +}; + +struct fast_mpool_man +{ + struct fast_mpool_malloc *malloc_chain_head; //malloc chain to be freed + struct fast_mpool_malloc *free_chain_head; //free node chain + int alloc_size_once; //alloc size once, default: 1MB + int discard_size; //discard size, default: 64 bytes +}; + +struct fast_mpool_stats +{ + int64_t total_bytes; + int64_t free_bytes; + int total_trunk_count; + int free_trunk_count; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** +mpool init +parameters: + mpool: the mpool pointer + alloc_size_once: malloc elements once, 0 for malloc 1MB memory once + discard_size: discard when remain size <= discard_size, 0 for 8 bytes +return error no, 0 for success, != 0 fail +*/ +int fast_mpool_init(struct fast_mpool_man *mpool, + const int alloc_size_once, const int discard_size); + +/** +mpool destroy +parameters: + mpool: the mpool pointer +*/ +void fast_mpool_destroy(struct fast_mpool_man *mpool); + +/** +free a node (put a node to the mpool) +parameters: + mpool: the mpool pointer + pNode: the node to free +*/ +void fast_mpool_reset(struct fast_mpool_man *mpool); + +/** +alloc a node from the mpool +parameters: + mpool: the mpool pointer +return the alloced ptr, return NULL if fail +*/ +void *fast_mpool_alloc(struct fast_mpool_man *mpool, const int size); + +/** +get stats +parameters: + mpool: the mpool pointer +*/ +void fast_mpool_stats(struct fast_mpool_man *mpool, struct fast_mpool_stats *stats); + +#ifdef __cplusplus +} +#endif + +#endif +