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