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