1 /*
2 * Copyright (C) 2009, 2010 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: mem_api.c,v 1.8 2010/08/12 21:30:26 jinmei Exp $ */
18
19 #include <config.h>
20
21 #include <isc/magic.h>
22 #include <isc/mem.h>
23 #include <isc/once.h>
24 #include <isc/util.h>
25
26 #if ISC_MEM_TRACKLINES
27 #define FLARG_PASS , file, line
28 #define FLARG , const char *file, unsigned int line
29 #else
30 #define FLARG_PASS
31 #define FLARG
32 #endif
33
34 static isc_mutex_t createlock;
35 static isc_once_t once = ISC_ONCE_INIT;
36 static isc_memcreatefunc_t mem_createfunc = NULL;
37
38 static void
initialize(void)39 initialize(void) {
40 RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
41 }
42
43 isc_result_t
isc_mem_register(isc_memcreatefunc_t createfunc)44 isc_mem_register(isc_memcreatefunc_t createfunc) {
45 isc_result_t result = ISC_R_SUCCESS;
46
47 RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
48
49 LOCK(&createlock);
50 if (mem_createfunc == NULL)
51 mem_createfunc = createfunc;
52 else
53 result = ISC_R_EXISTS;
54 UNLOCK(&createlock);
55
56 return (result);
57 }
58
59 isc_result_t
isc_mem_create(size_t init_max_size,size_t target_size,isc_mem_t ** mctxp)60 isc_mem_create(size_t init_max_size, size_t target_size, isc_mem_t **mctxp) {
61 isc_result_t result;
62
63 LOCK(&createlock);
64
65 REQUIRE(mem_createfunc != NULL);
66 result = (*mem_createfunc)(init_max_size, target_size, mctxp,
67 ISC_MEMFLAG_DEFAULT);
68
69 UNLOCK(&createlock);
70
71 return (result);
72 }
73
74 isc_result_t
isc_mem_create2(size_t init_max_size,size_t target_size,isc_mem_t ** mctxp,unsigned int flags)75 isc_mem_create2(size_t init_max_size, size_t target_size, isc_mem_t **mctxp,
76 unsigned int flags)
77 {
78 isc_result_t result;
79
80 LOCK(&createlock);
81
82 REQUIRE(mem_createfunc != NULL);
83 result = (*mem_createfunc)(init_max_size, target_size, mctxp, flags);
84
85 UNLOCK(&createlock);
86
87 return (result);
88 }
89
90 void
isc_mem_attach(isc_mem_t * source,isc_mem_t ** targetp)91 isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
92 REQUIRE(ISCAPI_MCTX_VALID(source));
93 REQUIRE(targetp != NULL && *targetp == NULL);
94
95 source->methods->attach(source, targetp);
96
97 ENSURE(*targetp == source);
98 }
99
100 void
isc_mem_detach(isc_mem_t ** mctxp)101 isc_mem_detach(isc_mem_t **mctxp) {
102 REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
103
104 (*mctxp)->methods->detach(mctxp);
105
106 ENSURE(*mctxp == NULL);
107 }
108
109 void
isc_mem_destroy(isc_mem_t ** mctxp)110 isc_mem_destroy(isc_mem_t **mctxp) {
111 REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
112
113 (*mctxp)->methods->destroy(mctxp);
114
115 ENSURE(*mctxp == NULL);
116 }
117
118 void *
isc__mem_get(isc_mem_t * mctx,size_t size FLARG)119 isc__mem_get(isc_mem_t *mctx, size_t size FLARG) {
120 REQUIRE(ISCAPI_MCTX_VALID(mctx));
121
122 return (mctx->methods->memget(mctx, size FLARG_PASS));
123 }
124
125 void
isc__mem_put(isc_mem_t * mctx,void * ptr,size_t size FLARG)126 isc__mem_put(isc_mem_t *mctx, void *ptr, size_t size FLARG) {
127 REQUIRE(ISCAPI_MCTX_VALID(mctx));
128
129 mctx->methods->memput(mctx, ptr, size FLARG_PASS);
130 }
131
132 void
isc__mem_putanddetach(isc_mem_t ** mctxp,void * ptr,size_t size FLARG)133 isc__mem_putanddetach(isc_mem_t **mctxp, void *ptr, size_t size FLARG) {
134 REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
135
136 (*mctxp)->methods->memputanddetach(mctxp, ptr, size FLARG_PASS);
137
138 /*
139 * XXX: We cannot always ensure *mctxp == NULL here
140 * (see lib/isc/mem.c).
141 */
142 }
143
144 void *
isc__mem_allocate(isc_mem_t * mctx,size_t size FLARG)145 isc__mem_allocate(isc_mem_t *mctx, size_t size FLARG) {
146 REQUIRE(ISCAPI_MCTX_VALID(mctx));
147
148 return (mctx->methods->memallocate(mctx, size FLARG_PASS));
149 }
150
151 void *
isc__mem_reallocate(isc_mem_t * mctx,void * ptr,size_t size FLARG)152 isc__mem_reallocate(isc_mem_t *mctx, void *ptr, size_t size FLARG) {
153 REQUIRE(ISCAPI_MCTX_VALID(mctx));
154
155 return (mctx->methods->memreallocate(mctx, ptr, size FLARG_PASS));
156 }
157
158 char *
isc__mem_strdup(isc_mem_t * mctx,const char * s FLARG)159 isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
160 REQUIRE(ISCAPI_MCTX_VALID(mctx));
161
162 return (mctx->methods->memstrdup(mctx, s FLARG_PASS));
163 }
164
165 void
isc__mem_free(isc_mem_t * mctx,void * ptr FLARG)166 isc__mem_free(isc_mem_t *mctx, void *ptr FLARG) {
167 REQUIRE(ISCAPI_MCTX_VALID(mctx));
168
169 mctx->methods->memfree(mctx, ptr FLARG_PASS);
170 }
171
172 void
isc_mem_setdestroycheck(isc_mem_t * mctx,isc_boolean_t flag)173 isc_mem_setdestroycheck(isc_mem_t *mctx, isc_boolean_t flag) {
174 REQUIRE(ISCAPI_MCTX_VALID(mctx));
175
176 mctx->methods->setdestroycheck(mctx, flag);
177 }
178
179 void
isc_mem_setwater(isc_mem_t * ctx,isc_mem_water_t water,void * water_arg,size_t hiwater,size_t lowater)180 isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
181 size_t hiwater, size_t lowater)
182 {
183 REQUIRE(ISCAPI_MCTX_VALID(ctx));
184
185 ctx->methods->setwater(ctx, water, water_arg, hiwater, lowater);
186 }
187
188 void
isc_mem_waterack(isc_mem_t * ctx,int flag)189 isc_mem_waterack(isc_mem_t *ctx, int flag) {
190 REQUIRE(ISCAPI_MCTX_VALID(ctx));
191
192 ctx->methods->waterack(ctx, flag);
193 }
194
195 size_t
isc_mem_inuse(isc_mem_t * mctx)196 isc_mem_inuse(isc_mem_t *mctx) {
197 REQUIRE(ISCAPI_MCTX_VALID(mctx));
198
199 return (mctx->methods->inuse(mctx));
200 }
201
202 isc_boolean_t
isc_mem_isovermem(isc_mem_t * mctx)203 isc_mem_isovermem(isc_mem_t *mctx) {
204 REQUIRE(ISCAPI_MCTX_VALID(mctx));
205
206 return (mctx->methods->isovermem(mctx));
207 }
208
209 void
isc_mem_setname(isc_mem_t * mctx,const char * name,void * tag)210 isc_mem_setname(isc_mem_t *mctx, const char *name, void *tag) {
211 REQUIRE(ISCAPI_MCTX_VALID(mctx));
212
213 UNUSED(name);
214 UNUSED(tag);
215
216 return;
217 }
218
219 const char *
isc_mem_getname(isc_mem_t * mctx)220 isc_mem_getname(isc_mem_t *mctx) {
221 REQUIRE(ISCAPI_MCTX_VALID(mctx));
222
223 return ("");
224 }
225
226 void *
isc_mem_gettag(isc_mem_t * mctx)227 isc_mem_gettag(isc_mem_t *mctx) {
228 REQUIRE(ISCAPI_MCTX_VALID(mctx));
229
230 return (NULL);
231 }
232
233 isc_result_t
isc_mempool_create(isc_mem_t * mctx,size_t size,isc_mempool_t ** mpctxp)234 isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
235 REQUIRE(ISCAPI_MCTX_VALID(mctx));
236
237 return (mctx->methods->mpcreate(mctx, size, mpctxp));
238 }
239
240 void
isc_mempool_destroy(isc_mempool_t ** mpctxp)241 isc_mempool_destroy(isc_mempool_t **mpctxp) {
242 REQUIRE(mpctxp != NULL && ISCAPI_MPOOL_VALID(*mpctxp));
243
244 (*mpctxp)->methods->destroy(mpctxp);
245
246 ENSURE(*mpctxp == NULL);
247 }
248
249 void *
isc__mempool_get(isc_mempool_t * mpctx FLARG)250 isc__mempool_get(isc_mempool_t *mpctx FLARG) {
251 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
252
253 return (mpctx->methods->get(mpctx FLARG_PASS));
254 }
255
256 void
isc__mempool_put(isc_mempool_t * mpctx,void * mem FLARG)257 isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
258 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
259
260 mpctx->methods->put(mpctx, mem FLARG_PASS);
261 }
262
263 unsigned int
isc_mempool_getallocated(isc_mempool_t * mpctx)264 isc_mempool_getallocated(isc_mempool_t *mpctx) {
265 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
266
267 return (mpctx->methods->getallocated(mpctx));
268 }
269
270 void
isc_mempool_setmaxalloc(isc_mempool_t * mpctx,unsigned int limit)271 isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
272 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
273
274 mpctx->methods->setmaxalloc(mpctx, limit);
275 }
276
277 void
isc_mempool_setfreemax(isc_mempool_t * mpctx,unsigned int limit)278 isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
279 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
280
281 mpctx->methods->setfreemax(mpctx, limit);
282 }
283
284 void
isc_mempool_setname(isc_mempool_t * mpctx,const char * name)285 isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
286 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
287
288 mpctx->methods->setname(mpctx, name);
289 }
290
291 void
isc_mempool_associatelock(isc_mempool_t * mpctx,isc_mutex_t * lock)292 isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
293 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
294
295 mpctx->methods->associatelock(mpctx, lock);
296 }
297
298 void
isc_mempool_setfillcount(isc_mempool_t * mpctx,unsigned int limit)299 isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
300 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
301
302 mpctx->methods->setfillcount(mpctx, limit);
303 }
304