Blame complib/cl_pool.c

Packit 13e616
/*
Packit 13e616
 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
Packit 13e616
 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
Packit 13e616
 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
Packit 13e616
 *
Packit 13e616
 * This software is available to you under a choice of one of two
Packit 13e616
 * licenses.  You may choose to be licensed under the terms of the GNU
Packit 13e616
 * General Public License (GPL) Version 2, available from the file
Packit 13e616
 * COPYING in the main directory of this source tree, or the
Packit 13e616
 * OpenIB.org BSD license below:
Packit 13e616
 *
Packit 13e616
 *     Redistribution and use in source and binary forms, with or
Packit 13e616
 *     without modification, are permitted provided that the following
Packit 13e616
 *     conditions are met:
Packit 13e616
 *
Packit 13e616
 *      - Redistributions of source code must retain the above
Packit 13e616
 *        copyright notice, this list of conditions and the following
Packit 13e616
 *        disclaimer.
Packit 13e616
 *
Packit 13e616
 *      - Redistributions in binary form must reproduce the above
Packit 13e616
 *        copyright notice, this list of conditions and the following
Packit 13e616
 *        disclaimer in the documentation and/or other materials
Packit 13e616
 *        provided with the distribution.
Packit 13e616
 *
Packit 13e616
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit 13e616
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit 13e616
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit 13e616
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit 13e616
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit 13e616
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit 13e616
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit 13e616
 * SOFTWARE.
Packit 13e616
 *
Packit 13e616
 */
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * Abstract:
Packit 13e616
 *	Implementation of the grow pools.  The grow pools manage a pool of objects.
Packit 13e616
 *	The pools can grow to meet demand, limited only by system memory.
Packit 13e616
 *
Packit 13e616
 */
Packit 13e616
Packit 13e616
#if HAVE_CONFIG_H
Packit 13e616
#  include <config.h>
Packit 13e616
#endif				/* HAVE_CONFIG_H */
Packit 13e616
Packit 13e616
#include <stdlib.h>
Packit 13e616
#include <string.h>
Packit 13e616
#include <complib/cl_qcomppool.h>
Packit 13e616
#include <complib/cl_comppool.h>
Packit 13e616
#include <complib/cl_qpool.h>
Packit 13e616
#include <complib/cl_pool.h>
Packit 13e616
#include <complib/cl_math.h>
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * IMPLEMENTATION OF QUICK COMPOSITE POOL
Packit 13e616
 */
Packit 13e616
void cl_qcpool_construct(IN cl_qcpool_t * const p_pool)
Packit 13e616
{
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
Packit 13e616
	memset(p_pool, 0, sizeof(cl_qcpool_t));
Packit 13e616
Packit 13e616
	p_pool->state = CL_UNINITIALIZED;
Packit 13e616
}
Packit 13e616
Packit 13e616
cl_status_t cl_qcpool_init(IN cl_qcpool_t * const p_pool,
Packit 13e616
			   IN const size_t min_size, IN const size_t max_size,
Packit 13e616
			   IN const size_t grow_size,
Packit 13e616
			   IN const size_t * const component_sizes,
Packit 13e616
			   IN const uint32_t num_components,
Packit 13e616
			   IN cl_pfn_qcpool_init_t pfn_initializer OPTIONAL,
Packit 13e616
			   IN cl_pfn_qcpool_dtor_t pfn_destructor OPTIONAL,
Packit 13e616
			   IN const void *const context)
