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