1*00b67f09SDavid van Moolenbroek /* $NetBSD: pool.c,v 1.1.1.3 2014/12/10 03:34:43 christos Exp $ */
2*00b67f09SDavid van Moolenbroek
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek *
6*00b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any
7*00b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
8*00b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
9*00b67f09SDavid van Moolenbroek *
10*00b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11*00b67f09SDavid van Moolenbroek * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12*00b67f09SDavid van Moolenbroek * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13*00b67f09SDavid van Moolenbroek * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14*00b67f09SDavid van Moolenbroek * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15*00b67f09SDavid van Moolenbroek * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*00b67f09SDavid van Moolenbroek * PERFORMANCE OF THIS SOFTWARE.
17*00b67f09SDavid van Moolenbroek */
18*00b67f09SDavid van Moolenbroek
19*00b67f09SDavid van Moolenbroek /* Id */
20*00b67f09SDavid van Moolenbroek
21*00b67f09SDavid van Moolenbroek /*! \file */
22*00b67f09SDavid van Moolenbroek
23*00b67f09SDavid van Moolenbroek #include <config.h>
24*00b67f09SDavid van Moolenbroek
25*00b67f09SDavid van Moolenbroek #include <string.h>
26*00b67f09SDavid van Moolenbroek
27*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
28*00b67f09SDavid van Moolenbroek #include <isc/random.h>
29*00b67f09SDavid van Moolenbroek #include <isc/pool.h>
30*00b67f09SDavid van Moolenbroek #include <isc/util.h>
31*00b67f09SDavid van Moolenbroek
32*00b67f09SDavid van Moolenbroek /***
33*00b67f09SDavid van Moolenbroek *** Types.
34*00b67f09SDavid van Moolenbroek ***/
35*00b67f09SDavid van Moolenbroek
36*00b67f09SDavid van Moolenbroek struct isc_pool {
37*00b67f09SDavid van Moolenbroek isc_mem_t * mctx;
38*00b67f09SDavid van Moolenbroek unsigned int count;
39*00b67f09SDavid van Moolenbroek isc_pooldeallocator_t free;
40*00b67f09SDavid van Moolenbroek isc_poolinitializer_t init;
41*00b67f09SDavid van Moolenbroek void * initarg;
42*00b67f09SDavid van Moolenbroek void ** pool;
43*00b67f09SDavid van Moolenbroek };
44*00b67f09SDavid van Moolenbroek
45*00b67f09SDavid van Moolenbroek /***
46*00b67f09SDavid van Moolenbroek *** Functions.
47*00b67f09SDavid van Moolenbroek ***/
48*00b67f09SDavid van Moolenbroek
49*00b67f09SDavid van Moolenbroek static isc_result_t
alloc_pool(isc_mem_t * mctx,unsigned int count,isc_pool_t ** poolp)50*00b67f09SDavid van Moolenbroek alloc_pool(isc_mem_t *mctx, unsigned int count, isc_pool_t **poolp) {
51*00b67f09SDavid van Moolenbroek isc_pool_t *pool;
52*00b67f09SDavid van Moolenbroek
53*00b67f09SDavid van Moolenbroek pool = isc_mem_get(mctx, sizeof(*pool));
54*00b67f09SDavid van Moolenbroek if (pool == NULL)
55*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
56*00b67f09SDavid van Moolenbroek pool->count = count;
57*00b67f09SDavid van Moolenbroek pool->free = NULL;
58*00b67f09SDavid van Moolenbroek pool->init = NULL;
59*00b67f09SDavid van Moolenbroek pool->initarg = NULL;
60*00b67f09SDavid van Moolenbroek pool->mctx = NULL;
61*00b67f09SDavid van Moolenbroek isc_mem_attach(mctx, &pool->mctx);
62*00b67f09SDavid van Moolenbroek pool->pool = isc_mem_get(mctx, count * sizeof(void *));
63*00b67f09SDavid van Moolenbroek if (pool->pool == NULL) {
64*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, pool, sizeof(*pool));
65*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
66*00b67f09SDavid van Moolenbroek }
67*00b67f09SDavid van Moolenbroek memset(pool->pool, 0, count * sizeof(void *));
68*00b67f09SDavid van Moolenbroek
69*00b67f09SDavid van Moolenbroek *poolp = pool;
70*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
71*00b67f09SDavid van Moolenbroek }
72*00b67f09SDavid van Moolenbroek
73*00b67f09SDavid van Moolenbroek isc_result_t
isc_pool_create(isc_mem_t * mctx,unsigned int count,isc_pooldeallocator_t free,isc_poolinitializer_t init,void * initarg,isc_pool_t ** poolp)74*00b67f09SDavid van Moolenbroek isc_pool_create(isc_mem_t *mctx, unsigned int count,
75*00b67f09SDavid van Moolenbroek isc_pooldeallocator_t free,
76*00b67f09SDavid van Moolenbroek isc_poolinitializer_t init, void *initarg,
77*00b67f09SDavid van Moolenbroek isc_pool_t **poolp)
78*00b67f09SDavid van Moolenbroek {
79*00b67f09SDavid van Moolenbroek isc_pool_t *pool = NULL;
80*00b67f09SDavid van Moolenbroek isc_result_t result;
81*00b67f09SDavid van Moolenbroek unsigned int i;
82*00b67f09SDavid van Moolenbroek
83*00b67f09SDavid van Moolenbroek INSIST(count > 0);
84*00b67f09SDavid van Moolenbroek
85*00b67f09SDavid van Moolenbroek /* Allocate the pool structure */
86*00b67f09SDavid van Moolenbroek result = alloc_pool(mctx, count, &pool);
87*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
88*00b67f09SDavid van Moolenbroek return (result);
89*00b67f09SDavid van Moolenbroek
90*00b67f09SDavid van Moolenbroek pool->free = free;
91*00b67f09SDavid van Moolenbroek pool->init = init;
92*00b67f09SDavid van Moolenbroek pool->initarg = initarg;
93*00b67f09SDavid van Moolenbroek
94*00b67f09SDavid van Moolenbroek /* Populate the pool */
95*00b67f09SDavid van Moolenbroek for (i = 0; i < count; i++) {
96*00b67f09SDavid van Moolenbroek result = init(&pool->pool[i], initarg);
97*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
98*00b67f09SDavid van Moolenbroek isc_pool_destroy(&pool);
99*00b67f09SDavid van Moolenbroek return (result);
100*00b67f09SDavid van Moolenbroek }
101*00b67f09SDavid van Moolenbroek }
102*00b67f09SDavid van Moolenbroek
103*00b67f09SDavid van Moolenbroek *poolp = pool;
104*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
105*00b67f09SDavid van Moolenbroek }
106*00b67f09SDavid van Moolenbroek
107*00b67f09SDavid van Moolenbroek void *
isc_pool_get(isc_pool_t * pool)108*00b67f09SDavid van Moolenbroek isc_pool_get(isc_pool_t *pool) {
109*00b67f09SDavid van Moolenbroek isc_uint32_t i;
110*00b67f09SDavid van Moolenbroek isc_random_get(&i);
111*00b67f09SDavid van Moolenbroek return (pool->pool[i % pool->count]);
112*00b67f09SDavid van Moolenbroek }
113*00b67f09SDavid van Moolenbroek
114*00b67f09SDavid van Moolenbroek int
isc_pool_count(isc_pool_t * pool)115*00b67f09SDavid van Moolenbroek isc_pool_count(isc_pool_t *pool) {
116*00b67f09SDavid van Moolenbroek REQUIRE(pool != NULL);
117*00b67f09SDavid van Moolenbroek return (pool->count);
118*00b67f09SDavid van Moolenbroek }
119*00b67f09SDavid van Moolenbroek
120*00b67f09SDavid van Moolenbroek isc_result_t
isc_pool_expand(isc_pool_t ** sourcep,unsigned int count,isc_pool_t ** targetp)121*00b67f09SDavid van Moolenbroek isc_pool_expand(isc_pool_t **sourcep, unsigned int count,
122*00b67f09SDavid van Moolenbroek isc_pool_t **targetp)
123*00b67f09SDavid van Moolenbroek {
124*00b67f09SDavid van Moolenbroek isc_result_t result;
125*00b67f09SDavid van Moolenbroek isc_pool_t *pool;
126*00b67f09SDavid van Moolenbroek
127*00b67f09SDavid van Moolenbroek REQUIRE(sourcep != NULL && *sourcep != NULL);
128*00b67f09SDavid van Moolenbroek REQUIRE(targetp != NULL && *targetp == NULL);
129*00b67f09SDavid van Moolenbroek
130*00b67f09SDavid van Moolenbroek pool = *sourcep;
131*00b67f09SDavid van Moolenbroek if (count > pool->count) {
132*00b67f09SDavid van Moolenbroek isc_pool_t *newpool = NULL;
133*00b67f09SDavid van Moolenbroek unsigned int i;
134*00b67f09SDavid van Moolenbroek
135*00b67f09SDavid van Moolenbroek /* Allocate a new pool structure */
136*00b67f09SDavid van Moolenbroek result = alloc_pool(pool->mctx, count, &newpool);
137*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
138*00b67f09SDavid van Moolenbroek return (result);
139*00b67f09SDavid van Moolenbroek
140*00b67f09SDavid van Moolenbroek newpool->free = pool->free;
141*00b67f09SDavid van Moolenbroek newpool->init = pool->init;
142*00b67f09SDavid van Moolenbroek newpool->initarg = pool->initarg;
143*00b67f09SDavid van Moolenbroek
144*00b67f09SDavid van Moolenbroek /* Copy over the objects from the old pool */
145*00b67f09SDavid van Moolenbroek for (i = 0; i < pool->count; i++) {
146*00b67f09SDavid van Moolenbroek newpool->pool[i] = pool->pool[i];
147*00b67f09SDavid van Moolenbroek pool->pool[i] = NULL;
148*00b67f09SDavid van Moolenbroek }
149*00b67f09SDavid van Moolenbroek
150*00b67f09SDavid van Moolenbroek /* Populate the new entries */
151*00b67f09SDavid van Moolenbroek for (i = pool->count; i < count; i++) {
152*00b67f09SDavid van Moolenbroek result = pool->init(&newpool->pool[i], pool->initarg);
153*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
154*00b67f09SDavid van Moolenbroek isc_pool_destroy(&pool);
155*00b67f09SDavid van Moolenbroek return (result);
156*00b67f09SDavid van Moolenbroek }
157*00b67f09SDavid van Moolenbroek }
158*00b67f09SDavid van Moolenbroek
159*00b67f09SDavid van Moolenbroek isc_pool_destroy(&pool);
160*00b67f09SDavid van Moolenbroek pool = newpool;
161*00b67f09SDavid van Moolenbroek }
162*00b67f09SDavid van Moolenbroek
163*00b67f09SDavid van Moolenbroek *sourcep = NULL;
164*00b67f09SDavid van Moolenbroek *targetp = pool;
165*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
166*00b67f09SDavid van Moolenbroek }
167*00b67f09SDavid van Moolenbroek
168*00b67f09SDavid van Moolenbroek void
isc_pool_destroy(isc_pool_t ** poolp)169*00b67f09SDavid van Moolenbroek isc_pool_destroy(isc_pool_t **poolp) {
170*00b67f09SDavid van Moolenbroek unsigned int i;
171*00b67f09SDavid van Moolenbroek isc_pool_t *pool = *poolp;
172*00b67f09SDavid van Moolenbroek for (i = 0; i < pool->count; i++) {
173*00b67f09SDavid van Moolenbroek if (pool->free != NULL && pool->pool[i] != NULL)
174*00b67f09SDavid van Moolenbroek pool->free(&pool->pool[i]);
175*00b67f09SDavid van Moolenbroek }
176*00b67f09SDavid van Moolenbroek isc_mem_put(pool->mctx, pool->pool, pool->count * sizeof(void *));
177*00b67f09SDavid van Moolenbroek isc_mem_putanddetach(&pool->mctx, pool, sizeof(*pool));
178*00b67f09SDavid van Moolenbroek *poolp = NULL;
179*00b67f09SDavid van Moolenbroek }
180