Packit 13e616
{
Packit 13e616
	cl_status_t status;
Packit 13e616
	uint32_t i;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
	/* Must have a minimum of 1 component. */
Packit 13e616
	CL_ASSERT(num_components);
Packit 13e616
	/* A component size array is required. */
Packit 13e616
	CL_ASSERT(component_sizes);
Packit 13e616
	/*
Packit 13e616
	 * If no initializer is provided, the first component must be large
Packit 13e616
	 * enough to hold a pool item.
Packit 13e616
	 */
Packit 13e616
	CL_ASSERT(pfn_initializer ||
Packit 13e616
		  (component_sizes[0] >= sizeof(cl_pool_item_t)));
Packit 13e616
Packit 13e616
	cl_qcpool_construct(p_pool);
Packit 13e616
Packit 13e616
	if (num_components > 1 && !pfn_initializer)
Packit 13e616
		return (CL_INVALID_SETTING);
Packit 13e616
Packit 13e616
	if (max_size && max_size < min_size)
Packit 13e616
		return (CL_INVALID_SETTING);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * Allocate the array of component sizes and component pointers all
Packit 13e616
	 * in one allocation.
Packit 13e616
	 */
Packit 13e616
	p_pool->component_sizes = (size_t *) malloc((sizeof(size_t) +
Packit 13e616
						     sizeof(void *)) *
Packit 13e616
						    num_components);
Packit 13e616
Packit 13e616
	if (!p_pool->component_sizes)
Packit 13e616
		return (CL_INSUFFICIENT_MEMORY);
Packit 13e616
	else
Packit 13e616
		memset(p_pool->component_sizes, 0,
Packit 13e616
		       (sizeof(size_t) + sizeof(void *)) * num_components);
Packit 13e616
Packit 13e616
	/* Calculate the pointer to the array of pointers, used for callbacks. */
Packit 13e616
	p_pool->p_components =
Packit 13e616
	    (void **)(p_pool->component_sizes + num_components);
Packit 13e616
Packit 13e616
	/* Copy the user's sizes into our array for future use. */
Packit 13e616
	memcpy(p_pool->component_sizes, component_sizes,
Packit 13e616
	       sizeof(component_sizes[0]) * num_components);
Packit 13e616
Packit 13e616
	/* Store the number of components per object. */
Packit 13e616
	p_pool->num_components = num_components;
Packit 13e616
Packit 13e616
	/* Round up and store the size of the components. */
Packit 13e616
	for (i = 0; i < num_components; i++) {
Packit 13e616
		/*
Packit 13e616
		 * We roundup each component size so that all components
Packit 13e616
		 * are aligned on a natural boundary.
Packit 13e616
		 */
Packit 13e616
		p_pool->component_sizes[i] =
Packit 13e616
		    ROUNDUP(p_pool->component_sizes[i], sizeof(uintptr_t));
Packit 13e616
	}
Packit 13e616
Packit 13e616
	p_pool->max_objects = max_size ? max_size : ~(size_t) 0;
Packit 13e616
	p_pool->grow_size = grow_size;
Packit 13e616
Packit 13e616
	/* Store callback function pointers. */
Packit 13e616
	p_pool->pfn_init = pfn_initializer;	/* may be NULL */
Packit 13e616
	p_pool->pfn_dtor = pfn_destructor;	/* may be NULL */
Packit 13e616
	p_pool->context = context;
Packit 13e616
Packit 13e616
	cl_qlist_init(&p_pool->alloc_list);
Packit 13e616
Packit 13e616
	cl_qlist_init(&p_pool->free_list);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * We are now initialized.  We change the initialized flag before
Packit 13e616
	 * growing since the grow function asserts that we are initialized.
Packit 13e616
	 */
Packit 13e616
	p_pool->state = CL_INITIALIZED;
Packit 13e616
Packit 13e616
	/* Allocate the minimum number of objects as requested. */
Packit 13e616
	if (!min_size)
Packit 13e616
		return (CL_SUCCESS);
Packit 13e616
Packit 13e616
	status = cl_qcpool_grow(p_pool, min_size);
Packit 13e616
	/* Trap for error and cleanup if necessary. */
Packit 13e616
	if (status != CL_SUCCESS)
Packit 13e616
		cl_qcpool_destroy(p_pool);
Packit 13e616
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
void cl_qcpool_destroy(IN cl_qcpool_t * const p_pool)
Packit 13e616
{
Packit 13e616
	/* CL_ASSERT that a non-NULL pointer was provided. */
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
	/* CL_ASSERT that we are in a valid state (not uninitialized memory). */
Packit 13e616
	CL_ASSERT(cl_is_state_valid(p_pool->state));
Packit 13e616
Packit 13e616
	if (p_pool->state == CL_INITIALIZED) {
Packit 13e616
		/*
Packit 13e616
		 * Assert if the user hasn't put everything back in the pool
Packit 13e616
		 * before destroying it
Packit 13e616
		 * if they haven't, then most likely they are still using memory
Packit 13e616
		 * that will be freed, and the destructor will not be called!
Packit 13e616
		 */
Packit 13e616
#ifdef _DEBUG_
Packit 13e616
		/* but we do not want "free" version to assert on this one */
Packit 13e616
		CL_ASSERT(cl_qcpool_count(p_pool) == p_pool->num_objects);
Packit 13e616
#endif
Packit 13e616
		/* call the user's destructor for each object in the pool */
Packit 13e616
		if (p_pool->pfn_dtor) {
Packit 13e616
			while (!cl_is_qlist_empty(&p_pool->free_list)) {
Packit 13e616
				p_pool->pfn_dtor((cl_pool_item_t *)
Packit 13e616
						 cl_qlist_remove_head(&p_pool->
Packit 13e616
								      free_list),
Packit 13e616
						 (void *)p_pool->context);
Packit 13e616
			}
Packit 13e616
		} else {
Packit 13e616
			cl_qlist_remove_all(&p_pool->free_list);
Packit 13e616
		}
Packit 13e616
Packit 13e616
		/* Free all allocated memory blocks. */
Packit 13e616
		while (!cl_is_qlist_empty(&p_pool->alloc_list))
Packit 13e616
			free(cl_qlist_remove_head(&p_pool->alloc_list));
Packit 13e616
Packit 13e616
		if (p_pool->component_sizes) {
Packit 13e616
			free(p_pool->component_sizes);
Packit 13e616
			p_pool->component_sizes = NULL;
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
Packit 13e616
	p_pool->state = CL_UNINITIALIZED;
Packit 13e616
}
Packit 13e616
Packit 13e616
cl_status_t cl_qcpool_grow(IN cl_qcpool_t * const p_pool, IN size_t obj_count)
Packit 13e616
{
Packit 13e616
	cl_status_t status = CL_SUCCESS;
Packit 13e616
	uint8_t *p_objects;
Packit 13e616
	cl_pool_item_t *p_pool_item;
Packit 13e616
	uint32_t i;
Packit 13e616
	size_t obj_size;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
	CL_ASSERT(p_pool->state == CL_INITIALIZED);
Packit 13e616
	CL_ASSERT(obj_count);
Packit 13e616
Packit 13e616
	/* Validate that growth is possible. */
Packit 13e616
	if (p_pool->num_objects == p_pool->max_objects)
Packit 13e616
		return (CL_INSUFFICIENT_MEMORY);
Packit 13e616
Packit 13e616
	/* Cap the growth to the desired maximum. */
Packit 13e616
	if (obj_count > (p_pool->max_objects - p_pool->num_objects))
Packit 13e616
		obj_count = p_pool->max_objects - p_pool->num_objects;
Packit 13e616
Packit 13e616
	/* Calculate the size of an object. */
Packit 13e616
	obj_size = 0;
Packit 13e616
	for (i = 0; i < p_pool->num_components; i++)
Packit 13e616
		obj_size += p_pool->component_sizes[i];
Packit 13e616
Packit 13e616
	/* Allocate the buffer for the new objects. */
Packit 13e616
	p_objects = (uint8_t *)
Packit 13e616
	    malloc(sizeof(cl_list_item_t) + (obj_size * obj_count));
Packit 13e616
Packit 13e616
	/* Make sure the allocation succeeded. */
Packit 13e616
	if (!p_objects)
Packit 13e616
		return (CL_INSUFFICIENT_MEMORY);
Packit 13e616
	else
Packit 13e616
		memset(p_objects, 0,
Packit 13e616
		       sizeof(cl_list_item_t) + (obj_size * obj_count));
Packit 13e616
Packit 13e616
	/* Insert the allocation in our list. */
Packit 13e616
	cl_qlist_insert_tail(&p_pool->alloc_list, (cl_list_item_t *) p_objects);
Packit 13e616
	p_objects += sizeof(cl_list_item_t);
Packit 13e616
Packit 13e616
	/* initialize the new elements and add them to the free list */
Packit 13e616
	while (obj_count--) {
Packit 13e616
		/* Setup the array of components for the current object. */
Packit 13e616
		p_pool->p_components[0] = p_objects;
Packit 13e616
		for (i = 1; i < p_pool->num_components; i++) {
Packit 13e616
			/* Calculate the pointer to the next component. */
Packit 13e616
			p_pool->p_components[i] =
Packit 13e616
			    (uint8_t *) p_pool->p_components[i - 1] +
Packit 13e616
			    p_pool->component_sizes[i - 1];
Packit 13e616
		}
Packit 13e616
Packit 13e616
		/*
Packit 13e616
		 * call the user's initializer
Packit 13e616
		 * this can fail!
Packit 13e616
		 */
Packit 13e616
		if (p_pool->pfn_init) {
Packit 13e616
			p_pool_item = NULL;
Packit 13e616
			status = p_pool->pfn_init(p_pool->p_components,
Packit 13e616
						  p_pool->num_components,
Packit 13e616
						  (void *)p_pool->context,
Packit 13e616
						  &p_pool_item);
Packit 13e616
			if (status != CL_SUCCESS) {
Packit 13e616
				/*
Packit 13e616
				 * User initialization failed
Packit 13e616
				 * we may have only grown the pool by some partial amount
Packit 13e616
				 * Invoke the destructor for the object that failed
Packit 13e616
				 * initialization.
Packit 13e616
				 */
Packit 13e616
				if (p_pool->pfn_dtor)
Packit 13e616
					p_pool->pfn_dtor(p_pool_item,
Packit 13e616
							 (void *)p_pool->
Packit 13e616
							 context);
Packit 13e616
Packit 13e616
				/* Return the user's status. */
Packit 13e616
				return (status);
Packit 13e616
			}
Packit 13e616
			CL_ASSERT(p_pool_item);
Packit 13e616
		} else {
Packit 13e616
			/*
Packit 13e616
			 * If no initializer is provided, assume that the pool item
Packit 13e616
			 * is stored at the beginning of the first component.
Packit 13e616
			 */
Packit 13e616
			p_pool_item =
Packit 13e616
			    (cl_pool_item_t *) p_pool->p_components[0];
Packit 13e616
		}
Packit 13e616
Packit 13e616
#ifdef _DEBUG_
Packit 13e616
		/*
Packit 13e616
		 * Set the pool item's pool pointer to this pool so that we can
Packit 13e616
		 * check that items get returned to the correct pool.
Packit 13e616
		 */
Packit 13e616
		p_pool_item->p_pool = p_pool;
Packit 13e616
#endif
Packit 13e616
Packit 13e616
		/* Insert the new item in the free list, traping for failure. */
Packit 13e616
		cl_qlist_insert_head(&p_pool->free_list,
Packit 13e616
				     &p_pool_item->list_item);
Packit 13e616
Packit 13e616
		p_pool->num_objects++;
Packit 13e616
Packit 13e616
		/* move the pointer to the next item */
Packit 13e616
		p_objects += obj_size;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
cl_pool_item_t *cl_qcpool_get(IN cl_qcpool_t * const p_pool)
Packit 13e616
{
Packit 13e616
	cl_list_item_t *p_list_item;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
	CL_ASSERT(p_pool->state == CL_INITIALIZED);
Packit 13e616
Packit 13e616
	if (cl_is_qlist_empty(&p_pool->free_list)) {
Packit 13e616
		/*
Packit 13e616
		 * No object is available.
Packit 13e616
		 * Return NULL if the user does not want automatic growth.
Packit 13e616
		 */
Packit 13e616
		if (!p_pool->grow_size)
Packit 13e616
			return (NULL);
Packit 13e616
Packit 13e616
		/* We ran out of elements.  Get more */
Packit 13e616
		cl_qcpool_grow(p_pool, p_pool->grow_size);
Packit 13e616
		/*
Packit 13e616
		 * We may not have gotten everything we wanted but we might have
Packit 13e616
		 * gotten something.
Packit 13e616
		 */
Packit 13e616
		if (cl_is_qlist_empty(&p_pool->free_list))
Packit 13e616
			return (NULL);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	p_list_item = cl_qlist_remove_head(&p_pool->free_list);
Packit 13e616
	/* OK, at this point we have an object */
Packit 13e616
	CL_ASSERT(p_list_item != cl_qlist_end(&p_pool->free_list));
Packit 13e616
	return ((cl_pool_item_t *) p_list_item);
Packit 13e616
}
Packit 13e616
Packit 13e616
cl_pool_item_t *cl_qcpool_get_tail(IN cl_qcpool_t * const p_pool)
Packit 13e616
{
Packit 13e616
	cl_list_item_t *p_list_item;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
	CL_ASSERT(p_pool->state == CL_INITIALIZED);
Packit 13e616
Packit 13e616
	if (cl_is_qlist_empty(&p_pool->free_list)) {
Packit 13e616
		/*
Packit 13e616
		 * No object is available.
Packit 13e616
		 * Return NULL if the user does not want automatic growth.
Packit 13e616
		 */
Packit 13e616
		if (!p_pool->grow_size)
Packit 13e616
			return (NULL);
Packit 13e616
Packit 13e616
		/* We ran out of elements.  Get more */
Packit 13e616
		cl_qcpool_grow(p_pool, p_pool->grow_size);
Packit 13e616
		/*
Packit 13e616
		 * We may not have gotten everything we wanted but we might have
Packit 13e616
		 * gotten something.
Packit 13e616
		 */
Packit 13e616
		if (cl_is_qlist_empty(&p_pool->free_list))
Packit 13e616
			return (NULL);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	p_list_item = cl_qlist_remove_tail(&p_pool->free_list);
Packit 13e616
	/* OK, at this point we have an object */
Packit 13e616
	CL_ASSERT(p_list_item != cl_qlist_end(&p_pool->free_list));
Packit 13e616
	return ((cl_pool_item_t *) p_list_item);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * IMPLEMENTATION OF QUICK GROW POOL
Packit 13e616
 */
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * Callback to translate quick composite to quick grow pool
Packit 13e616
 * initializer callback.
Packit 13e616
 */
Packit 13e616
static cl_status_t __cl_qpool_init_cb(IN void **const p_comp_array,
Packit 13e616
				      IN const uint32_t num_components,
Packit 13e616
				      IN void *const context,
Packit 13e616
				      OUT cl_pool_item_t ** const pp_pool_item)
Packit 13e616
{
Packit 13e616
	cl_qpool_t *p_pool = (cl_qpool_t *) context;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
	CL_ASSERT(p_pool->pfn_init);
Packit 13e616
	CL_ASSERT(num_components == 1);
Packit 13e616
Packit 13e616
	UNUSED_PARAM(num_components);
Packit 13e616
Packit 13e616
	return (p_pool->pfn_init(p_comp_array[0], (void *)p_pool->context,
Packit 13e616
				 pp_pool_item));
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * Callback to translate quick composite to quick grow pool
Packit 13e616
 * destructor callback.
Packit 13e616
 */
Packit 13e616
static void __cl_qpool_dtor_cb(IN const cl_pool_item_t * const p_pool_item,
Packit 13e616
			       IN void *const context)
Packit 13e616
{
Packit 13e616
	cl_qpool_t *p_pool = (cl_qpool_t *) context;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
	CL_ASSERT(p_pool->pfn_dtor);
Packit 13e616
Packit 13e616
	p_pool->pfn_dtor(p_pool_item, (void *)p_pool->context);
Packit 13e616
}
Packit 13e616
Packit 13e616
void cl_qpool_construct(IN cl_qpool_t * const p_pool)
Packit 13e616
{
Packit 13e616
	memset(p_pool, 0, sizeof(cl_qpool_t));
Packit 13e616
Packit 13e616
	cl_qcpool_construct(&p_pool->qcpool);
Packit 13e616
}
Packit 13e616
Packit 13e616
cl_status_t cl_qpool_init(IN cl_qpool_t * const p_pool,
Packit 13e616
			  IN const size_t min_size, IN const size_t max_size,
Packit 13e616
			  IN const size_t grow_size,
Packit 13e616
			  IN const size_t object_size,
Packit 13e616
			  IN cl_pfn_qpool_init_t pfn_initializer OPTIONAL,
Packit 13e616
			  IN cl_pfn_qpool_dtor_t pfn_destructor OPTIONAL,
Packit 13e616
			  IN const void *const context)
Packit 13e616
{
Packit 13e616
	cl_status_t status;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
Packit 13e616
	p_pool->pfn_init = pfn_initializer;	/* may be NULL */
Packit 13e616
	p_pool->pfn_dtor = pfn_destructor;	/* may be NULL */
Packit 13e616
	p_pool->context = context;
Packit 13e616
Packit 13e616
	status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size,
Packit 13e616
				&object_size, 1,
Packit 13e616
				pfn_initializer ? __cl_qpool_init_cb : NULL,
Packit 13e616
				pfn_destructor ? __cl_qpool_dtor_cb : NULL,
Packit 13e616
				p_pool);
Packit 13e616
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * IMPLEMENTATION OF COMPOSITE POOL
Packit 13e616
 */
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * Callback to translate quick composite to compsite pool
Packit 13e616
 * initializer callback.
Packit 13e616
 */
Packit 13e616
static cl_status_t __cl_cpool_init_cb(IN void **const p_comp_array,
Packit 13e616
				      IN const uint32_t num_components,
Packit 13e616
				      IN void *const context,
Packit 13e616
				      OUT cl_pool_item_t ** const pp_pool_item)
Packit 13e616
{
Packit 13e616
	cl_cpool_t *p_pool = (cl_cpool_t *) context;
Packit 13e616
	cl_pool_obj_t *p_pool_obj;
Packit 13e616
	cl_status_t status = CL_SUCCESS;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * Set our pointer to the list item, which is stored at the beginning of
Packit 13e616
	 * the first component.
Packit 13e616
	 */
Packit 13e616
	p_pool_obj = (cl_pool_obj_t *) p_comp_array[0];
Packit 13e616
	/* Set the pool item pointer for the caller. */
Packit 13e616
	*pp_pool_item = &p_pool_obj->pool_item;
Packit 13e616
Packit 13e616
	/* Calculate the pointer to the user's first component. */
Packit 13e616
	p_comp_array[0] = ((uint8_t *) p_comp_array[0]) + sizeof(cl_pool_obj_t);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * Set the object pointer in the pool object to point to the first of the
Packit 13e616
	 * user's components.
Packit 13e616
	 */
Packit 13e616
	p_pool_obj->p_object = p_comp_array[0];
Packit 13e616
Packit 13e616
	/* Invoke the user's constructor callback. */
Packit 13e616
	if (p_pool->pfn_init) {
Packit 13e616
		status = p_pool->pfn_init(p_comp_array, num_components,
Packit 13e616
					  (void *)p_pool->context);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * Callback to translate quick composite to composite pool
Packit 13e616
 * destructor callback.
Packit 13e616
 */
Packit 13e616
static void __cl_cpool_dtor_cb(IN const cl_pool_item_t * const p_pool_item,
Packit 13e616
			       IN void *const context)
Packit 13e616
{
Packit 13e616
	cl_cpool_t *p_pool = (cl_cpool_t *) context;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
	CL_ASSERT(p_pool->pfn_dtor);
Packit 13e616
	CL_ASSERT(((cl_pool_obj_t *) p_pool_item)->p_object);
Packit 13e616
Packit 13e616
	/* Invoke the user's destructor callback. */
Packit 13e616
	p_pool->pfn_dtor((void *)((cl_pool_obj_t *) p_pool_item)->p_object,
Packit 13e616
			 (void *)p_pool->context);
Packit 13e616
}
Packit 13e616
Packit 13e616
void cl_cpool_construct(IN cl_cpool_t * const p_pool)
Packit 13e616
{
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
Packit 13e616
	memset(p_pool, 0, sizeof(cl_cpool_t));
Packit 13e616
Packit 13e616
	cl_qcpool_construct(&p_pool->qcpool);
Packit 13e616
}
Packit 13e616
Packit 13e616
cl_status_t cl_cpool_init(IN cl_cpool_t * const p_pool,
Packit 13e616
			  IN const size_t min_size, IN const size_t max_size,
Packit 13e616
			  IN const size_t grow_size,
Packit 13e616
			  IN size_t * const component_sizes,
Packit 13e616
			  IN const uint32_t num_components,
Packit 13e616
			  IN cl_pfn_cpool_init_t pfn_initializer OPTIONAL,
Packit 13e616
			  IN cl_pfn_cpool_dtor_t pfn_destructor OPTIONAL,
Packit 13e616
			  IN const void *const context)
Packit 13e616
{
Packit 13e616
	cl_status_t status;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
	CL_ASSERT(num_components);
Packit 13e616
	CL_ASSERT(component_sizes);
Packit 13e616
Packit 13e616
	/* Add the size of the pool object to the first component. */
Packit 13e616
	component_sizes[0] += sizeof(cl_pool_obj_t);
Packit 13e616
Packit 13e616
	/* Store callback function pointers. */
Packit 13e616
	p_pool->pfn_init = pfn_initializer;	/* may be NULL */
Packit 13e616
	p_pool->pfn_dtor = pfn_destructor;	/* may be NULL */
Packit 13e616
	p_pool->context = context;
Packit 13e616
Packit 13e616
	status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size,
Packit 13e616
				component_sizes, num_components,
Packit 13e616
				__cl_cpool_init_cb,
Packit 13e616
				pfn_destructor ? __cl_cpool_dtor_cb : NULL,
Packit 13e616
				p_pool);
Packit 13e616
Packit 13e616
	/* Restore the original value of the first component. */
Packit 13e616
	component_sizes[0] -= sizeof(cl_pool_obj_t);
Packit 13e616
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * IMPLEMENTATION OF GROW POOL
Packit 13e616
 */
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * Callback to translate quick composite to grow pool constructor callback.
Packit 13e616
 */
Packit 13e616
static cl_status_t __cl_pool_init_cb(IN void **const pp_obj,
Packit 13e616
				     IN const uint32_t count,
Packit 13e616
				     IN void *const context,
Packit 13e616
				     OUT cl_pool_item_t ** const pp_pool_item)
Packit 13e616
{
Packit 13e616
	cl_pool_t *p_pool = (cl_pool_t *) context;
Packit 13e616
	cl_pool_obj_t *p_pool_obj;
Packit 13e616
	cl_status_t status = CL_SUCCESS;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
	CL_ASSERT(pp_obj);
Packit 13e616
	CL_ASSERT(count == 1);
Packit 13e616
Packit 13e616
	UNUSED_PARAM(count);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * Set our pointer to the list item, which is stored at the beginning of
Packit 13e616
	 * the first component.
Packit 13e616
	 */
Packit 13e616
	p_pool_obj = (cl_pool_obj_t *) * pp_obj;
Packit 13e616
	*pp_pool_item = &p_pool_obj->pool_item;
Packit 13e616
Packit 13e616
	/* Calculate the pointer to the user's first component. */
Packit 13e616
	*pp_obj = ((uint8_t *) * pp_obj) + sizeof(cl_pool_obj_t);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * Set the object pointer in the pool item to point to the first of the
Packit 13e616
	 * user's components.
Packit 13e616
	 */
Packit 13e616
	p_pool_obj->p_object = *pp_obj;
Packit 13e616
Packit 13e616
	/* Invoke the user's constructor callback. */
Packit 13e616
	if (p_pool->pfn_init)
Packit 13e616
		status = p_pool->pfn_init(*pp_obj, (void *)p_pool->context);
Packit 13e616
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * Callback to translate quick composite to grow pool destructor callback.
Packit 13e616
 */
Packit 13e616
static void __cl_pool_dtor_cb(IN const cl_pool_item_t * const p_pool_item,
Packit 13e616
			      IN void *const context)
Packit 13e616
{
Packit 13e616
	cl_pool_t *p_pool = (cl_pool_t *) context;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
	CL_ASSERT(p_pool->pfn_dtor);
Packit 13e616
	CL_ASSERT(((cl_pool_obj_t *) p_pool_item)->p_object);
Packit 13e616
Packit 13e616
	/* Invoke the user's destructor callback. */
Packit 13e616
	p_pool->pfn_dtor((void *)((cl_pool_obj_t *) p_pool_item)->p_object,
Packit 13e616
			 (void *)p_pool->context);
Packit 13e616
}
Packit 13e616
Packit 13e616
void cl_pool_construct(IN cl_pool_t * const p_pool)
Packit 13e616
{
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
Packit 13e616
	memset(p_pool, 0, sizeof(cl_pool_t));
Packit 13e616
Packit 13e616
	cl_qcpool_construct(&p_pool->qcpool);
Packit 13e616
}
Packit 13e616
Packit 13e616
cl_status_t cl_pool_init(IN cl_pool_t * const p_pool, IN const size_t min_size,
Packit 13e616
			 IN const size_t max_size, IN const size_t grow_size,
Packit 13e616
			 IN const size_t object_size,
Packit 13e616
			 IN cl_pfn_pool_init_t pfn_initializer OPTIONAL,
Packit 13e616
			 IN cl_pfn_pool_dtor_t pfn_destructor OPTIONAL,
Packit 13e616
			 IN const void *const context)
Packit 13e616
{
Packit 13e616
	cl_status_t status;
Packit 13e616
	size_t total_size;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_pool);
Packit 13e616
Packit 13e616
	/* Add the size of the list item to the first component. */
Packit 13e616
	total_size = object_size + sizeof(cl_pool_obj_t);
Packit 13e616
Packit 13e616
	/* Store callback function pointers. */
Packit 13e616
	p_pool->pfn_init = pfn_initializer;	/* may be NULL */
Packit 13e616
	p_pool->pfn_dtor = pfn_destructor;	/* may be NULL */
Packit 13e616
	p_pool->context = context;
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * We need an initializer in all cases for quick composite pool, since
Packit 13e616
	 * the user pointer must be manipulated to hide the prefixed cl_pool_obj_t.
Packit 13e616
	 */
Packit 13e616
	status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size,
Packit 13e616
				&total_size, 1, __cl_pool_init_cb,
Packit 13e616
				pfn_destructor ? __cl_pool_dtor_cb : NULL,
Packit 13e616
				p_pool);
Packit 13e616
Packit 13e616
	return (status);
Packit 13e616
}