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