int free_queue_init_ex(const int max_connections, const int init_connections, const int alloc_task_once, const int min_buff_size, const int max_buff_size, const int arg_size) { #define MAX_DATA_SIZE (256 * 1024 * 1024) int64_t total_size; struct mpool_node *mpool; int alloc_size; int alloc_once; int result; int loop_count; int aligned_min_size; int aligned_max_size; int aligned_arg_size; rlim_t max_data_size; if ((result=init_pthread_lock(&(g_free_queue.lock))) != 0) { logError("file: "__FILE__", line: %d, " \ "init_pthread_lock fail, errno: %d, error info: %s", \ __LINE__, result, STRERROR(result)); return result; } aligned_min_size = MEM_ALIGN(min_buff_size); aligned_max_size = MEM_ALIGN(max_buff_size); aligned_arg_size = MEM_ALIGN(arg_size); g_free_queue.block_size = ALIGNED_TASK_INFO_SIZE + aligned_arg_size; alloc_size = g_free_queue.block_size * init_connections; if (aligned_max_size > aligned_min_size) { total_size = alloc_size; g_free_queue.malloc_whole_block = false; max_data_size = 0; } else { struct rlimit rlimit_data; if (getrlimit(RLIMIT_DATA, &rlimit_data) < 0) { logError("file: "__FILE__", line: %d, " \ "call getrlimit fail, " \ "errno: %d, error info: %s", \ __LINE__, errno, STRERROR(errno)); return errno != 0 ? errno : EPERM; } if (rlimit_data.rlim_cur == RLIM_INFINITY) { max_data_size = MAX_DATA_SIZE; } else { max_data_size = rlimit_data.rlim_cur; if (max_data_size > MAX_DATA_SIZE) { max_data_size = MAX_DATA_SIZE; } } if (max_data_size >= (int64_t)(g_free_queue.block_size + aligned_min_size) * (int64_t)init_connections) { total_size = alloc_size + (int64_t)aligned_min_size * init_connections; g_free_queue.malloc_whole_block = true; g_free_queue.block_size += aligned_min_size; } else { total_size = alloc_size; g_free_queue.malloc_whole_block = false; max_data_size = 0; } } g_free_queue.max_connections = max_connections; g_free_queue.alloc_connections = init_connections; if (alloc_task_once <= 0) { g_free_queue.alloc_task_once = 256; alloc_once = MAX_DATA_SIZE / g_free_queue.block_size; if (g_free_queue.alloc_task_once > alloc_once) { g_free_queue.alloc_task_once = alloc_once; } } else { g_free_queue.alloc_task_once = alloc_task_once; } g_free_queue.min_buff_size = aligned_min_size; g_free_queue.max_buff_size = aligned_max_size; g_free_queue.arg_size = aligned_arg_size; logDebug("file: "__FILE__", line: %d, " "max_connections: %d, init_connections: %d, alloc_task_once: %d, " "min_buff_size: %d, max_buff_size: %d, block_size: %d, " "arg_size: %d, max_data_size: %d, total_size: %"PRId64, __LINE__, max_connections, init_connections, g_free_queue.alloc_task_once, aligned_min_size, aligned_max_size, g_free_queue.block_size, aligned_arg_size, (int)max_data_size, total_size); if ((!g_free_queue.malloc_whole_block) || (total_size <= max_data_size)) { loop_count = 1; mpool = malloc_mpool(total_size); if (mpool == NULL) { return errno != 0 ? errno : ENOMEM; } g_mpool.head = mpool; g_mpool.tail = mpool; } else { int remain_count; int alloc_count; int current_alloc_size; loop_count = 0; remain_count = init_connections; alloc_once = max_data_size / g_free_queue.block_size; while (remain_count > 0) { alloc_count = (remain_count > alloc_once) ? alloc_once : remain_count; current_alloc_size = g_free_queue.block_size * alloc_count; mpool = malloc_mpool(current_alloc_size); if (mpool == NULL) { free_queue_destroy(); return errno != 0 ? errno : ENOMEM; } if (g_mpool.tail == NULL) { g_mpool.head = mpool; } else { g_mpool.tail->next = mpool; g_mpool.tail->last_block->next = mpool->blocks; //link previous mpool to current } g_mpool.tail = mpool; remain_count -= alloc_count; loop_count++; } logDebug("file: "__FILE__", line: %d, " \ "alloc_once: %d", __LINE__, alloc_once); } logDebug("file: "__FILE__", line: %d, " \ "malloc task info as whole: %d, malloc loop count: %d", \ __LINE__, g_free_queue.malloc_whole_block, loop_count); if (g_mpool.head != NULL) { g_free_queue.head = g_mpool.head->blocks; g_free_queue.tail = g_mpool.tail->last_block; } return 0; }
int free_queue_init(const int max_connections, const int min_buff_size, \ const int max_buff_size, const int arg_size) { struct fast_task_info *pTask; char *p; char *pCharEnd; int block_size; int alloc_size; int64_t total_size; int result; if ((result=init_pthread_lock(&(g_free_queue.lock))) != 0) { logError("file: "__FILE__", line: %d, " \ "init_pthread_lock fail, errno: %d, error info: %s", \ __LINE__, result, STRERROR(result)); return result; } block_size = sizeof(struct fast_task_info) + arg_size; alloc_size = block_size * max_connections; if (max_buff_size > min_buff_size) { total_size = alloc_size; g_free_queue.malloc_whole_block = false; } else { struct rlimit rlimit_data; rlim_t max_data_size; if (getrlimit(RLIMIT_DATA, &rlimit_data) < 0) { logError("file: "__FILE__", line: %d, " \ "call getrlimit fail, " \ "errno: %d, error info: %s", \ __LINE__, errno, STRERROR(errno)); return errno != 0 ? errno : EPERM; } if (rlimit_data.rlim_cur == RLIM_INFINITY) { max_data_size = 512 * 1024 * 1024; } else { max_data_size = rlimit_data.rlim_cur; if (max_data_size > 512 * 1024 * 1024) { max_data_size = 512 * 1024 * 1024; } } total_size = alloc_size+(int64_t)min_buff_size*max_connections; if (total_size <= max_data_size) { g_free_queue.malloc_whole_block = true; block_size += min_buff_size; } else { g_free_queue.malloc_whole_block = false; total_size = alloc_size; } } g_mpool = (struct fast_task_info *)malloc(total_size); if (g_mpool == NULL) { logError("file: "__FILE__", line: %d, " \ "malloc "INT64_PRINTF_FORMAT" bytes fail, " \ "errno: %d, error info: %s", \ __LINE__, total_size, errno, STRERROR(errno)); return errno != 0 ? errno : ENOMEM; } memset(g_mpool, 0, total_size); pCharEnd = ((char *)g_mpool) + total_size; for (p=(char *)g_mpool; p<pCharEnd; p += block_size) { pTask = (struct fast_task_info *)p; pTask->size = min_buff_size; pTask->arg = p + sizeof(struct fast_task_info); if (g_free_queue.malloc_whole_block) { pTask->data = (char *)pTask->arg + arg_size; } else { pTask->data = (char *)malloc(pTask->size); if (pTask->data == NULL) { free_queue_destroy(); logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail, " \ "errno: %d, error info: %s", \ __LINE__, pTask->size, \ errno, STRERROR(errno)); return errno != 0 ? errno : ENOMEM; } } } g_free_queue.tail = (struct fast_task_info *)(pCharEnd - block_size); for (p=(char *)g_mpool; p<(char *)g_free_queue.tail; p += block_size) { pTask = (struct fast_task_info *)p; pTask->next = (struct fast_task_info *)(p + block_size); } g_free_queue.max_connections = max_connections; g_free_queue.min_buff_size = min_buff_size; g_free_queue.max_buff_size = max_buff_size; g_free_queue.arg_size = arg_size; g_free_queue.head = g_mpool; g_free_queue.tail->next = NULL; return 0; }