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