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
34static isc_mutex_t createlock;
35static isc_once_t once = ISC_ONCE_INIT;
36static isc_memcreatefunc_t mem_createfunc = NULL;
37
38static void
39initialize(void) {
40	RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
41}
42
43isc_result_t
44isc_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
59isc_result_t
60isc_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
74isc_result_t
75isc_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
90void
91isc_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
100void
101isc_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
109void
110isc_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
118void *
119isc__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
125void
126isc__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
132void
133isc__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
144void *
145isc__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
151void *
152isc__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
158char *
159isc__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
165void
166isc__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
172void
173isc_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
179void
180isc_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
188void
189isc_mem_waterack(isc_mem_t *ctx, int flag) {
190	REQUIRE(ISCAPI_MCTX_VALID(ctx));
191
192	ctx->methods->waterack(ctx, flag);
193}
194
195size_t
196isc_mem_inuse(isc_mem_t *mctx) {
197	REQUIRE(ISCAPI_MCTX_VALID(mctx));
198
199	return (mctx->methods->inuse(mctx));
200}
201
202isc_boolean_t
203isc_mem_isovermem(isc_mem_t *mctx) {
204	REQUIRE(ISCAPI_MCTX_VALID(mctx));
205
206	return (mctx->methods->isovermem(mctx));
207}
208
209void
210isc_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
219const char *
220isc_mem_getname(isc_mem_t *mctx) {
221	REQUIRE(ISCAPI_MCTX_VALID(mctx));
222
223	return ("");
224}
225
226void *
227isc_mem_gettag(isc_mem_t *mctx) {
228	REQUIRE(ISCAPI_MCTX_VALID(mctx));
229
230	return (NULL);
231}
232
233isc_result_t
234isc_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
240void
241isc_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
249void *
250isc__mempool_get(isc_mempool_t *mpctx FLARG) {
251	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
252
253	return (mpctx->methods->get(mpctx FLARG_PASS));
254}
255
256void
257isc__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
263unsigned int
264isc_mempool_getallocated(isc_mempool_t *mpctx) {
265	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
266
267	return (mpctx->methods->getallocated(mpctx));
268}
269
270void
271isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
272	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
273
274	mpctx->methods->setmaxalloc(mpctx, limit);
275}
276
277void
278isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
279	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
280
281	mpctx->methods->setfreemax(mpctx, limit);
282}
283
284void
285isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
286	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
287
288	mpctx->methods->setname(mpctx, name);
289}
290
291void
292isc_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
298void
299isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
300	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
301
302	mpctx->methods->setfillcount(mpctx, limit);
303}
304