xref: /freebsd/contrib/ofed/opensm/complib/cl_pool.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3*d6b92ffaSHans Petter Selasky  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4*d6b92ffaSHans Petter Selasky  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5*d6b92ffaSHans Petter Selasky  *
6*d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
7*d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
8*d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
9*d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
10*d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
11*d6b92ffaSHans Petter Selasky  *
12*d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
13*d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
14*d6b92ffaSHans Petter Selasky  *     conditions are met:
15*d6b92ffaSHans Petter Selasky  *
16*d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
17*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
18*d6b92ffaSHans Petter Selasky  *        disclaimer.
19*d6b92ffaSHans Petter Selasky  *
20*d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
21*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
22*d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
23*d6b92ffaSHans Petter Selasky  *        provided with the distribution.
24*d6b92ffaSHans Petter Selasky  *
25*d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26*d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27*d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28*d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29*d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30*d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31*d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32*d6b92ffaSHans Petter Selasky  * SOFTWARE.
33*d6b92ffaSHans Petter Selasky  *
34*d6b92ffaSHans Petter Selasky  */
35*d6b92ffaSHans Petter Selasky 
36*d6b92ffaSHans Petter Selasky /*
37*d6b92ffaSHans Petter Selasky  * Abstract:
38*d6b92ffaSHans Petter Selasky  *	Implementation of the grow pools.  The grow pools manage a pool of objects.
39*d6b92ffaSHans Petter Selasky  *	The pools can grow to meet demand, limited only by system memory.
40*d6b92ffaSHans Petter Selasky  *
41*d6b92ffaSHans Petter Selasky  */
42*d6b92ffaSHans Petter Selasky 
43*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
44*d6b92ffaSHans Petter Selasky #  include <config.h>
45*d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
46*d6b92ffaSHans Petter Selasky 
47*d6b92ffaSHans Petter Selasky #include <stdlib.h>
48*d6b92ffaSHans Petter Selasky #include <string.h>
49*d6b92ffaSHans Petter Selasky #include <complib/cl_qcomppool.h>
50*d6b92ffaSHans Petter Selasky #include <complib/cl_comppool.h>
51*d6b92ffaSHans Petter Selasky #include <complib/cl_qpool.h>
52*d6b92ffaSHans Petter Selasky #include <complib/cl_pool.h>
53*d6b92ffaSHans Petter Selasky #include <complib/cl_math.h>
54*d6b92ffaSHans Petter Selasky 
55*d6b92ffaSHans Petter Selasky /*
56*d6b92ffaSHans Petter Selasky  * IMPLEMENTATION OF QUICK COMPOSITE POOL
57*d6b92ffaSHans Petter Selasky  */
cl_qcpool_construct(IN cl_qcpool_t * const p_pool)58*d6b92ffaSHans Petter Selasky void cl_qcpool_construct(IN cl_qcpool_t * const p_pool)
59*d6b92ffaSHans Petter Selasky {
60*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
61*d6b92ffaSHans Petter Selasky 
62*d6b92ffaSHans Petter Selasky 	memset(p_pool, 0, sizeof(cl_qcpool_t));
63*d6b92ffaSHans Petter Selasky 
64*d6b92ffaSHans Petter Selasky 	p_pool->state = CL_UNINITIALIZED;
65*d6b92ffaSHans Petter Selasky }
66*d6b92ffaSHans Petter Selasky 
cl_qcpool_init(IN cl_qcpool_t * const p_pool,IN const size_t min_size,IN const size_t max_size,IN const size_t grow_size,IN const size_t * const component_sizes,IN const uint32_t num_components,IN cl_pfn_qcpool_init_t pfn_initializer OPTIONAL,IN cl_pfn_qcpool_dtor_t pfn_destructor OPTIONAL,IN const void * const context)67*d6b92ffaSHans Petter Selasky cl_status_t cl_qcpool_init(IN cl_qcpool_t * const p_pool,
68*d6b92ffaSHans Petter Selasky 			   IN const size_t min_size, IN const size_t max_size,
69*d6b92ffaSHans Petter Selasky 			   IN const size_t grow_size,
70*d6b92ffaSHans Petter Selasky 			   IN const size_t * const component_sizes,
71*d6b92ffaSHans Petter Selasky 			   IN const uint32_t num_components,
72*d6b92ffaSHans Petter Selasky 			   IN cl_pfn_qcpool_init_t pfn_initializer OPTIONAL,
73*d6b92ffaSHans Petter Selasky 			   IN cl_pfn_qcpool_dtor_t pfn_destructor OPTIONAL,
74*d6b92ffaSHans Petter Selasky 			   IN const void *const context)
75*d6b92ffaSHans Petter Selasky {
76*d6b92ffaSHans Petter Selasky 	cl_status_t status;
77*d6b92ffaSHans Petter Selasky 	uint32_t i;
78*d6b92ffaSHans Petter Selasky 
79*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
80*d6b92ffaSHans Petter Selasky 	/* Must have a minimum of 1 component. */
81*d6b92ffaSHans Petter Selasky 	CL_ASSERT(num_components);
82*d6b92ffaSHans Petter Selasky 	/* A component size array is required. */
83*d6b92ffaSHans Petter Selasky 	CL_ASSERT(component_sizes);
84*d6b92ffaSHans Petter Selasky 	/*
85*d6b92ffaSHans Petter Selasky 	 * If no initializer is provided, the first component must be large
86*d6b92ffaSHans Petter Selasky 	 * enough to hold a pool item.
87*d6b92ffaSHans Petter Selasky 	 */
88*d6b92ffaSHans Petter Selasky 	CL_ASSERT(pfn_initializer ||
89*d6b92ffaSHans Petter Selasky 		  (component_sizes[0] >= sizeof(cl_pool_item_t)));
90*d6b92ffaSHans Petter Selasky 
91*d6b92ffaSHans Petter Selasky 	cl_qcpool_construct(p_pool);
92*d6b92ffaSHans Petter Selasky 
93*d6b92ffaSHans Petter Selasky 	if (num_components > 1 && !pfn_initializer)
94*d6b92ffaSHans Petter Selasky 		return (CL_INVALID_SETTING);
95*d6b92ffaSHans Petter Selasky 
96*d6b92ffaSHans Petter Selasky 	if (max_size && max_size < min_size)
97*d6b92ffaSHans Petter Selasky 		return (CL_INVALID_SETTING);
98*d6b92ffaSHans Petter Selasky 
99*d6b92ffaSHans Petter Selasky 	/*
100*d6b92ffaSHans Petter Selasky 	 * Allocate the array of component sizes and component pointers all
101*d6b92ffaSHans Petter Selasky 	 * in one allocation.
102*d6b92ffaSHans Petter Selasky 	 */
103*d6b92ffaSHans Petter Selasky 	p_pool->component_sizes = (size_t *) malloc((sizeof(size_t) +
104*d6b92ffaSHans Petter Selasky 						     sizeof(void *)) *
105*d6b92ffaSHans Petter Selasky 						    num_components);
106*d6b92ffaSHans Petter Selasky 
107*d6b92ffaSHans Petter Selasky 	if (!p_pool->component_sizes)
108*d6b92ffaSHans Petter Selasky 		return (CL_INSUFFICIENT_MEMORY);
109*d6b92ffaSHans Petter Selasky 	else
110*d6b92ffaSHans Petter Selasky 		memset(p_pool->component_sizes, 0,
111*d6b92ffaSHans Petter Selasky 		       (sizeof(size_t) + sizeof(void *)) * num_components);
112*d6b92ffaSHans Petter Selasky 
113*d6b92ffaSHans Petter Selasky 	/* Calculate the pointer to the array of pointers, used for callbacks. */
114*d6b92ffaSHans Petter Selasky 	p_pool->p_components =
115*d6b92ffaSHans Petter Selasky 	    (void **)(p_pool->component_sizes + num_components);
116*d6b92ffaSHans Petter Selasky 
117*d6b92ffaSHans Petter Selasky 	/* Copy the user's sizes into our array for future use. */
118*d6b92ffaSHans Petter Selasky 	memcpy(p_pool->component_sizes, component_sizes,
119*d6b92ffaSHans Petter Selasky 	       sizeof(component_sizes[0]) * num_components);
120*d6b92ffaSHans Petter Selasky 
121*d6b92ffaSHans Petter Selasky 	/* Store the number of components per object. */
122*d6b92ffaSHans Petter Selasky 	p_pool->num_components = num_components;
123*d6b92ffaSHans Petter Selasky 
124*d6b92ffaSHans Petter Selasky 	/* Round up and store the size of the components. */
125*d6b92ffaSHans Petter Selasky 	for (i = 0; i < num_components; i++) {
126*d6b92ffaSHans Petter Selasky 		/*
127*d6b92ffaSHans Petter Selasky 		 * We roundup each component size so that all components
128*d6b92ffaSHans Petter Selasky 		 * are aligned on a natural boundary.
129*d6b92ffaSHans Petter Selasky 		 */
130*d6b92ffaSHans Petter Selasky 		p_pool->component_sizes[i] =
131*d6b92ffaSHans Petter Selasky 		    ROUNDUP(p_pool->component_sizes[i], sizeof(uintptr_t));
132*d6b92ffaSHans Petter Selasky 	}
133*d6b92ffaSHans Petter Selasky 
134*d6b92ffaSHans Petter Selasky 	p_pool->max_objects = max_size ? max_size : ~(size_t) 0;
135*d6b92ffaSHans Petter Selasky 	p_pool->grow_size = grow_size;
136*d6b92ffaSHans Petter Selasky 
137*d6b92ffaSHans Petter Selasky 	/* Store callback function pointers. */
138*d6b92ffaSHans Petter Selasky 	p_pool->pfn_init = pfn_initializer;	/* may be NULL */
139*d6b92ffaSHans Petter Selasky 	p_pool->pfn_dtor = pfn_destructor;	/* may be NULL */
140*d6b92ffaSHans Petter Selasky 	p_pool->context = context;
141*d6b92ffaSHans Petter Selasky 
142*d6b92ffaSHans Petter Selasky 	cl_qlist_init(&p_pool->alloc_list);
143*d6b92ffaSHans Petter Selasky 
144*d6b92ffaSHans Petter Selasky 	cl_qlist_init(&p_pool->free_list);
145*d6b92ffaSHans Petter Selasky 
146*d6b92ffaSHans Petter Selasky 	/*
147*d6b92ffaSHans Petter Selasky 	 * We are now initialized.  We change the initialized flag before
148*d6b92ffaSHans Petter Selasky 	 * growing since the grow function asserts that we are initialized.
149*d6b92ffaSHans Petter Selasky 	 */
150*d6b92ffaSHans Petter Selasky 	p_pool->state = CL_INITIALIZED;
151*d6b92ffaSHans Petter Selasky 
152*d6b92ffaSHans Petter Selasky 	/* Allocate the minimum number of objects as requested. */
153*d6b92ffaSHans Petter Selasky 	if (!min_size)
154*d6b92ffaSHans Petter Selasky 		return (CL_SUCCESS);
155*d6b92ffaSHans Petter Selasky 
156*d6b92ffaSHans Petter Selasky 	status = cl_qcpool_grow(p_pool, min_size);
157*d6b92ffaSHans Petter Selasky 	/* Trap for error and cleanup if necessary. */
158*d6b92ffaSHans Petter Selasky 	if (status != CL_SUCCESS)
159*d6b92ffaSHans Petter Selasky 		cl_qcpool_destroy(p_pool);
160*d6b92ffaSHans Petter Selasky 
161*d6b92ffaSHans Petter Selasky 	return (status);
162*d6b92ffaSHans Petter Selasky }
163*d6b92ffaSHans Petter Selasky 
cl_qcpool_destroy(IN cl_qcpool_t * const p_pool)164*d6b92ffaSHans Petter Selasky void cl_qcpool_destroy(IN cl_qcpool_t * const p_pool)
165*d6b92ffaSHans Petter Selasky {
166*d6b92ffaSHans Petter Selasky 	/* CL_ASSERT that a non-NULL pointer was provided. */
167*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
168*d6b92ffaSHans Petter Selasky 	/* CL_ASSERT that we are in a valid state (not uninitialized memory). */
169*d6b92ffaSHans Petter Selasky 	CL_ASSERT(cl_is_state_valid(p_pool->state));
170*d6b92ffaSHans Petter Selasky 
171*d6b92ffaSHans Petter Selasky 	if (p_pool->state == CL_INITIALIZED) {
172*d6b92ffaSHans Petter Selasky 		/*
173*d6b92ffaSHans Petter Selasky 		 * Assert if the user hasn't put everything back in the pool
174*d6b92ffaSHans Petter Selasky 		 * before destroying it
175*d6b92ffaSHans Petter Selasky 		 * if they haven't, then most likely they are still using memory
176*d6b92ffaSHans Petter Selasky 		 * that will be freed, and the destructor will not be called!
177*d6b92ffaSHans Petter Selasky 		 */
178*d6b92ffaSHans Petter Selasky #ifdef _DEBUG_
179*d6b92ffaSHans Petter Selasky 		/* but we do not want "free" version to assert on this one */
180*d6b92ffaSHans Petter Selasky 		CL_ASSERT(cl_qcpool_count(p_pool) == p_pool->num_objects);
181*d6b92ffaSHans Petter Selasky #endif
182*d6b92ffaSHans Petter Selasky 		/* call the user's destructor for each object in the pool */
183*d6b92ffaSHans Petter Selasky 		if (p_pool->pfn_dtor) {
184*d6b92ffaSHans Petter Selasky 			while (!cl_is_qlist_empty(&p_pool->free_list)) {
185*d6b92ffaSHans Petter Selasky 				p_pool->pfn_dtor((cl_pool_item_t *)
186*d6b92ffaSHans Petter Selasky 						 cl_qlist_remove_head(&p_pool->
187*d6b92ffaSHans Petter Selasky 								      free_list),
188*d6b92ffaSHans Petter Selasky 						 (void *)p_pool->context);
189*d6b92ffaSHans Petter Selasky 			}
190*d6b92ffaSHans Petter Selasky 		} else {
191*d6b92ffaSHans Petter Selasky 			cl_qlist_remove_all(&p_pool->free_list);
192*d6b92ffaSHans Petter Selasky 		}
193*d6b92ffaSHans Petter Selasky 
194*d6b92ffaSHans Petter Selasky 		/* Free all allocated memory blocks. */
195*d6b92ffaSHans Petter Selasky 		while (!cl_is_qlist_empty(&p_pool->alloc_list))
196*d6b92ffaSHans Petter Selasky 			free(cl_qlist_remove_head(&p_pool->alloc_list));
197*d6b92ffaSHans Petter Selasky 
198*d6b92ffaSHans Petter Selasky 		if (p_pool->component_sizes) {
199*d6b92ffaSHans Petter Selasky 			free(p_pool->component_sizes);
200*d6b92ffaSHans Petter Selasky 			p_pool->component_sizes = NULL;
201*d6b92ffaSHans Petter Selasky 		}
202*d6b92ffaSHans Petter Selasky 	}
203*d6b92ffaSHans Petter Selasky 
204*d6b92ffaSHans Petter Selasky 	p_pool->state = CL_UNINITIALIZED;
205*d6b92ffaSHans Petter Selasky }
206*d6b92ffaSHans Petter Selasky 
cl_qcpool_grow(IN cl_qcpool_t * const p_pool,IN size_t obj_count)207*d6b92ffaSHans Petter Selasky cl_status_t cl_qcpool_grow(IN cl_qcpool_t * const p_pool, IN size_t obj_count)
208*d6b92ffaSHans Petter Selasky {
209*d6b92ffaSHans Petter Selasky 	cl_status_t status = CL_SUCCESS;
210*d6b92ffaSHans Petter Selasky 	uint8_t *p_objects;
211*d6b92ffaSHans Petter Selasky 	cl_pool_item_t *p_pool_item;
212*d6b92ffaSHans Petter Selasky 	uint32_t i;
213*d6b92ffaSHans Petter Selasky 	size_t obj_size;
214*d6b92ffaSHans Petter Selasky 
215*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
216*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool->state == CL_INITIALIZED);
217*d6b92ffaSHans Petter Selasky 	CL_ASSERT(obj_count);
218*d6b92ffaSHans Petter Selasky 
219*d6b92ffaSHans Petter Selasky 	/* Validate that growth is possible. */
220*d6b92ffaSHans Petter Selasky 	if (p_pool->num_objects == p_pool->max_objects)
221*d6b92ffaSHans Petter Selasky 		return (CL_INSUFFICIENT_MEMORY);
222*d6b92ffaSHans Petter Selasky 
223*d6b92ffaSHans Petter Selasky 	/* Cap the growth to the desired maximum. */
224*d6b92ffaSHans Petter Selasky 	if (obj_count > (p_pool->max_objects - p_pool->num_objects))
225*d6b92ffaSHans Petter Selasky 		obj_count = p_pool->max_objects - p_pool->num_objects;
226*d6b92ffaSHans Petter Selasky 
227*d6b92ffaSHans Petter Selasky 	/* Calculate the size of an object. */
228*d6b92ffaSHans Petter Selasky 	obj_size = 0;
229*d6b92ffaSHans Petter Selasky 	for (i = 0; i < p_pool->num_components; i++)
230*d6b92ffaSHans Petter Selasky 		obj_size += p_pool->component_sizes[i];
231*d6b92ffaSHans Petter Selasky 
232*d6b92ffaSHans Petter Selasky 	/* Allocate the buffer for the new objects. */
233*d6b92ffaSHans Petter Selasky 	p_objects = (uint8_t *)
234*d6b92ffaSHans Petter Selasky 	    malloc(sizeof(cl_list_item_t) + (obj_size * obj_count));
235*d6b92ffaSHans Petter Selasky 
236*d6b92ffaSHans Petter Selasky 	/* Make sure the allocation succeeded. */
237*d6b92ffaSHans Petter Selasky 	if (!p_objects)
238*d6b92ffaSHans Petter Selasky 		return (CL_INSUFFICIENT_MEMORY);
239*d6b92ffaSHans Petter Selasky 	else
240*d6b92ffaSHans Petter Selasky 		memset(p_objects, 0,
241*d6b92ffaSHans Petter Selasky 		       sizeof(cl_list_item_t) + (obj_size * obj_count));
242*d6b92ffaSHans Petter Selasky 
243*d6b92ffaSHans Petter Selasky 	/* Insert the allocation in our list. */
244*d6b92ffaSHans Petter Selasky 	cl_qlist_insert_tail(&p_pool->alloc_list, (cl_list_item_t *) p_objects);
245*d6b92ffaSHans Petter Selasky 	p_objects += sizeof(cl_list_item_t);
246*d6b92ffaSHans Petter Selasky 
247*d6b92ffaSHans Petter Selasky 	/* initialize the new elements and add them to the free list */
248*d6b92ffaSHans Petter Selasky 	while (obj_count--) {
249*d6b92ffaSHans Petter Selasky 		/* Setup the array of components for the current object. */
250*d6b92ffaSHans Petter Selasky 		p_pool->p_components[0] = p_objects;
251*d6b92ffaSHans Petter Selasky 		for (i = 1; i < p_pool->num_components; i++) {
252*d6b92ffaSHans Petter Selasky 			/* Calculate the pointer to the next component. */
253*d6b92ffaSHans Petter Selasky 			p_pool->p_components[i] =
254*d6b92ffaSHans Petter Selasky 			    (uint8_t *) p_pool->p_components[i - 1] +
255*d6b92ffaSHans Petter Selasky 			    p_pool->component_sizes[i - 1];
256*d6b92ffaSHans Petter Selasky 		}
257*d6b92ffaSHans Petter Selasky 
258*d6b92ffaSHans Petter Selasky 		/*
259*d6b92ffaSHans Petter Selasky 		 * call the user's initializer
260*d6b92ffaSHans Petter Selasky 		 * this can fail!
261*d6b92ffaSHans Petter Selasky 		 */
262*d6b92ffaSHans Petter Selasky 		if (p_pool->pfn_init) {
263*d6b92ffaSHans Petter Selasky 			p_pool_item = NULL;
264*d6b92ffaSHans Petter Selasky 			status = p_pool->pfn_init(p_pool->p_components,
265*d6b92ffaSHans Petter Selasky 						  p_pool->num_components,
266*d6b92ffaSHans Petter Selasky 						  (void *)p_pool->context,
267*d6b92ffaSHans Petter Selasky 						  &p_pool_item);
268*d6b92ffaSHans Petter Selasky 			if (status != CL_SUCCESS) {
269*d6b92ffaSHans Petter Selasky 				/*
270*d6b92ffaSHans Petter Selasky 				 * User initialization failed
271*d6b92ffaSHans Petter Selasky 				 * we may have only grown the pool by some partial amount
272*d6b92ffaSHans Petter Selasky 				 * Invoke the destructor for the object that failed
273*d6b92ffaSHans Petter Selasky 				 * initialization.
274*d6b92ffaSHans Petter Selasky 				 */
275*d6b92ffaSHans Petter Selasky 				if (p_pool->pfn_dtor)
276*d6b92ffaSHans Petter Selasky 					p_pool->pfn_dtor(p_pool_item,
277*d6b92ffaSHans Petter Selasky 							 (void *)p_pool->
278*d6b92ffaSHans Petter Selasky 							 context);
279*d6b92ffaSHans Petter Selasky 
280*d6b92ffaSHans Petter Selasky 				/* Return the user's status. */
281*d6b92ffaSHans Petter Selasky 				return (status);
282*d6b92ffaSHans Petter Selasky 			}
283*d6b92ffaSHans Petter Selasky 			CL_ASSERT(p_pool_item);
284*d6b92ffaSHans Petter Selasky 		} else {
285*d6b92ffaSHans Petter Selasky 			/*
286*d6b92ffaSHans Petter Selasky 			 * If no initializer is provided, assume that the pool item
287*d6b92ffaSHans Petter Selasky 			 * is stored at the beginning of the first component.
288*d6b92ffaSHans Petter Selasky 			 */
289*d6b92ffaSHans Petter Selasky 			p_pool_item =
290*d6b92ffaSHans Petter Selasky 			    (cl_pool_item_t *) p_pool->p_components[0];
291*d6b92ffaSHans Petter Selasky 		}
292*d6b92ffaSHans Petter Selasky 
293*d6b92ffaSHans Petter Selasky #ifdef _DEBUG_
294*d6b92ffaSHans Petter Selasky 		/*
295*d6b92ffaSHans Petter Selasky 		 * Set the pool item's pool pointer to this pool so that we can
296*d6b92ffaSHans Petter Selasky 		 * check that items get returned to the correct pool.
297*d6b92ffaSHans Petter Selasky 		 */
298*d6b92ffaSHans Petter Selasky 		p_pool_item->p_pool = p_pool;
299*d6b92ffaSHans Petter Selasky #endif
300*d6b92ffaSHans Petter Selasky 
301*d6b92ffaSHans Petter Selasky 		/* Insert the new item in the free list, traping for failure. */
302*d6b92ffaSHans Petter Selasky 		cl_qlist_insert_head(&p_pool->free_list,
303*d6b92ffaSHans Petter Selasky 				     &p_pool_item->list_item);
304*d6b92ffaSHans Petter Selasky 
305*d6b92ffaSHans Petter Selasky 		p_pool->num_objects++;
306*d6b92ffaSHans Petter Selasky 
307*d6b92ffaSHans Petter Selasky 		/* move the pointer to the next item */
308*d6b92ffaSHans Petter Selasky 		p_objects += obj_size;
309*d6b92ffaSHans Petter Selasky 	}
310*d6b92ffaSHans Petter Selasky 
311*d6b92ffaSHans Petter Selasky 	return (status);
312*d6b92ffaSHans Petter Selasky }
313*d6b92ffaSHans Petter Selasky 
cl_qcpool_get(IN cl_qcpool_t * const p_pool)314*d6b92ffaSHans Petter Selasky cl_pool_item_t *cl_qcpool_get(IN cl_qcpool_t * const p_pool)
315*d6b92ffaSHans Petter Selasky {
316*d6b92ffaSHans Petter Selasky 	cl_list_item_t *p_list_item;
317*d6b92ffaSHans Petter Selasky 
318*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
319*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool->state == CL_INITIALIZED);
320*d6b92ffaSHans Petter Selasky 
321*d6b92ffaSHans Petter Selasky 	if (cl_is_qlist_empty(&p_pool->free_list)) {
322*d6b92ffaSHans Petter Selasky 		/*
323*d6b92ffaSHans Petter Selasky 		 * No object is available.
324*d6b92ffaSHans Petter Selasky 		 * Return NULL if the user does not want automatic growth.
325*d6b92ffaSHans Petter Selasky 		 */
326*d6b92ffaSHans Petter Selasky 		if (!p_pool->grow_size)
327*d6b92ffaSHans Petter Selasky 			return (NULL);
328*d6b92ffaSHans Petter Selasky 
329*d6b92ffaSHans Petter Selasky 		/* We ran out of elements.  Get more */
330*d6b92ffaSHans Petter Selasky 		cl_qcpool_grow(p_pool, p_pool->grow_size);
331*d6b92ffaSHans Petter Selasky 		/*
332*d6b92ffaSHans Petter Selasky 		 * We may not have gotten everything we wanted but we might have
333*d6b92ffaSHans Petter Selasky 		 * gotten something.
334*d6b92ffaSHans Petter Selasky 		 */
335*d6b92ffaSHans Petter Selasky 		if (cl_is_qlist_empty(&p_pool->free_list))
336*d6b92ffaSHans Petter Selasky 			return (NULL);
337*d6b92ffaSHans Petter Selasky 	}
338*d6b92ffaSHans Petter Selasky 
339*d6b92ffaSHans Petter Selasky 	p_list_item = cl_qlist_remove_head(&p_pool->free_list);
340*d6b92ffaSHans Petter Selasky 	/* OK, at this point we have an object */
341*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list_item != cl_qlist_end(&p_pool->free_list));
342*d6b92ffaSHans Petter Selasky 	return ((cl_pool_item_t *) p_list_item);
343*d6b92ffaSHans Petter Selasky }
344*d6b92ffaSHans Petter Selasky 
cl_qcpool_get_tail(IN cl_qcpool_t * const p_pool)345*d6b92ffaSHans Petter Selasky cl_pool_item_t *cl_qcpool_get_tail(IN cl_qcpool_t * const p_pool)
346*d6b92ffaSHans Petter Selasky {
347*d6b92ffaSHans Petter Selasky 	cl_list_item_t *p_list_item;
348*d6b92ffaSHans Petter Selasky 
349*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
350*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool->state == CL_INITIALIZED);
351*d6b92ffaSHans Petter Selasky 
352*d6b92ffaSHans Petter Selasky 	if (cl_is_qlist_empty(&p_pool->free_list)) {
353*d6b92ffaSHans Petter Selasky 		/*
354*d6b92ffaSHans Petter Selasky 		 * No object is available.
355*d6b92ffaSHans Petter Selasky 		 * Return NULL if the user does not want automatic growth.
356*d6b92ffaSHans Petter Selasky 		 */
357*d6b92ffaSHans Petter Selasky 		if (!p_pool->grow_size)
358*d6b92ffaSHans Petter Selasky 			return (NULL);
359*d6b92ffaSHans Petter Selasky 
360*d6b92ffaSHans Petter Selasky 		/* We ran out of elements.  Get more */
361*d6b92ffaSHans Petter Selasky 		cl_qcpool_grow(p_pool, p_pool->grow_size);
362*d6b92ffaSHans Petter Selasky 		/*
363*d6b92ffaSHans Petter Selasky 		 * We may not have gotten everything we wanted but we might have
364*d6b92ffaSHans Petter Selasky 		 * gotten something.
365*d6b92ffaSHans Petter Selasky 		 */
366*d6b92ffaSHans Petter Selasky 		if (cl_is_qlist_empty(&p_pool->free_list))
367*d6b92ffaSHans Petter Selasky 			return (NULL);
368*d6b92ffaSHans Petter Selasky 	}
369*d6b92ffaSHans Petter Selasky 
370*d6b92ffaSHans Petter Selasky 	p_list_item = cl_qlist_remove_tail(&p_pool->free_list);
371*d6b92ffaSHans Petter Selasky 	/* OK, at this point we have an object */
372*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list_item != cl_qlist_end(&p_pool->free_list));
373*d6b92ffaSHans Petter Selasky 	return ((cl_pool_item_t *) p_list_item);
374*d6b92ffaSHans Petter Selasky }
375*d6b92ffaSHans Petter Selasky 
376*d6b92ffaSHans Petter Selasky /*
377*d6b92ffaSHans Petter Selasky  * IMPLEMENTATION OF QUICK GROW POOL
378*d6b92ffaSHans Petter Selasky  */
379*d6b92ffaSHans Petter Selasky 
380*d6b92ffaSHans Petter Selasky /*
381*d6b92ffaSHans Petter Selasky  * Callback to translate quick composite to quick grow pool
382*d6b92ffaSHans Petter Selasky  * initializer callback.
383*d6b92ffaSHans Petter Selasky  */
__cl_qpool_init_cb(IN void ** const p_comp_array,IN const uint32_t num_components,IN void * const context,OUT cl_pool_item_t ** const pp_pool_item)384*d6b92ffaSHans Petter Selasky static cl_status_t __cl_qpool_init_cb(IN void **const p_comp_array,
385*d6b92ffaSHans Petter Selasky 				      IN const uint32_t num_components,
386*d6b92ffaSHans Petter Selasky 				      IN void *const context,
387*d6b92ffaSHans Petter Selasky 				      OUT cl_pool_item_t ** const pp_pool_item)
388*d6b92ffaSHans Petter Selasky {
389*d6b92ffaSHans Petter Selasky 	cl_qpool_t *p_pool = (cl_qpool_t *) context;
390*d6b92ffaSHans Petter Selasky 
391*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
392*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool->pfn_init);
393*d6b92ffaSHans Petter Selasky 	CL_ASSERT(num_components == 1);
394*d6b92ffaSHans Petter Selasky 
395*d6b92ffaSHans Petter Selasky 	UNUSED_PARAM(num_components);
396*d6b92ffaSHans Petter Selasky 
397*d6b92ffaSHans Petter Selasky 	return (p_pool->pfn_init(p_comp_array[0], (void *)p_pool->context,
398*d6b92ffaSHans Petter Selasky 				 pp_pool_item));
399*d6b92ffaSHans Petter Selasky }
400*d6b92ffaSHans Petter Selasky 
401*d6b92ffaSHans Petter Selasky /*
402*d6b92ffaSHans Petter Selasky  * Callback to translate quick composite to quick grow pool
403*d6b92ffaSHans Petter Selasky  * destructor callback.
404*d6b92ffaSHans Petter Selasky  */
__cl_qpool_dtor_cb(IN const cl_pool_item_t * const p_pool_item,IN void * const context)405*d6b92ffaSHans Petter Selasky static void __cl_qpool_dtor_cb(IN const cl_pool_item_t * const p_pool_item,
406*d6b92ffaSHans Petter Selasky 			       IN void *const context)
407*d6b92ffaSHans Petter Selasky {
408*d6b92ffaSHans Petter Selasky 	cl_qpool_t *p_pool = (cl_qpool_t *) context;
409*d6b92ffaSHans Petter Selasky 
410*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
411*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool->pfn_dtor);
412*d6b92ffaSHans Petter Selasky 
413*d6b92ffaSHans Petter Selasky 	p_pool->pfn_dtor(p_pool_item, (void *)p_pool->context);
414*d6b92ffaSHans Petter Selasky }
415*d6b92ffaSHans Petter Selasky 
cl_qpool_construct(IN cl_qpool_t * const p_pool)416*d6b92ffaSHans Petter Selasky void cl_qpool_construct(IN cl_qpool_t * const p_pool)
417*d6b92ffaSHans Petter Selasky {
418*d6b92ffaSHans Petter Selasky 	memset(p_pool, 0, sizeof(cl_qpool_t));
419*d6b92ffaSHans Petter Selasky 
420*d6b92ffaSHans Petter Selasky 	cl_qcpool_construct(&p_pool->qcpool);
421*d6b92ffaSHans Petter Selasky }
422*d6b92ffaSHans Petter Selasky 
cl_qpool_init(IN cl_qpool_t * const p_pool,IN const size_t min_size,IN const size_t max_size,IN const size_t grow_size,IN const size_t object_size,IN cl_pfn_qpool_init_t pfn_initializer OPTIONAL,IN cl_pfn_qpool_dtor_t pfn_destructor OPTIONAL,IN const void * const context)423*d6b92ffaSHans Petter Selasky cl_status_t cl_qpool_init(IN cl_qpool_t * const p_pool,
424*d6b92ffaSHans Petter Selasky 			  IN const size_t min_size, IN const size_t max_size,
425*d6b92ffaSHans Petter Selasky 			  IN const size_t grow_size,
426*d6b92ffaSHans Petter Selasky 			  IN const size_t object_size,
427*d6b92ffaSHans Petter Selasky 			  IN cl_pfn_qpool_init_t pfn_initializer OPTIONAL,
428*d6b92ffaSHans Petter Selasky 			  IN cl_pfn_qpool_dtor_t pfn_destructor OPTIONAL,
429*d6b92ffaSHans Petter Selasky 			  IN const void *const context)
430*d6b92ffaSHans Petter Selasky {
431*d6b92ffaSHans Petter Selasky 	cl_status_t status;
432*d6b92ffaSHans Petter Selasky 
433*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
434*d6b92ffaSHans Petter Selasky 
435*d6b92ffaSHans Petter Selasky 	p_pool->pfn_init = pfn_initializer;	/* may be NULL */
436*d6b92ffaSHans Petter Selasky 	p_pool->pfn_dtor = pfn_destructor;	/* may be NULL */
437*d6b92ffaSHans Petter Selasky 	p_pool->context = context;
438*d6b92ffaSHans Petter Selasky 
439*d6b92ffaSHans Petter Selasky 	status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size,
440*d6b92ffaSHans Petter Selasky 				&object_size, 1,
441*d6b92ffaSHans Petter Selasky 				pfn_initializer ? __cl_qpool_init_cb : NULL,
442*d6b92ffaSHans Petter Selasky 				pfn_destructor ? __cl_qpool_dtor_cb : NULL,
443*d6b92ffaSHans Petter Selasky 				p_pool);
444*d6b92ffaSHans Petter Selasky 
445*d6b92ffaSHans Petter Selasky 	return (status);
446*d6b92ffaSHans Petter Selasky }
447*d6b92ffaSHans Petter Selasky 
448*d6b92ffaSHans Petter Selasky /*
449*d6b92ffaSHans Petter Selasky  * IMPLEMENTATION OF COMPOSITE POOL
450*d6b92ffaSHans Petter Selasky  */
451*d6b92ffaSHans Petter Selasky 
452*d6b92ffaSHans Petter Selasky /*
453*d6b92ffaSHans Petter Selasky  * Callback to translate quick composite to compsite pool
454*d6b92ffaSHans Petter Selasky  * initializer callback.
455*d6b92ffaSHans Petter Selasky  */
__cl_cpool_init_cb(IN void ** const p_comp_array,IN const uint32_t num_components,IN void * const context,OUT cl_pool_item_t ** const pp_pool_item)456*d6b92ffaSHans Petter Selasky static cl_status_t __cl_cpool_init_cb(IN void **const p_comp_array,
457*d6b92ffaSHans Petter Selasky 				      IN const uint32_t num_components,
458*d6b92ffaSHans Petter Selasky 				      IN void *const context,
459*d6b92ffaSHans Petter Selasky 				      OUT cl_pool_item_t ** const pp_pool_item)
460*d6b92ffaSHans Petter Selasky {
461*d6b92ffaSHans Petter Selasky 	cl_cpool_t *p_pool = (cl_cpool_t *) context;
462*d6b92ffaSHans Petter Selasky 	cl_pool_obj_t *p_pool_obj;
463*d6b92ffaSHans Petter Selasky 	cl_status_t status = CL_SUCCESS;
464*d6b92ffaSHans Petter Selasky 
465*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
466*d6b92ffaSHans Petter Selasky 
467*d6b92ffaSHans Petter Selasky 	/*
468*d6b92ffaSHans Petter Selasky 	 * Set our pointer to the list item, which is stored at the beginning of
469*d6b92ffaSHans Petter Selasky 	 * the first component.
470*d6b92ffaSHans Petter Selasky 	 */
471*d6b92ffaSHans Petter Selasky 	p_pool_obj = (cl_pool_obj_t *) p_comp_array[0];
472*d6b92ffaSHans Petter Selasky 	/* Set the pool item pointer for the caller. */
473*d6b92ffaSHans Petter Selasky 	*pp_pool_item = &p_pool_obj->pool_item;
474*d6b92ffaSHans Petter Selasky 
475*d6b92ffaSHans Petter Selasky 	/* Calculate the pointer to the user's first component. */
476*d6b92ffaSHans Petter Selasky 	p_comp_array[0] = ((uint8_t *) p_comp_array[0]) + sizeof(cl_pool_obj_t);
477*d6b92ffaSHans Petter Selasky 
478*d6b92ffaSHans Petter Selasky 	/*
479*d6b92ffaSHans Petter Selasky 	 * Set the object pointer in the pool object to point to the first of the
480*d6b92ffaSHans Petter Selasky 	 * user's components.
481*d6b92ffaSHans Petter Selasky 	 */
482*d6b92ffaSHans Petter Selasky 	p_pool_obj->p_object = p_comp_array[0];
483*d6b92ffaSHans Petter Selasky 
484*d6b92ffaSHans Petter Selasky 	/* Invoke the user's constructor callback. */
485*d6b92ffaSHans Petter Selasky 	if (p_pool->pfn_init) {
486*d6b92ffaSHans Petter Selasky 		status = p_pool->pfn_init(p_comp_array, num_components,
487*d6b92ffaSHans Petter Selasky 					  (void *)p_pool->context);
488*d6b92ffaSHans Petter Selasky 	}
489*d6b92ffaSHans Petter Selasky 
490*d6b92ffaSHans Petter Selasky 	return (status);
491*d6b92ffaSHans Petter Selasky }
492*d6b92ffaSHans Petter Selasky 
493*d6b92ffaSHans Petter Selasky /*
494*d6b92ffaSHans Petter Selasky  * Callback to translate quick composite to composite pool
495*d6b92ffaSHans Petter Selasky  * destructor callback.
496*d6b92ffaSHans Petter Selasky  */
__cl_cpool_dtor_cb(IN const cl_pool_item_t * const p_pool_item,IN void * const context)497*d6b92ffaSHans Petter Selasky static void __cl_cpool_dtor_cb(IN const cl_pool_item_t * const p_pool_item,
498*d6b92ffaSHans Petter Selasky 			       IN void *const context)
499*d6b92ffaSHans Petter Selasky {
500*d6b92ffaSHans Petter Selasky 	cl_cpool_t *p_pool = (cl_cpool_t *) context;
501*d6b92ffaSHans Petter Selasky 
502*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
503*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool->pfn_dtor);
504*d6b92ffaSHans Petter Selasky 	CL_ASSERT(((cl_pool_obj_t *) p_pool_item)->p_object);
505*d6b92ffaSHans Petter Selasky 
506*d6b92ffaSHans Petter Selasky 	/* Invoke the user's destructor callback. */
507*d6b92ffaSHans Petter Selasky 	p_pool->pfn_dtor((void *)((cl_pool_obj_t *) p_pool_item)->p_object,
508*d6b92ffaSHans Petter Selasky 			 (void *)p_pool->context);
509*d6b92ffaSHans Petter Selasky }
510*d6b92ffaSHans Petter Selasky 
cl_cpool_construct(IN cl_cpool_t * const p_pool)511*d6b92ffaSHans Petter Selasky void cl_cpool_construct(IN cl_cpool_t * const p_pool)
512*d6b92ffaSHans Petter Selasky {
513*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
514*d6b92ffaSHans Petter Selasky 
515*d6b92ffaSHans Petter Selasky 	memset(p_pool, 0, sizeof(cl_cpool_t));
516*d6b92ffaSHans Petter Selasky 
517*d6b92ffaSHans Petter Selasky 	cl_qcpool_construct(&p_pool->qcpool);
518*d6b92ffaSHans Petter Selasky }
519*d6b92ffaSHans Petter Selasky 
cl_cpool_init(IN cl_cpool_t * const p_pool,IN const size_t min_size,IN const size_t max_size,IN const size_t grow_size,IN size_t * const component_sizes,IN const uint32_t num_components,IN cl_pfn_cpool_init_t pfn_initializer OPTIONAL,IN cl_pfn_cpool_dtor_t pfn_destructor OPTIONAL,IN const void * const context)520*d6b92ffaSHans Petter Selasky cl_status_t cl_cpool_init(IN cl_cpool_t * const p_pool,
521*d6b92ffaSHans Petter Selasky 			  IN const size_t min_size, IN const size_t max_size,
522*d6b92ffaSHans Petter Selasky 			  IN const size_t grow_size,
523*d6b92ffaSHans Petter Selasky 			  IN size_t * const component_sizes,
524*d6b92ffaSHans Petter Selasky 			  IN const uint32_t num_components,
525*d6b92ffaSHans Petter Selasky 			  IN cl_pfn_cpool_init_t pfn_initializer OPTIONAL,
526*d6b92ffaSHans Petter Selasky 			  IN cl_pfn_cpool_dtor_t pfn_destructor OPTIONAL,
527*d6b92ffaSHans Petter Selasky 			  IN const void *const context)
528*d6b92ffaSHans Petter Selasky {
529*d6b92ffaSHans Petter Selasky 	cl_status_t status;
530*d6b92ffaSHans Petter Selasky 
531*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
532*d6b92ffaSHans Petter Selasky 	CL_ASSERT(num_components);
533*d6b92ffaSHans Petter Selasky 	CL_ASSERT(component_sizes);
534*d6b92ffaSHans Petter Selasky 
535*d6b92ffaSHans Petter Selasky 	/* Add the size of the pool object to the first component. */
536*d6b92ffaSHans Petter Selasky 	component_sizes[0] += sizeof(cl_pool_obj_t);
537*d6b92ffaSHans Petter Selasky 
538*d6b92ffaSHans Petter Selasky 	/* Store callback function pointers. */
539*d6b92ffaSHans Petter Selasky 	p_pool->pfn_init = pfn_initializer;	/* may be NULL */
540*d6b92ffaSHans Petter Selasky 	p_pool->pfn_dtor = pfn_destructor;	/* may be NULL */
541*d6b92ffaSHans Petter Selasky 	p_pool->context = context;
542*d6b92ffaSHans Petter Selasky 
543*d6b92ffaSHans Petter Selasky 	status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size,
544*d6b92ffaSHans Petter Selasky 				component_sizes, num_components,
545*d6b92ffaSHans Petter Selasky 				__cl_cpool_init_cb,
546*d6b92ffaSHans Petter Selasky 				pfn_destructor ? __cl_cpool_dtor_cb : NULL,
547*d6b92ffaSHans Petter Selasky 				p_pool);
548*d6b92ffaSHans Petter Selasky 
549*d6b92ffaSHans Petter Selasky 	/* Restore the original value of the first component. */
550*d6b92ffaSHans Petter Selasky 	component_sizes[0] -= sizeof(cl_pool_obj_t);
551*d6b92ffaSHans Petter Selasky 
552*d6b92ffaSHans Petter Selasky 	return (status);
553*d6b92ffaSHans Petter Selasky }
554*d6b92ffaSHans Petter Selasky 
555*d6b92ffaSHans Petter Selasky /*
556*d6b92ffaSHans Petter Selasky  * IMPLEMENTATION OF GROW POOL
557*d6b92ffaSHans Petter Selasky  */
558*d6b92ffaSHans Petter Selasky 
559*d6b92ffaSHans Petter Selasky /*
560*d6b92ffaSHans Petter Selasky  * Callback to translate quick composite to grow pool constructor callback.
561*d6b92ffaSHans Petter Selasky  */
__cl_pool_init_cb(IN void ** const pp_obj,IN const uint32_t count,IN void * const context,OUT cl_pool_item_t ** const pp_pool_item)562*d6b92ffaSHans Petter Selasky static cl_status_t __cl_pool_init_cb(IN void **const pp_obj,
563*d6b92ffaSHans Petter Selasky 				     IN const uint32_t count,
564*d6b92ffaSHans Petter Selasky 				     IN void *const context,
565*d6b92ffaSHans Petter Selasky 				     OUT cl_pool_item_t ** const pp_pool_item)
566*d6b92ffaSHans Petter Selasky {
567*d6b92ffaSHans Petter Selasky 	cl_pool_t *p_pool = (cl_pool_t *) context;
568*d6b92ffaSHans Petter Selasky 	cl_pool_obj_t *p_pool_obj;
569*d6b92ffaSHans Petter Selasky 	cl_status_t status = CL_SUCCESS;
570*d6b92ffaSHans Petter Selasky 
571*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
572*d6b92ffaSHans Petter Selasky 	CL_ASSERT(pp_obj);
573*d6b92ffaSHans Petter Selasky 	CL_ASSERT(count == 1);
574*d6b92ffaSHans Petter Selasky 
575*d6b92ffaSHans Petter Selasky 	UNUSED_PARAM(count);
576*d6b92ffaSHans Petter Selasky 
577*d6b92ffaSHans Petter Selasky 	/*
578*d6b92ffaSHans Petter Selasky 	 * Set our pointer to the list item, which is stored at the beginning of
579*d6b92ffaSHans Petter Selasky 	 * the first component.
580*d6b92ffaSHans Petter Selasky 	 */
581*d6b92ffaSHans Petter Selasky 	p_pool_obj = (cl_pool_obj_t *) * pp_obj;
582*d6b92ffaSHans Petter Selasky 	*pp_pool_item = &p_pool_obj->pool_item;
583*d6b92ffaSHans Petter Selasky 
584*d6b92ffaSHans Petter Selasky 	/* Calculate the pointer to the user's first component. */
585*d6b92ffaSHans Petter Selasky 	*pp_obj = ((uint8_t *) * pp_obj) + sizeof(cl_pool_obj_t);
586*d6b92ffaSHans Petter Selasky 
587*d6b92ffaSHans Petter Selasky 	/*
588*d6b92ffaSHans Petter Selasky 	 * Set the object pointer in the pool item to point to the first of the
589*d6b92ffaSHans Petter Selasky 	 * user's components.
590*d6b92ffaSHans Petter Selasky 	 */
591*d6b92ffaSHans Petter Selasky 	p_pool_obj->p_object = *pp_obj;
592*d6b92ffaSHans Petter Selasky 
593*d6b92ffaSHans Petter Selasky 	/* Invoke the user's constructor callback. */
594*d6b92ffaSHans Petter Selasky 	if (p_pool->pfn_init)
595*d6b92ffaSHans Petter Selasky 		status = p_pool->pfn_init(*pp_obj, (void *)p_pool->context);
596*d6b92ffaSHans Petter Selasky 
597*d6b92ffaSHans Petter Selasky 	return (status);
598*d6b92ffaSHans Petter Selasky }
599*d6b92ffaSHans Petter Selasky 
600*d6b92ffaSHans Petter Selasky /*
601*d6b92ffaSHans Petter Selasky  * Callback to translate quick composite to grow pool destructor callback.
602*d6b92ffaSHans Petter Selasky  */
__cl_pool_dtor_cb(IN const cl_pool_item_t * const p_pool_item,IN void * const context)603*d6b92ffaSHans Petter Selasky static void __cl_pool_dtor_cb(IN const cl_pool_item_t * const p_pool_item,
604*d6b92ffaSHans Petter Selasky 			      IN void *const context)
605*d6b92ffaSHans Petter Selasky {
606*d6b92ffaSHans Petter Selasky 	cl_pool_t *p_pool = (cl_pool_t *) context;
607*d6b92ffaSHans Petter Selasky 
608*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
609*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool->pfn_dtor);
610*d6b92ffaSHans Petter Selasky 	CL_ASSERT(((cl_pool_obj_t *) p_pool_item)->p_object);
611*d6b92ffaSHans Petter Selasky 
612*d6b92ffaSHans Petter Selasky 	/* Invoke the user's destructor callback. */
613*d6b92ffaSHans Petter Selasky 	p_pool->pfn_dtor((void *)((cl_pool_obj_t *) p_pool_item)->p_object,
614*d6b92ffaSHans Petter Selasky 			 (void *)p_pool->context);
615*d6b92ffaSHans Petter Selasky }
616*d6b92ffaSHans Petter Selasky 
cl_pool_construct(IN cl_pool_t * const p_pool)617*d6b92ffaSHans Petter Selasky void cl_pool_construct(IN cl_pool_t * const p_pool)
618*d6b92ffaSHans Petter Selasky {
619*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
620*d6b92ffaSHans Petter Selasky 
621*d6b92ffaSHans Petter Selasky 	memset(p_pool, 0, sizeof(cl_pool_t));
622*d6b92ffaSHans Petter Selasky 
623*d6b92ffaSHans Petter Selasky 	cl_qcpool_construct(&p_pool->qcpool);
624*d6b92ffaSHans Petter Selasky }
625*d6b92ffaSHans Petter Selasky 
cl_pool_init(IN cl_pool_t * const p_pool,IN const size_t min_size,IN const size_t max_size,IN const size_t grow_size,IN const size_t object_size,IN cl_pfn_pool_init_t pfn_initializer OPTIONAL,IN cl_pfn_pool_dtor_t pfn_destructor OPTIONAL,IN const void * const context)626*d6b92ffaSHans Petter Selasky cl_status_t cl_pool_init(IN cl_pool_t * const p_pool, IN const size_t min_size,
627*d6b92ffaSHans Petter Selasky 			 IN const size_t max_size, IN const size_t grow_size,
628*d6b92ffaSHans Petter Selasky 			 IN const size_t object_size,
629*d6b92ffaSHans Petter Selasky 			 IN cl_pfn_pool_init_t pfn_initializer OPTIONAL,
630*d6b92ffaSHans Petter Selasky 			 IN cl_pfn_pool_dtor_t pfn_destructor OPTIONAL,
631*d6b92ffaSHans Petter Selasky 			 IN const void *const context)
632*d6b92ffaSHans Petter Selasky {
633*d6b92ffaSHans Petter Selasky 	cl_status_t status;
634*d6b92ffaSHans Petter Selasky 	size_t total_size;
635*d6b92ffaSHans Petter Selasky 
636*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_pool);
637*d6b92ffaSHans Petter Selasky 
638*d6b92ffaSHans Petter Selasky 	/* Add the size of the list item to the first component. */
639*d6b92ffaSHans Petter Selasky 	total_size = object_size + sizeof(cl_pool_obj_t);
640*d6b92ffaSHans Petter Selasky 
641*d6b92ffaSHans Petter Selasky 	/* Store callback function pointers. */
642*d6b92ffaSHans Petter Selasky 	p_pool->pfn_init = pfn_initializer;	/* may be NULL */
643*d6b92ffaSHans Petter Selasky 	p_pool->pfn_dtor = pfn_destructor;	/* may be NULL */
644*d6b92ffaSHans Petter Selasky 	p_pool->context = context;
645*d6b92ffaSHans Petter Selasky 
646*d6b92ffaSHans Petter Selasky 	/*
647*d6b92ffaSHans Petter Selasky 	 * We need an initializer in all cases for quick composite pool, since
648*d6b92ffaSHans Petter Selasky 	 * the user pointer must be manipulated to hide the prefixed cl_pool_obj_t.
649*d6b92ffaSHans Petter Selasky 	 */
650*d6b92ffaSHans Petter Selasky 	status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size,
651*d6b92ffaSHans Petter Selasky 				&total_size, 1, __cl_pool_init_cb,
652*d6b92ffaSHans Petter Selasky 				pfn_destructor ? __cl_pool_dtor_cb : NULL,
653*d6b92ffaSHans Petter Selasky 				p_pool);
654*d6b92ffaSHans Petter Selasky 
655*d6b92ffaSHans Petter Selasky 	return (status);
656*d6b92ffaSHans Petter Selasky }
657