1321936Shselasky/* 2321936Shselasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. 3321936Shselasky * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4321936Shselasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5321936Shselasky * 6321936Shselasky * This software is available to you under a choice of one of two 7321936Shselasky * licenses. You may choose to be licensed under the terms of the GNU 8321936Shselasky * General Public License (GPL) Version 2, available from the file 9321936Shselasky * COPYING in the main directory of this source tree, or the 10321936Shselasky * OpenIB.org BSD license below: 11321936Shselasky * 12321936Shselasky * Redistribution and use in source and binary forms, with or 13321936Shselasky * without modification, are permitted provided that the following 14321936Shselasky * conditions are met: 15321936Shselasky * 16321936Shselasky * - Redistributions of source code must retain the above 17321936Shselasky * copyright notice, this list of conditions and the following 18321936Shselasky * disclaimer. 19321936Shselasky * 20321936Shselasky * - Redistributions in binary form must reproduce the above 21321936Shselasky * copyright notice, this list of conditions and the following 22321936Shselasky * disclaimer in the documentation and/or other materials 23321936Shselasky * provided with the distribution. 24321936Shselasky * 25321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32321936Shselasky * SOFTWARE. 33321936Shselasky * 34321936Shselasky */ 35321936Shselasky 36321936Shselasky/* 37321936Shselasky * Abstract: 38321936Shselasky * Implementation of the grow pools. The grow pools manage a pool of objects. 39321936Shselasky * The pools can grow to meet demand, limited only by system memory. 40321936Shselasky * 41321936Shselasky */ 42321936Shselasky 43321936Shselasky#if HAVE_CONFIG_H 44321936Shselasky# include <config.h> 45321936Shselasky#endif /* HAVE_CONFIG_H */ 46321936Shselasky 47321936Shselasky#include <stdlib.h> 48321936Shselasky#include <string.h> 49321936Shselasky#include <complib/cl_qcomppool.h> 50321936Shselasky#include <complib/cl_comppool.h> 51321936Shselasky#include <complib/cl_qpool.h> 52321936Shselasky#include <complib/cl_pool.h> 53321936Shselasky#include <complib/cl_math.h> 54321936Shselasky 55321936Shselasky/* 56321936Shselasky * IMPLEMENTATION OF QUICK COMPOSITE POOL 57321936Shselasky */ 58321936Shselaskyvoid cl_qcpool_construct(IN cl_qcpool_t * const p_pool) 59321936Shselasky{ 60321936Shselasky CL_ASSERT(p_pool); 61321936Shselasky 62321936Shselasky memset(p_pool, 0, sizeof(cl_qcpool_t)); 63321936Shselasky 64321936Shselasky p_pool->state = CL_UNINITIALIZED; 65321936Shselasky} 66321936Shselasky 67321936Shselaskycl_status_t cl_qcpool_init(IN cl_qcpool_t * const p_pool, 68321936Shselasky IN const size_t min_size, IN const size_t max_size, 69321936Shselasky IN const size_t grow_size, 70321936Shselasky IN const size_t * const component_sizes, 71321936Shselasky IN const uint32_t num_components, 72321936Shselasky IN cl_pfn_qcpool_init_t pfn_initializer OPTIONAL, 73321936Shselasky IN cl_pfn_qcpool_dtor_t pfn_destructor OPTIONAL, 74321936Shselasky IN const void *const context) 75321936Shselasky{ 76321936Shselasky cl_status_t status; 77321936Shselasky uint32_t i; 78321936Shselasky 79321936Shselasky CL_ASSERT(p_pool); 80321936Shselasky /* Must have a minimum of 1 component. */ 81321936Shselasky CL_ASSERT(num_components); 82321936Shselasky /* A component size array is required. */ 83321936Shselasky CL_ASSERT(component_sizes); 84321936Shselasky /* 85321936Shselasky * If no initializer is provided, the first component must be large 86321936Shselasky * enough to hold a pool item. 87321936Shselasky */ 88321936Shselasky CL_ASSERT(pfn_initializer || 89321936Shselasky (component_sizes[0] >= sizeof(cl_pool_item_t))); 90321936Shselasky 91321936Shselasky cl_qcpool_construct(p_pool); 92321936Shselasky 93321936Shselasky if (num_components > 1 && !pfn_initializer) 94321936Shselasky return (CL_INVALID_SETTING); 95321936Shselasky 96321936Shselasky if (max_size && max_size < min_size) 97321936Shselasky return (CL_INVALID_SETTING); 98321936Shselasky 99321936Shselasky /* 100321936Shselasky * Allocate the array of component sizes and component pointers all 101321936Shselasky * in one allocation. 102321936Shselasky */ 103321936Shselasky p_pool->component_sizes = (size_t *) malloc((sizeof(size_t) + 104321936Shselasky sizeof(void *)) * 105321936Shselasky num_components); 106321936Shselasky 107321936Shselasky if (!p_pool->component_sizes) 108321936Shselasky return (CL_INSUFFICIENT_MEMORY); 109321936Shselasky else 110321936Shselasky memset(p_pool->component_sizes, 0, 111321936Shselasky (sizeof(size_t) + sizeof(void *)) * num_components); 112321936Shselasky 113321936Shselasky /* Calculate the pointer to the array of pointers, used for callbacks. */ 114321936Shselasky p_pool->p_components = 115321936Shselasky (void **)(p_pool->component_sizes + num_components); 116321936Shselasky 117321936Shselasky /* Copy the user's sizes into our array for future use. */ 118321936Shselasky memcpy(p_pool->component_sizes, component_sizes, 119321936Shselasky sizeof(component_sizes[0]) * num_components); 120321936Shselasky 121321936Shselasky /* Store the number of components per object. */ 122321936Shselasky p_pool->num_components = num_components; 123321936Shselasky 124321936Shselasky /* Round up and store the size of the components. */ 125321936Shselasky for (i = 0; i < num_components; i++) { 126321936Shselasky /* 127321936Shselasky * We roundup each component size so that all components 128321936Shselasky * are aligned on a natural boundary. 129321936Shselasky */ 130321936Shselasky p_pool->component_sizes[i] = 131321936Shselasky ROUNDUP(p_pool->component_sizes[i], sizeof(uintptr_t)); 132321936Shselasky } 133321936Shselasky 134321936Shselasky p_pool->max_objects = max_size ? max_size : ~(size_t) 0; 135321936Shselasky p_pool->grow_size = grow_size; 136321936Shselasky 137321936Shselasky /* Store callback function pointers. */ 138321936Shselasky p_pool->pfn_init = pfn_initializer; /* may be NULL */ 139321936Shselasky p_pool->pfn_dtor = pfn_destructor; /* may be NULL */ 140321936Shselasky p_pool->context = context; 141321936Shselasky 142321936Shselasky cl_qlist_init(&p_pool->alloc_list); 143321936Shselasky 144321936Shselasky cl_qlist_init(&p_pool->free_list); 145321936Shselasky 146321936Shselasky /* 147321936Shselasky * We are now initialized. We change the initialized flag before 148321936Shselasky * growing since the grow function asserts that we are initialized. 149321936Shselasky */ 150321936Shselasky p_pool->state = CL_INITIALIZED; 151321936Shselasky 152321936Shselasky /* Allocate the minimum number of objects as requested. */ 153321936Shselasky if (!min_size) 154321936Shselasky return (CL_SUCCESS); 155321936Shselasky 156321936Shselasky status = cl_qcpool_grow(p_pool, min_size); 157321936Shselasky /* Trap for error and cleanup if necessary. */ 158321936Shselasky if (status != CL_SUCCESS) 159321936Shselasky cl_qcpool_destroy(p_pool); 160321936Shselasky 161321936Shselasky return (status); 162321936Shselasky} 163321936Shselasky 164321936Shselaskyvoid cl_qcpool_destroy(IN cl_qcpool_t * const p_pool) 165321936Shselasky{ 166321936Shselasky /* CL_ASSERT that a non-NULL pointer was provided. */ 167321936Shselasky CL_ASSERT(p_pool); 168321936Shselasky /* CL_ASSERT that we are in a valid state (not uninitialized memory). */ 169321936Shselasky CL_ASSERT(cl_is_state_valid(p_pool->state)); 170321936Shselasky 171321936Shselasky if (p_pool->state == CL_INITIALIZED) { 172321936Shselasky /* 173321936Shselasky * Assert if the user hasn't put everything back in the pool 174321936Shselasky * before destroying it 175321936Shselasky * if they haven't, then most likely they are still using memory 176321936Shselasky * that will be freed, and the destructor will not be called! 177321936Shselasky */ 178321936Shselasky#ifdef _DEBUG_ 179321936Shselasky /* but we do not want "free" version to assert on this one */ 180321936Shselasky CL_ASSERT(cl_qcpool_count(p_pool) == p_pool->num_objects); 181321936Shselasky#endif 182321936Shselasky /* call the user's destructor for each object in the pool */ 183321936Shselasky if (p_pool->pfn_dtor) { 184321936Shselasky while (!cl_is_qlist_empty(&p_pool->free_list)) { 185321936Shselasky p_pool->pfn_dtor((cl_pool_item_t *) 186321936Shselasky cl_qlist_remove_head(&p_pool-> 187321936Shselasky free_list), 188321936Shselasky (void *)p_pool->context); 189321936Shselasky } 190321936Shselasky } else { 191321936Shselasky cl_qlist_remove_all(&p_pool->free_list); 192321936Shselasky } 193321936Shselasky 194321936Shselasky /* Free all allocated memory blocks. */ 195321936Shselasky while (!cl_is_qlist_empty(&p_pool->alloc_list)) 196321936Shselasky free(cl_qlist_remove_head(&p_pool->alloc_list)); 197321936Shselasky 198321936Shselasky if (p_pool->component_sizes) { 199321936Shselasky free(p_pool->component_sizes); 200321936Shselasky p_pool->component_sizes = NULL; 201321936Shselasky } 202321936Shselasky } 203321936Shselasky 204321936Shselasky p_pool->state = CL_UNINITIALIZED; 205321936Shselasky} 206321936Shselasky 207321936Shselaskycl_status_t cl_qcpool_grow(IN cl_qcpool_t * const p_pool, IN size_t obj_count) 208321936Shselasky{ 209321936Shselasky cl_status_t status = CL_SUCCESS; 210321936Shselasky uint8_t *p_objects; 211321936Shselasky cl_pool_item_t *p_pool_item; 212321936Shselasky uint32_t i; 213321936Shselasky size_t obj_size; 214321936Shselasky 215321936Shselasky CL_ASSERT(p_pool); 216321936Shselasky CL_ASSERT(p_pool->state == CL_INITIALIZED); 217321936Shselasky CL_ASSERT(obj_count); 218321936Shselasky 219321936Shselasky /* Validate that growth is possible. */ 220321936Shselasky if (p_pool->num_objects == p_pool->max_objects) 221321936Shselasky return (CL_INSUFFICIENT_MEMORY); 222321936Shselasky 223321936Shselasky /* Cap the growth to the desired maximum. */ 224321936Shselasky if (obj_count > (p_pool->max_objects - p_pool->num_objects)) 225321936Shselasky obj_count = p_pool->max_objects - p_pool->num_objects; 226321936Shselasky 227321936Shselasky /* Calculate the size of an object. */ 228321936Shselasky obj_size = 0; 229321936Shselasky for (i = 0; i < p_pool->num_components; i++) 230321936Shselasky obj_size += p_pool->component_sizes[i]; 231321936Shselasky 232321936Shselasky /* Allocate the buffer for the new objects. */ 233321936Shselasky p_objects = (uint8_t *) 234321936Shselasky malloc(sizeof(cl_list_item_t) + (obj_size * obj_count)); 235321936Shselasky 236321936Shselasky /* Make sure the allocation succeeded. */ 237321936Shselasky if (!p_objects) 238321936Shselasky return (CL_INSUFFICIENT_MEMORY); 239321936Shselasky else 240321936Shselasky memset(p_objects, 0, 241321936Shselasky sizeof(cl_list_item_t) + (obj_size * obj_count)); 242321936Shselasky 243321936Shselasky /* Insert the allocation in our list. */ 244321936Shselasky cl_qlist_insert_tail(&p_pool->alloc_list, (cl_list_item_t *) p_objects); 245321936Shselasky p_objects += sizeof(cl_list_item_t); 246321936Shselasky 247321936Shselasky /* initialize the new elements and add them to the free list */ 248321936Shselasky while (obj_count--) { 249321936Shselasky /* Setup the array of components for the current object. */ 250321936Shselasky p_pool->p_components[0] = p_objects; 251321936Shselasky for (i = 1; i < p_pool->num_components; i++) { 252321936Shselasky /* Calculate the pointer to the next component. */ 253321936Shselasky p_pool->p_components[i] = 254321936Shselasky (uint8_t *) p_pool->p_components[i - 1] + 255321936Shselasky p_pool->component_sizes[i - 1]; 256321936Shselasky } 257321936Shselasky 258321936Shselasky /* 259321936Shselasky * call the user's initializer 260321936Shselasky * this can fail! 261321936Shselasky */ 262321936Shselasky if (p_pool->pfn_init) { 263321936Shselasky p_pool_item = NULL; 264321936Shselasky status = p_pool->pfn_init(p_pool->p_components, 265321936Shselasky p_pool->num_components, 266321936Shselasky (void *)p_pool->context, 267321936Shselasky &p_pool_item); 268321936Shselasky if (status != CL_SUCCESS) { 269321936Shselasky /* 270321936Shselasky * User initialization failed 271321936Shselasky * we may have only grown the pool by some partial amount 272321936Shselasky * Invoke the destructor for the object that failed 273321936Shselasky * initialization. 274321936Shselasky */ 275321936Shselasky if (p_pool->pfn_dtor) 276321936Shselasky p_pool->pfn_dtor(p_pool_item, 277321936Shselasky (void *)p_pool-> 278321936Shselasky context); 279321936Shselasky 280321936Shselasky /* Return the user's status. */ 281321936Shselasky return (status); 282321936Shselasky } 283321936Shselasky CL_ASSERT(p_pool_item); 284321936Shselasky } else { 285321936Shselasky /* 286321936Shselasky * If no initializer is provided, assume that the pool item 287321936Shselasky * is stored at the beginning of the first component. 288321936Shselasky */ 289321936Shselasky p_pool_item = 290321936Shselasky (cl_pool_item_t *) p_pool->p_components[0]; 291321936Shselasky } 292321936Shselasky 293321936Shselasky#ifdef _DEBUG_ 294321936Shselasky /* 295321936Shselasky * Set the pool item's pool pointer to this pool so that we can 296321936Shselasky * check that items get returned to the correct pool. 297321936Shselasky */ 298321936Shselasky p_pool_item->p_pool = p_pool; 299321936Shselasky#endif 300321936Shselasky 301321936Shselasky /* Insert the new item in the free list, traping for failure. */ 302321936Shselasky cl_qlist_insert_head(&p_pool->free_list, 303321936Shselasky &p_pool_item->list_item); 304321936Shselasky 305321936Shselasky p_pool->num_objects++; 306321936Shselasky 307321936Shselasky /* move the pointer to the next item */ 308321936Shselasky p_objects += obj_size; 309321936Shselasky } 310321936Shselasky 311321936Shselasky return (status); 312321936Shselasky} 313321936Shselasky 314321936Shselaskycl_pool_item_t *cl_qcpool_get(IN cl_qcpool_t * const p_pool) 315321936Shselasky{ 316321936Shselasky cl_list_item_t *p_list_item; 317321936Shselasky 318321936Shselasky CL_ASSERT(p_pool); 319321936Shselasky CL_ASSERT(p_pool->state == CL_INITIALIZED); 320321936Shselasky 321321936Shselasky if (cl_is_qlist_empty(&p_pool->free_list)) { 322321936Shselasky /* 323321936Shselasky * No object is available. 324321936Shselasky * Return NULL if the user does not want automatic growth. 325321936Shselasky */ 326321936Shselasky if (!p_pool->grow_size) 327321936Shselasky return (NULL); 328321936Shselasky 329321936Shselasky /* We ran out of elements. Get more */ 330321936Shselasky cl_qcpool_grow(p_pool, p_pool->grow_size); 331321936Shselasky /* 332321936Shselasky * We may not have gotten everything we wanted but we might have 333321936Shselasky * gotten something. 334321936Shselasky */ 335321936Shselasky if (cl_is_qlist_empty(&p_pool->free_list)) 336321936Shselasky return (NULL); 337321936Shselasky } 338321936Shselasky 339321936Shselasky p_list_item = cl_qlist_remove_head(&p_pool->free_list); 340321936Shselasky /* OK, at this point we have an object */ 341321936Shselasky CL_ASSERT(p_list_item != cl_qlist_end(&p_pool->free_list)); 342321936Shselasky return ((cl_pool_item_t *) p_list_item); 343321936Shselasky} 344321936Shselasky 345321936Shselaskycl_pool_item_t *cl_qcpool_get_tail(IN cl_qcpool_t * const p_pool) 346321936Shselasky{ 347321936Shselasky cl_list_item_t *p_list_item; 348321936Shselasky 349321936Shselasky CL_ASSERT(p_pool); 350321936Shselasky CL_ASSERT(p_pool->state == CL_INITIALIZED); 351321936Shselasky 352321936Shselasky if (cl_is_qlist_empty(&p_pool->free_list)) { 353321936Shselasky /* 354321936Shselasky * No object is available. 355321936Shselasky * Return NULL if the user does not want automatic growth. 356321936Shselasky */ 357321936Shselasky if (!p_pool->grow_size) 358321936Shselasky return (NULL); 359321936Shselasky 360321936Shselasky /* We ran out of elements. Get more */ 361321936Shselasky cl_qcpool_grow(p_pool, p_pool->grow_size); 362321936Shselasky /* 363321936Shselasky * We may not have gotten everything we wanted but we might have 364321936Shselasky * gotten something. 365321936Shselasky */ 366321936Shselasky if (cl_is_qlist_empty(&p_pool->free_list)) 367321936Shselasky return (NULL); 368321936Shselasky } 369321936Shselasky 370321936Shselasky p_list_item = cl_qlist_remove_tail(&p_pool->free_list); 371321936Shselasky /* OK, at this point we have an object */ 372321936Shselasky CL_ASSERT(p_list_item != cl_qlist_end(&p_pool->free_list)); 373321936Shselasky return ((cl_pool_item_t *) p_list_item); 374321936Shselasky} 375321936Shselasky 376321936Shselasky/* 377321936Shselasky * IMPLEMENTATION OF QUICK GROW POOL 378321936Shselasky */ 379321936Shselasky 380321936Shselasky/* 381321936Shselasky * Callback to translate quick composite to quick grow pool 382321936Shselasky * initializer callback. 383321936Shselasky */ 384321936Shselaskystatic cl_status_t __cl_qpool_init_cb(IN void **const p_comp_array, 385321936Shselasky IN const uint32_t num_components, 386321936Shselasky IN void *const context, 387321936Shselasky OUT cl_pool_item_t ** const pp_pool_item) 388321936Shselasky{ 389321936Shselasky cl_qpool_t *p_pool = (cl_qpool_t *) context; 390321936Shselasky 391321936Shselasky CL_ASSERT(p_pool); 392321936Shselasky CL_ASSERT(p_pool->pfn_init); 393321936Shselasky CL_ASSERT(num_components == 1); 394321936Shselasky 395321936Shselasky UNUSED_PARAM(num_components); 396321936Shselasky 397321936Shselasky return (p_pool->pfn_init(p_comp_array[0], (void *)p_pool->context, 398321936Shselasky pp_pool_item)); 399321936Shselasky} 400321936Shselasky 401321936Shselasky/* 402321936Shselasky * Callback to translate quick composite to quick grow pool 403321936Shselasky * destructor callback. 404321936Shselasky */ 405321936Shselaskystatic void __cl_qpool_dtor_cb(IN const cl_pool_item_t * const p_pool_item, 406321936Shselasky IN void *const context) 407321936Shselasky{ 408321936Shselasky cl_qpool_t *p_pool = (cl_qpool_t *) context; 409321936Shselasky 410321936Shselasky CL_ASSERT(p_pool); 411321936Shselasky CL_ASSERT(p_pool->pfn_dtor); 412321936Shselasky 413321936Shselasky p_pool->pfn_dtor(p_pool_item, (void *)p_pool->context); 414321936Shselasky} 415321936Shselasky 416321936Shselaskyvoid cl_qpool_construct(IN cl_qpool_t * const p_pool) 417321936Shselasky{ 418321936Shselasky memset(p_pool, 0, sizeof(cl_qpool_t)); 419321936Shselasky 420321936Shselasky cl_qcpool_construct(&p_pool->qcpool); 421321936Shselasky} 422321936Shselasky 423321936Shselaskycl_status_t cl_qpool_init(IN cl_qpool_t * const p_pool, 424321936Shselasky IN const size_t min_size, IN const size_t max_size, 425321936Shselasky IN const size_t grow_size, 426321936Shselasky IN const size_t object_size, 427321936Shselasky IN cl_pfn_qpool_init_t pfn_initializer OPTIONAL, 428321936Shselasky IN cl_pfn_qpool_dtor_t pfn_destructor OPTIONAL, 429321936Shselasky IN const void *const context) 430321936Shselasky{ 431321936Shselasky cl_status_t status; 432321936Shselasky 433321936Shselasky CL_ASSERT(p_pool); 434321936Shselasky 435321936Shselasky p_pool->pfn_init = pfn_initializer; /* may be NULL */ 436321936Shselasky p_pool->pfn_dtor = pfn_destructor; /* may be NULL */ 437321936Shselasky p_pool->context = context; 438321936Shselasky 439321936Shselasky status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size, 440321936Shselasky &object_size, 1, 441321936Shselasky pfn_initializer ? __cl_qpool_init_cb : NULL, 442321936Shselasky pfn_destructor ? __cl_qpool_dtor_cb : NULL, 443321936Shselasky p_pool); 444321936Shselasky 445321936Shselasky return (status); 446321936Shselasky} 447321936Shselasky 448321936Shselasky/* 449321936Shselasky * IMPLEMENTATION OF COMPOSITE POOL 450321936Shselasky */ 451321936Shselasky 452321936Shselasky/* 453321936Shselasky * Callback to translate quick composite to compsite pool 454321936Shselasky * initializer callback. 455321936Shselasky */ 456321936Shselaskystatic cl_status_t __cl_cpool_init_cb(IN void **const p_comp_array, 457321936Shselasky IN const uint32_t num_components, 458321936Shselasky IN void *const context, 459321936Shselasky OUT cl_pool_item_t ** const pp_pool_item) 460321936Shselasky{ 461321936Shselasky cl_cpool_t *p_pool = (cl_cpool_t *) context; 462321936Shselasky cl_pool_obj_t *p_pool_obj; 463321936Shselasky cl_status_t status = CL_SUCCESS; 464321936Shselasky 465321936Shselasky CL_ASSERT(p_pool); 466321936Shselasky 467321936Shselasky /* 468321936Shselasky * Set our pointer to the list item, which is stored at the beginning of 469321936Shselasky * the first component. 470321936Shselasky */ 471321936Shselasky p_pool_obj = (cl_pool_obj_t *) p_comp_array[0]; 472321936Shselasky /* Set the pool item pointer for the caller. */ 473321936Shselasky *pp_pool_item = &p_pool_obj->pool_item; 474321936Shselasky 475321936Shselasky /* Calculate the pointer to the user's first component. */ 476321936Shselasky p_comp_array[0] = ((uint8_t *) p_comp_array[0]) + sizeof(cl_pool_obj_t); 477321936Shselasky 478321936Shselasky /* 479321936Shselasky * Set the object pointer in the pool object to point to the first of the 480321936Shselasky * user's components. 481321936Shselasky */ 482321936Shselasky p_pool_obj->p_object = p_comp_array[0]; 483321936Shselasky 484321936Shselasky /* Invoke the user's constructor callback. */ 485321936Shselasky if (p_pool->pfn_init) { 486321936Shselasky status = p_pool->pfn_init(p_comp_array, num_components, 487321936Shselasky (void *)p_pool->context); 488321936Shselasky } 489321936Shselasky 490321936Shselasky return (status); 491321936Shselasky} 492321936Shselasky 493321936Shselasky/* 494321936Shselasky * Callback to translate quick composite to composite pool 495321936Shselasky * destructor callback. 496321936Shselasky */ 497321936Shselaskystatic void __cl_cpool_dtor_cb(IN const cl_pool_item_t * const p_pool_item, 498321936Shselasky IN void *const context) 499321936Shselasky{ 500321936Shselasky cl_cpool_t *p_pool = (cl_cpool_t *) context; 501321936Shselasky 502321936Shselasky CL_ASSERT(p_pool); 503321936Shselasky CL_ASSERT(p_pool->pfn_dtor); 504321936Shselasky CL_ASSERT(((cl_pool_obj_t *) p_pool_item)->p_object); 505321936Shselasky 506321936Shselasky /* Invoke the user's destructor callback. */ 507321936Shselasky p_pool->pfn_dtor((void *)((cl_pool_obj_t *) p_pool_item)->p_object, 508321936Shselasky (void *)p_pool->context); 509321936Shselasky} 510321936Shselasky 511321936Shselaskyvoid cl_cpool_construct(IN cl_cpool_t * const p_pool) 512321936Shselasky{ 513321936Shselasky CL_ASSERT(p_pool); 514321936Shselasky 515321936Shselasky memset(p_pool, 0, sizeof(cl_cpool_t)); 516321936Shselasky 517321936Shselasky cl_qcpool_construct(&p_pool->qcpool); 518321936Shselasky} 519321936Shselasky 520321936Shselaskycl_status_t cl_cpool_init(IN cl_cpool_t * const p_pool, 521321936Shselasky IN const size_t min_size, IN const size_t max_size, 522321936Shselasky IN const size_t grow_size, 523321936Shselasky IN size_t * const component_sizes, 524321936Shselasky IN const uint32_t num_components, 525321936Shselasky IN cl_pfn_cpool_init_t pfn_initializer OPTIONAL, 526321936Shselasky IN cl_pfn_cpool_dtor_t pfn_destructor OPTIONAL, 527321936Shselasky IN const void *const context) 528321936Shselasky{ 529321936Shselasky cl_status_t status; 530321936Shselasky 531321936Shselasky CL_ASSERT(p_pool); 532321936Shselasky CL_ASSERT(num_components); 533321936Shselasky CL_ASSERT(component_sizes); 534321936Shselasky 535321936Shselasky /* Add the size of the pool object to the first component. */ 536321936Shselasky component_sizes[0] += sizeof(cl_pool_obj_t); 537321936Shselasky 538321936Shselasky /* Store callback function pointers. */ 539321936Shselasky p_pool->pfn_init = pfn_initializer; /* may be NULL */ 540321936Shselasky p_pool->pfn_dtor = pfn_destructor; /* may be NULL */ 541321936Shselasky p_pool->context = context; 542321936Shselasky 543321936Shselasky status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size, 544321936Shselasky component_sizes, num_components, 545321936Shselasky __cl_cpool_init_cb, 546321936Shselasky pfn_destructor ? __cl_cpool_dtor_cb : NULL, 547321936Shselasky p_pool); 548321936Shselasky 549321936Shselasky /* Restore the original value of the first component. */ 550321936Shselasky component_sizes[0] -= sizeof(cl_pool_obj_t); 551321936Shselasky 552321936Shselasky return (status); 553321936Shselasky} 554321936Shselasky 555321936Shselasky/* 556321936Shselasky * IMPLEMENTATION OF GROW POOL 557321936Shselasky */ 558321936Shselasky 559321936Shselasky/* 560321936Shselasky * Callback to translate quick composite to grow pool constructor callback. 561321936Shselasky */ 562321936Shselaskystatic cl_status_t __cl_pool_init_cb(IN void **const pp_obj, 563321936Shselasky IN const uint32_t count, 564321936Shselasky IN void *const context, 565321936Shselasky OUT cl_pool_item_t ** const pp_pool_item) 566321936Shselasky{ 567321936Shselasky cl_pool_t *p_pool = (cl_pool_t *) context; 568321936Shselasky cl_pool_obj_t *p_pool_obj; 569321936Shselasky cl_status_t status = CL_SUCCESS; 570321936Shselasky 571321936Shselasky CL_ASSERT(p_pool); 572321936Shselasky CL_ASSERT(pp_obj); 573321936Shselasky CL_ASSERT(count == 1); 574321936Shselasky 575321936Shselasky UNUSED_PARAM(count); 576321936Shselasky 577321936Shselasky /* 578321936Shselasky * Set our pointer to the list item, which is stored at the beginning of 579321936Shselasky * the first component. 580321936Shselasky */ 581321936Shselasky p_pool_obj = (cl_pool_obj_t *) * pp_obj; 582321936Shselasky *pp_pool_item = &p_pool_obj->pool_item; 583321936Shselasky 584321936Shselasky /* Calculate the pointer to the user's first component. */ 585321936Shselasky *pp_obj = ((uint8_t *) * pp_obj) + sizeof(cl_pool_obj_t); 586321936Shselasky 587321936Shselasky /* 588321936Shselasky * Set the object pointer in the pool item to point to the first of the 589321936Shselasky * user's components. 590321936Shselasky */ 591321936Shselasky p_pool_obj->p_object = *pp_obj; 592321936Shselasky 593321936Shselasky /* Invoke the user's constructor callback. */ 594321936Shselasky if (p_pool->pfn_init) 595321936Shselasky status = p_pool->pfn_init(*pp_obj, (void *)p_pool->context); 596321936Shselasky 597321936Shselasky return (status); 598321936Shselasky} 599321936Shselasky 600321936Shselasky/* 601321936Shselasky * Callback to translate quick composite to grow pool destructor callback. 602321936Shselasky */ 603321936Shselaskystatic void __cl_pool_dtor_cb(IN const cl_pool_item_t * const p_pool_item, 604321936Shselasky IN void *const context) 605321936Shselasky{ 606321936Shselasky cl_pool_t *p_pool = (cl_pool_t *) context; 607321936Shselasky 608321936Shselasky CL_ASSERT(p_pool); 609321936Shselasky CL_ASSERT(p_pool->pfn_dtor); 610321936Shselasky CL_ASSERT(((cl_pool_obj_t *) p_pool_item)->p_object); 611321936Shselasky 612321936Shselasky /* Invoke the user's destructor callback. */ 613321936Shselasky p_pool->pfn_dtor((void *)((cl_pool_obj_t *) p_pool_item)->p_object, 614321936Shselasky (void *)p_pool->context); 615321936Shselasky} 616321936Shselasky 617321936Shselaskyvoid cl_pool_construct(IN cl_pool_t * const p_pool) 618321936Shselasky{ 619321936Shselasky CL_ASSERT(p_pool); 620321936Shselasky 621321936Shselasky memset(p_pool, 0, sizeof(cl_pool_t)); 622321936Shselasky 623321936Shselasky cl_qcpool_construct(&p_pool->qcpool); 624321936Shselasky} 625321936Shselasky 626321936Shselaskycl_status_t cl_pool_init(IN cl_pool_t * const p_pool, IN const size_t min_size, 627321936Shselasky IN const size_t max_size, IN const size_t grow_size, 628321936Shselasky IN const size_t object_size, 629321936Shselasky IN cl_pfn_pool_init_t pfn_initializer OPTIONAL, 630321936Shselasky IN cl_pfn_pool_dtor_t pfn_destructor OPTIONAL, 631321936Shselasky IN const void *const context) 632321936Shselasky{ 633321936Shselasky cl_status_t status; 634321936Shselasky size_t total_size; 635321936Shselasky 636321936Shselasky CL_ASSERT(p_pool); 637321936Shselasky 638321936Shselasky /* Add the size of the list item to the first component. */ 639321936Shselasky total_size = object_size + sizeof(cl_pool_obj_t); 640321936Shselasky 641321936Shselasky /* Store callback function pointers. */ 642321936Shselasky p_pool->pfn_init = pfn_initializer; /* may be NULL */ 643321936Shselasky p_pool->pfn_dtor = pfn_destructor; /* may be NULL */ 644321936Shselasky p_pool->context = context; 645321936Shselasky 646321936Shselasky /* 647321936Shselasky * We need an initializer in all cases for quick composite pool, since 648321936Shselasky * the user pointer must be manipulated to hide the prefixed cl_pool_obj_t. 649321936Shselasky */ 650321936Shselasky status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size, 651321936Shselasky &total_size, 1, __cl_pool_init_cb, 652321936Shselasky pfn_destructor ? __cl_pool_dtor_cb : NULL, 653321936Shselasky p_pool); 654321936Shselasky 655321936Shselasky return (status); 656321936Shselasky} 657