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