diff options
Diffstat (limited to 'libglusterfs/src/mem-pool.c')
| -rw-r--r-- | libglusterfs/src/mem-pool.c | 174 | 
1 files changed, 174 insertions, 0 deletions
diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c new file mode 100644 index 00000000000..c3646f35023 --- /dev/null +++ b/libglusterfs/src/mem-pool.c @@ -0,0 +1,174 @@ +/* +   Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> +   This file is part of GlusterFS. + +   GlusterFS is free software; you can redistribute it and/or modify +   it under the terms of the GNU General Public License as published +   by the Free Software Foundation; either version 3 of the License, +   or (at your option) any later version. + +   GlusterFS is distributed in the hope that it will be useful, but +   WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program.  If not, see +   <http://www.gnu.org/licenses/>. +*/ + +#include "mem-pool.h" +#include "logging.h" +#include <stdlib.h> + + +#define GF_MEM_POOL_PAD_BOUNDRY    16 + + +struct mem_pool * +mem_pool_new_fn (unsigned long sizeof_type, +		 unsigned long count) +{ +	struct mem_pool  *mem_pool = NULL; +	int               pad = 0; +	unsigned long     padded_sizeof_type = 0; +	void             *pool = NULL; +	int               i = 0; +	struct list_head *list = NULL; +   +	if (!sizeof_type || !count) { +		gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); +		return NULL; +	} +   +	pad = GF_MEM_POOL_PAD_BOUNDRY - +		(sizeof_type % GF_MEM_POOL_PAD_BOUNDRY); +	padded_sizeof_type = sizeof_type + pad; +   +	mem_pool = CALLOC (sizeof (*mem_pool), 1); +	if (!mem_pool) +		return NULL; + +	LOCK_INIT (&mem_pool->lock); +	INIT_LIST_HEAD (&mem_pool->list); + +	mem_pool->padded_sizeof_type = padded_sizeof_type; +	mem_pool->cold_count = count; + +	pool = CALLOC (count, sizeof_type + pad); +	if (!pool) +		return NULL; + +	for (i = 0; i < count; i++) { +		list = pool + (i * (sizeof_type + pad)); +		INIT_LIST_HEAD (list); +		list_add_tail (list, &mem_pool->list); +	} + +	mem_pool->pool = pool; +	mem_pool->pool_end = pool + (count * (sizeof_type + pad)); + +	return mem_pool; +} + + +void * +mem_get (struct mem_pool *mem_pool) +{ +	struct list_head *list = NULL; +	void             *ptr = NULL; +   +	if (!mem_pool) { +		gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); +		return NULL; +	} + +	LOCK (&mem_pool->lock); +	{ +		if (mem_pool->cold_count) { +			list = mem_pool->list.next; +			list_del (list); + +			mem_pool->hot_count++; +			mem_pool->cold_count--; + +			ptr = list; +		} +	} +	UNLOCK (&mem_pool->lock); + +	if (ptr == NULL) { +		ptr = MALLOC (mem_pool->padded_sizeof_type); + +		if (!ptr) { +			return NULL; +		} + +		LOCK (&mem_pool->lock); +		{ +			mem_pool->hot_count ++; +		} +		UNLOCK (&mem_pool->lock); +	} + +	return ptr; +} + + +static int +__is_member (struct mem_pool *pool, void *ptr) +{ +	if (!pool || !ptr) { +		gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); +		return -1; +	} +   +	if (ptr < pool->pool || ptr >= pool->pool_end) +		return 0; + +	if ((ptr - pool->pool) % pool->padded_sizeof_type) +		return -1; + +	return 1; +} + + +void +mem_put (struct mem_pool *pool, void *ptr) +{ +	struct list_head *list = NULL; +   +	if (!pool || !ptr) { +		gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); +		return; +	} +   +	list = ptr; +   +	LOCK (&pool->lock); +	{ +		pool->hot_count--; + +		switch (__is_member (pool, ptr)) +		{ +		case 1: +			pool->cold_count++; +			list_add (list, &pool->list); +			break; +		case -1: +			/* log error */ +			abort (); +			break; +		case 0: +			free (ptr); +			break; +		default: +			/* log error */ +			break; +		} +	} +	UNLOCK (&pool->lock); + +	if (ptr) +		free (ptr); +}  | 
