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;
}
예제 #2
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;
}