xref: /netbsd/external/mpl/bind/dist/lib/isc/pool.c (revision c0b5d9fb)
1*c0b5d9fbSchristos /*	$NetBSD: pool.c,v 1.6 2022/09/23 12:15:33 christos Exp $	*/
2e2b1b9c0Schristos 
3e2b1b9c0Schristos /*
4e2b1b9c0Schristos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5e2b1b9c0Schristos  *
6*c0b5d9fbSchristos  * SPDX-License-Identifier: MPL-2.0
7*c0b5d9fbSchristos  *
8e2b1b9c0Schristos  * This Source Code Form is subject to the terms of the Mozilla Public
9e2b1b9c0Schristos  * License, v. 2.0. If a copy of the MPL was not distributed with this
1073584a28Schristos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11e2b1b9c0Schristos  *
12e2b1b9c0Schristos  * See the COPYRIGHT file distributed with this work for additional
13e2b1b9c0Schristos  * information regarding copyright ownership.
14e2b1b9c0Schristos  */
15e2b1b9c0Schristos 
16e2b1b9c0Schristos /*! \file */
17e2b1b9c0Schristos 
18e2b1b9c0Schristos #include <string.h>
19e2b1b9c0Schristos 
20e2b1b9c0Schristos #include <isc/mem.h>
21e2b1b9c0Schristos #include <isc/pool.h>
229742fdb4Schristos #include <isc/random.h>
23e2b1b9c0Schristos #include <isc/util.h>
24e2b1b9c0Schristos 
25e2b1b9c0Schristos /***
26e2b1b9c0Schristos  *** Types.
27e2b1b9c0Schristos  ***/
28e2b1b9c0Schristos 
29e2b1b9c0Schristos struct isc_pool {
30e2b1b9c0Schristos 	isc_mem_t *mctx;
31e2b1b9c0Schristos 	unsigned int count;
32e2b1b9c0Schristos 	isc_pooldeallocator_t free;
33e2b1b9c0Schristos 	isc_poolinitializer_t init;
34e2b1b9c0Schristos 	void *initarg;
35e2b1b9c0Schristos 	void **pool;
36e2b1b9c0Schristos };
37e2b1b9c0Schristos 
38e2b1b9c0Schristos /***
39e2b1b9c0Schristos  *** Functions.
40e2b1b9c0Schristos  ***/
41e2b1b9c0Schristos 
42e2b1b9c0Schristos static isc_result_t
alloc_pool(isc_mem_t * mctx,unsigned int count,isc_pool_t ** poolp)43e2b1b9c0Schristos alloc_pool(isc_mem_t *mctx, unsigned int count, isc_pool_t **poolp) {
44e2b1b9c0Schristos 	isc_pool_t *pool;
45e2b1b9c0Schristos 
46e2b1b9c0Schristos 	pool = isc_mem_get(mctx, sizeof(*pool));
47e2b1b9c0Schristos 	pool->count = count;
48e2b1b9c0Schristos 	pool->free = NULL;
49e2b1b9c0Schristos 	pool->init = NULL;
50e2b1b9c0Schristos 	pool->initarg = NULL;
51e2b1b9c0Schristos 	pool->mctx = NULL;
52e2b1b9c0Schristos 	isc_mem_attach(mctx, &pool->mctx);
53e2b1b9c0Schristos 	pool->pool = isc_mem_get(mctx, count * sizeof(void *));
54e2b1b9c0Schristos 	memset(pool->pool, 0, count * sizeof(void *));
55e2b1b9c0Schristos 
56e2b1b9c0Schristos 	*poolp = pool;
57e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
58e2b1b9c0Schristos }
59e2b1b9c0Schristos 
60e2b1b9c0Schristos isc_result_t
isc_pool_create(isc_mem_t * mctx,unsigned int count,isc_pooldeallocator_t release,isc_poolinitializer_t init,void * initarg,isc_pool_t ** poolp)61e2b1b9c0Schristos isc_pool_create(isc_mem_t *mctx, unsigned int count,
629742fdb4Schristos 		isc_pooldeallocator_t release, isc_poolinitializer_t init,
639742fdb4Schristos 		void *initarg, isc_pool_t **poolp) {
64e2b1b9c0Schristos 	isc_pool_t *pool = NULL;
65e2b1b9c0Schristos 	isc_result_t result;
66e2b1b9c0Schristos 	unsigned int i;
67e2b1b9c0Schristos 
68e2b1b9c0Schristos 	INSIST(count > 0);
69e2b1b9c0Schristos 
70e2b1b9c0Schristos 	/* Allocate the pool structure */
71e2b1b9c0Schristos 	result = alloc_pool(mctx, count, &pool);
729742fdb4Schristos 	if (result != ISC_R_SUCCESS) {
73e2b1b9c0Schristos 		return (result);
749742fdb4Schristos 	}
75e2b1b9c0Schristos 
76e2b1b9c0Schristos 	pool->free = release;
77e2b1b9c0Schristos 	pool->init = init;
78e2b1b9c0Schristos 	pool->initarg = initarg;
79e2b1b9c0Schristos 
80e2b1b9c0Schristos 	/* Populate the pool */
81e2b1b9c0Schristos 	for (i = 0; i < count; i++) {
82e2b1b9c0Schristos 		result = init(&pool->pool[i], initarg);
83e2b1b9c0Schristos 		if (result != ISC_R_SUCCESS) {
84e2b1b9c0Schristos 			isc_pool_destroy(&pool);
85e2b1b9c0Schristos 			return (result);
86e2b1b9c0Schristos 		}
87e2b1b9c0Schristos 	}
88e2b1b9c0Schristos 
89e2b1b9c0Schristos 	*poolp = pool;
90e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
91e2b1b9c0Schristos }
92e2b1b9c0Schristos 
93e2b1b9c0Schristos void *
isc_pool_get(isc_pool_t * pool)94e2b1b9c0Schristos isc_pool_get(isc_pool_t *pool) {
95f2e20987Schristos 	return (pool->pool[isc_random_uniform(pool->count)]);
96e2b1b9c0Schristos }
97e2b1b9c0Schristos 
98e2b1b9c0Schristos int
isc_pool_count(isc_pool_t * pool)99e2b1b9c0Schristos isc_pool_count(isc_pool_t *pool) {
100e2b1b9c0Schristos 	REQUIRE(pool != NULL);
101e2b1b9c0Schristos 	return (pool->count);
102e2b1b9c0Schristos }
103e2b1b9c0Schristos 
104e2b1b9c0Schristos isc_result_t
isc_pool_expand(isc_pool_t ** sourcep,unsigned int count,isc_pool_t ** targetp)105e2b1b9c0Schristos isc_pool_expand(isc_pool_t **sourcep, unsigned int count,
1069742fdb4Schristos 		isc_pool_t **targetp) {
107e2b1b9c0Schristos 	isc_result_t result;
108e2b1b9c0Schristos 	isc_pool_t *pool;
109e2b1b9c0Schristos 
110e2b1b9c0Schristos 	REQUIRE(sourcep != NULL && *sourcep != NULL);
111e2b1b9c0Schristos 	REQUIRE(targetp != NULL && *targetp == NULL);
112e2b1b9c0Schristos 
113e2b1b9c0Schristos 	pool = *sourcep;
1149742fdb4Schristos 	*sourcep = NULL;
115e2b1b9c0Schristos 	if (count > pool->count) {
116e2b1b9c0Schristos 		isc_pool_t *newpool = NULL;
117e2b1b9c0Schristos 		unsigned int i;
118e2b1b9c0Schristos 
119e2b1b9c0Schristos 		/* Allocate a new pool structure */
120e2b1b9c0Schristos 		result = alloc_pool(pool->mctx, count, &newpool);
1219742fdb4Schristos 		if (result != ISC_R_SUCCESS) {
122e2b1b9c0Schristos 			return (result);
1239742fdb4Schristos 		}
124e2b1b9c0Schristos 
125e2b1b9c0Schristos 		newpool->free = pool->free;
126e2b1b9c0Schristos 		newpool->init = pool->init;
127e2b1b9c0Schristos 		newpool->initarg = pool->initarg;
128e2b1b9c0Schristos 
129f2e20987Schristos 		/* Populate the new entries */
130f2e20987Schristos 		for (i = pool->count; i < count; i++) {
131f2e20987Schristos 			result = newpool->init(&newpool->pool[i],
132f2e20987Schristos 					       newpool->initarg);
133f2e20987Schristos 			if (result != ISC_R_SUCCESS) {
134f2e20987Schristos 				isc_pool_destroy(&newpool);
135f2e20987Schristos 				return (result);
136f2e20987Schristos 			}
137f2e20987Schristos 		}
138f2e20987Schristos 
139e2b1b9c0Schristos 		/* Copy over the objects from the old pool */
140e2b1b9c0Schristos 		for (i = 0; i < pool->count; i++) {
141e2b1b9c0Schristos 			newpool->pool[i] = pool->pool[i];
142e2b1b9c0Schristos 			pool->pool[i] = NULL;
143e2b1b9c0Schristos 		}
144e2b1b9c0Schristos 
145e2b1b9c0Schristos 		isc_pool_destroy(&pool);
146e2b1b9c0Schristos 		pool = newpool;
147e2b1b9c0Schristos 	}
148e2b1b9c0Schristos 
149e2b1b9c0Schristos 	*targetp = pool;
150e2b1b9c0Schristos 	return (ISC_R_SUCCESS);
151e2b1b9c0Schristos }
152e2b1b9c0Schristos 
153e2b1b9c0Schristos void
isc_pool_destroy(isc_pool_t ** poolp)154e2b1b9c0Schristos isc_pool_destroy(isc_pool_t **poolp) {
155e2b1b9c0Schristos 	unsigned int i;
156e2b1b9c0Schristos 	isc_pool_t *pool = *poolp;
1579742fdb4Schristos 	*poolp = NULL;
158e2b1b9c0Schristos 	for (i = 0; i < pool->count; i++) {
1599742fdb4Schristos 		if (pool->free != NULL && pool->pool[i] != NULL) {
160e2b1b9c0Schristos 			pool->free(&pool->pool[i]);
161e2b1b9c0Schristos 		}
1629742fdb4Schristos 	}
163e2b1b9c0Schristos 	isc_mem_put(pool->mctx, pool->pool, pool->count * sizeof(void *));
164e2b1b9c0Schristos 	isc_mem_putanddetach(&pool->mctx, pool, sizeof(*pool));
165e2b1b9c0Schristos }
166