df925e6c66d45d960fbac0383169763967d2111cEvan Hunt/*
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 2013, 2015, 2016 Internet Systems Consortium, Inc. ("ISC")
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt */
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt/* $Id$ */
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt/*! \file */
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt#include <config.h>
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt#include <string.h>
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt#include <isc/mem.h>
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt#include <isc/random.h>
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt#include <isc/pool.h>
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt#include <isc/util.h>
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt/***
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt *** Types.
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt ***/
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Huntstruct isc_pool {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_mem_t * mctx;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt unsigned int count;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_pooldeallocator_t free;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_poolinitializer_t init;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt void * initarg;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt void ** pool;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt};
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt/***
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt *** Functions.
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt ***/
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Huntstatic isc_result_t
df925e6c66d45d960fbac0383169763967d2111cEvan Huntalloc_pool(isc_mem_t *mctx, unsigned int count, isc_pool_t **poolp) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_pool_t *pool;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool = isc_mem_get(mctx, sizeof(*pool));
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt if (pool == NULL)
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (ISC_R_NOMEMORY);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool->count = count;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool->free = NULL;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool->init = NULL;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool->initarg = NULL;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool->mctx = NULL;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_mem_attach(mctx, &pool->mctx);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool->pool = isc_mem_get(mctx, count * sizeof(void *));
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt if (pool->pool == NULL) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_mem_put(mctx, pool, sizeof(*pool));
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (ISC_R_NOMEMORY);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt }
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt memset(pool->pool, 0, count * sizeof(void *));
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt *poolp = pool;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (ISC_R_SUCCESS);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt}
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Huntisc_result_t
573d78f3d53859bc01ce5d5cebbaac9b8b90bfbaTinderbox Userisc_pool_create(isc_mem_t *mctx, unsigned int count,
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews isc_pooldeallocator_t release,
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_poolinitializer_t init, void *initarg,
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_pool_t **poolp)
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt{
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_pool_t *pool = NULL;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_result_t result;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt unsigned int i;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt INSIST(count > 0);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt /* Allocate the pool structure */
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt result = alloc_pool(mctx, count, &pool);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt if (result != ISC_R_SUCCESS)
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (result);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews pool->free = release;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool->init = init;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool->initarg = initarg;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt /* Populate the pool */
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt for (i = 0; i < count; i++) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt result = init(&pool->pool[i], initarg);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt if (result != ISC_R_SUCCESS) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_pool_destroy(&pool);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (result);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt }
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt }
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt *poolp = pool;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (ISC_R_SUCCESS);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt}
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Huntvoid *
df925e6c66d45d960fbac0383169763967d2111cEvan Huntisc_pool_get(isc_pool_t *pool) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_uint32_t i;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_random_get(&i);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (pool->pool[i % pool->count]);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt}
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Huntint
df925e6c66d45d960fbac0383169763967d2111cEvan Huntisc_pool_count(isc_pool_t *pool) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt REQUIRE(pool != NULL);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (pool->count);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt}
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Huntisc_result_t
df925e6c66d45d960fbac0383169763967d2111cEvan Huntisc_pool_expand(isc_pool_t **sourcep, unsigned int count,
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_pool_t **targetp)
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt{
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_result_t result;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_pool_t *pool;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt REQUIRE(sourcep != NULL && *sourcep != NULL);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt REQUIRE(targetp != NULL && *targetp == NULL);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool = *sourcep;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt if (count > pool->count) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_pool_t *newpool = NULL;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt unsigned int i;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt /* Allocate a new pool structure */
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt result = alloc_pool(pool->mctx, count, &newpool);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt if (result != ISC_R_SUCCESS)
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (result);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt newpool->free = pool->free;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt newpool->init = pool->init;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt newpool->initarg = pool->initarg;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt /* Copy over the objects from the old pool */
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt for (i = 0; i < pool->count; i++) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt newpool->pool[i] = pool->pool[i];
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool->pool[i] = NULL;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt }
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt /* Populate the new entries */
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt for (i = pool->count; i < count; i++) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt result = pool->init(&newpool->pool[i], pool->initarg);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt if (result != ISC_R_SUCCESS) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_pool_destroy(&pool);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (result);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt }
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt }
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_pool_destroy(&pool);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool = newpool;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt }
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt *sourcep = NULL;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt *targetp = pool;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt return (ISC_R_SUCCESS);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt}
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt
df925e6c66d45d960fbac0383169763967d2111cEvan Huntvoid
df925e6c66d45d960fbac0383169763967d2111cEvan Huntisc_pool_destroy(isc_pool_t **poolp) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt unsigned int i;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_pool_t *pool = *poolp;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt for (i = 0; i < pool->count; i++) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt if (pool->free != NULL && pool->pool[i] != NULL)
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt pool->free(&pool->pool[i]);
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt }
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_mem_put(pool->mctx, pool->pool, pool->count * sizeof(void *));
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_mem_putanddetach(&pool->mctx, pool, sizeof(*pool));
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt *poolp = NULL;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt}