xref: /minix3/external/bsd/bind/dist/lib/isc/pool.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
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