summaryrefslogtreecommitdiff
path: root/lib/isc/include/isc/mem.h
blob: a3bb16ec8c6711d47ece87fdcb379d0826534cd0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
/*
 * Copyright (C) 1997-2000  Internet Software Consortium.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* $Id: mem.h,v 1.45 2000/12/01 00:32:02 gson Exp $ */

#ifndef ISC_MEM_H
#define ISC_MEM_H 1

#include <stdio.h>

#include <isc/lang.h>
#include <isc/mutex.h>
#include <isc/types.h>

ISC_LANG_BEGINDECLS

#define ISC_MEM_LOWATER 0
#define ISC_MEM_HIWATER 1
typedef void (*isc_mem_water_t)(void *, int);

typedef void * (*isc_memalloc_t)(void *, size_t);
typedef void (*isc_memfree_t)(void *, void *);

/*
 * ISC_MEM_DEBUG is enabled by default; set ISC_MEM_DEBUG=0 to disable it.
 */
#ifndef ISC_MEM_DEBUG
#define ISC_MEM_DEBUG 1
#endif

/*
 * Define ISC_MEM_TRACKLINES=1 to turn on detailed tracing of memory allocation
 * and freeing by file and line number.
 */
#ifndef ISC_MEM_TRACKLINES
#define ISC_MEM_TRACKLINES 0
#endif

/*
 * Define ISC_MEM_CHECKOVERRUN=1 to turn on checks for using memory outside
 * the requested space.  This will increase the size of each allocation.
 */
#ifndef ISC_MEM_CHECKOVERRUN
#define ISC_MEM_CHECKOVERRUN 0
#endif

/*
 * Define ISC_MEM_FILL to fill each block of memory returned to the system
 * with the byte string '0xbe'.  This helps track down uninitialized pointers
 * and the like.  On freeing memory, the space is filled with '0xde' for
 * the same reasons.
 */
#ifndef ISC_MEM_FILL
#define ISC_MEM_FILL 1
#endif

/*
 * Define this to turn on memory pool names.
 */
#ifndef ISC_MEMPOOL_NAMES
#define ISC_MEMPOOL_NAMES 1
#endif

/*
 * _DEBUGTRACE
 *	log (to isc_lctx) each allocation and free.
 *
 * _DEBUGRECORD
 *	remember each allocation, and match them up on free.  Crash if
 *	a free doesn't match an allocation
 */
extern unsigned int isc_mem_debugging;
#define ISC_MEM_DEBUGTRACE		0x00000001U
#define ISC_MEM_DEBUGRECORD		0x00000002U

#if ISC_MEM_TRACKLINES
#define _ISC_MEM_FILELINE	, __FILE__, __LINE__
#define _ISC_MEM_FLARG		, const char *, int
#else
#define _ISC_MEM_FILELINE
#define _ISC_MEM_FLARG
#endif

#define isc_mem_get(c, s)	isc__mem_get((c), (s) _ISC_MEM_FILELINE)
#define isc_mem_allocate(c, s)	isc__mem_allocate((c), (s) _ISC_MEM_FILELINE)
#define isc_mem_strdup(c, p)	isc__mem_strdup((c), (p) _ISC_MEM_FILELINE)
#define isc_mempool_get(c)	isc__mempool_get((c) _ISC_MEM_FILELINE)

/*
 * isc_mem_putanddetach() is a convienence function for use where you
 * have a structure with an attached memory context.
 *
 * Given:
 *
 * struct {
 *	...
 *	isc_mem_t *mctx;
 *	...
 * } *ptr;
 *
 * isc_mem_t *mctx;
 *
 * isc_mem_putanddetach(&ptr->mctx, ptr, sizeof(*ptr));
 *
 * is the equivalent of:
 *
 * mctx = NULL;
 * isc_mem_attach(ptr->mctx, &mctx);
 * isc_mem_detach(&ptr->mctx);
 * isc_mem_put(mctx, ptr, sizeof(*ptr));
 * isc_mem_detach(&mctx);
 */

#if ISC_MEM_DEBUG
#define isc_mem_put(c, p, s) \
	do { \
		isc__mem_put((c), (p), (s) _ISC_MEM_FILELINE); \
		(p) = NULL; \
	} while (0)
#define isc_mem_putanddetach(c, p, s) \
	do { \
		isc__mem_putanddetach((c), (p), (s) _ISC_MEM_FILELINE); \
		(p) = NULL; \
	} while (0)
#define isc_mem_free(c, p) \
	do { \
		isc__mem_free((c), (p) _ISC_MEM_FILELINE); \
		(p) = NULL; \
	} while (0)
#define isc_mempool_put(c, p) \
	do { \
		isc__mempool_put((c), (p) _ISC_MEM_FILELINE); \
		(p) = NULL; \
	} while (0)
#else
#define isc_mem_put(c, p, s)	isc__mem_put((c), (p), (s) _ISC_MEM_FILELINE)
#define isc_mem_putanddetach(c, p, s) \
	isc__mem_putanddetach((c), (p), (s) _ISC_MEM_FILELINE)
#define isc_mem_free(c, p)	isc__mem_free((c), (p) _ISC_MEM_FILELINE)
#define isc_mempool_put(c, p)	isc__mempool_put((c), (p) _ISC_MEM_FILELINE)
#endif

isc_result_t			isc_mem_create(size_t, size_t, isc_mem_t **);
void				isc_mem_attach(isc_mem_t *, isc_mem_t **);
void				isc_mem_detach(isc_mem_t **);
void				isc_mem_destroy(isc_mem_t **);
isc_result_t			isc_mem_ondestroy(isc_mem_t *ctx,
						  isc_task_t *task,
						  isc_event_t **event);
void *				isc__mem_get(isc_mem_t *, size_t
					     _ISC_MEM_FLARG);
void 				isc__mem_putanddetach(isc_mem_t **, void *,
						      size_t _ISC_MEM_FLARG);
void 				isc__mem_put(isc_mem_t *, void *,
					     size_t _ISC_MEM_FLARG);
isc_result_t			isc_mem_preallocate(isc_mem_t *);
void 				isc_mem_stats(isc_mem_t *, FILE *);
isc_boolean_t			isc_mem_valid(isc_mem_t *, void *);
void *				isc__mem_allocate(isc_mem_t *, size_t
						  _ISC_MEM_FLARG);
void				isc__mem_free(isc_mem_t *, void *
					      _ISC_MEM_FLARG);
char *				isc__mem_strdup(isc_mem_t *, const char *
						_ISC_MEM_FLARG);
void				isc_mem_setdestroycheck(isc_mem_t *,
							isc_boolean_t);
void				isc_mem_setsplit(isc_mem_t *, isc_boolean_t);
void				isc_mem_setquota(isc_mem_t *, size_t);
size_t				isc_mem_getquota(isc_mem_t *);
size_t				isc_mem_inuse(isc_mem_t *);

isc_result_t			isc_mem_createx(size_t, size_t,
						isc_memalloc_t memalloc,
						isc_memfree_t memfree,
						void *arg, isc_mem_t **);
isc_result_t			isc_mem_restore(isc_mem_t *);

void
isc_mem_setwater(isc_mem_t *mctx, isc_mem_water_t water, void *water_arg,
		 size_t hiwater, size_t lowater);
/*
 * Set high and low water marks for this memory context.  When the memory
 * usage of 'mctx' exceeds 'hiwater', '(water)(water_arg, ISC_MEM_HIWATER)'
 * will be called.  When the usage drops below 'lowater', 'water' will
 * again be called, this time with ISC_MEM_LOWATER.
 *
 * Requires:
 * 	If 'water' is NULL then 'water_arg', 'hi_water' and 'lo_water' are
 *	ignored and the state is reset.  Otherwise, requires
 *
 *	'water' to point to a valid function.
 *	'hi_water > lo_water'
 *	'lo_water != 0'
 *	'hi_water != 0'
 */

/*
 * Memory pools
 */

/*
 * Internal (but public) functions.  Don't call these from application
 * code.  Use isc_mempool_get() and isc_mempool_put() instead.
 */
void *		isc__mempool_get(isc_mempool_t * _ISC_MEM_FLARG);
void 		isc__mempool_put(isc_mempool_t *, void * _ISC_MEM_FLARG);

isc_result_t
isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp);
/*
 * Create a memory pool.
 *
 * Requires:
 *	mctx is a valid memory context.
 *	size > 0
 *	mpctxp != NULL and *mpctxp == NULL
 *
 * Defaults:
 *	maxalloc = UINT_MAX
 *	freemax = 1
 *	fillcount = 1
 *
 * Returns:
 *	ISC_R_NOMEMORY		-- not enough memory to create pool
 *	ISC_R_SUCCESS		-- all is well.
 */

void
isc_mempool_destroy(isc_mempool_t **mpctxp);
/*
 * Destroy a memory pool.
 *
 * Requires:
 *	mpctxp != NULL && *mpctxp is a valid pool.
 *	The pool has no un"put" allocations outstanding
 */

void
isc_mempool_setname(isc_mempool_t *mpctx, const char *name);
/*
 * Associate a name with a memory pool.  At most 15 characters may be used.
 *
 * Requires:
 *	mpctx is a valid pool.
 *	name != NULL;
 */

void
isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock);
/*
 * Associate a lock with this memory pool.
 *
 * This lock is used when getting or putting items using this memory pool,
 * and it is also used to set or get internal state via the isc_mempool_get*()
 * and isc_mempool_set*() set of functions.
 *
 * Mutiple pools can each share a single lock.  For instance, if "manager"
 * type object contained pools for various sizes of events, and each of
 * these pools used a common lock.  Note that this lock must NEVER be used
 * by other than mempool routines once it is given to a pool, since that can
 * easily cause double locking.
 *
 * Requires:
 *
 *	mpctpx is a valid pool.
 *
 *	lock != NULL.
 *
 *	No previous lock is assigned to this pool.
 *
 *	The lock is initialized before calling this function via the normal
 *	means of doing that.
 */

/*
 * The following functions get/set various parameters.  Note that due to
 * the unlocked nature of pools these are potentially random values unless
 * the imposed externally provided locking protocols are followed.
 *
 * Also note that the quota limits will not always take immediate effect.
 * For instance, setting "maxalloc" to a number smaller than the currently
 * allocated count is permitted.  New allocations will be refused until
 * the count drops below this threshold.
 *
 * All functions require (in addition to other requirements):
 *	mpctx is a valid memory pool
 */

unsigned int
isc_mempool_getfreemax(isc_mempool_t *mpctx);
/*
 * Returns the maximum allowed size of the free list.
 */

void
isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit);
/*
 * Sets the maximum allowed size of the free list.
 */

unsigned int
isc_mempool_getfreecount(isc_mempool_t *mpctx);
/*
 * Returns current size of the free list.
 */

unsigned int
isc_mempool_getmaxalloc(isc_mempool_t *mpctx);
/*
 * Returns the maximum allowed number of allocations.
 */

void
isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit);
/*
 * Sets the maximum allowed number of allocations.
 *
 * Additional requirements:
 *	limit > 0
 */

unsigned int
isc_mempool_getallocated(isc_mempool_t *mpctx);
/*
 * Returns the number of items allocated from this pool.
 */

unsigned int
isc_mempool_getfillcount(isc_mempool_t *mpctx);
/*
 * Returns the number of items allocated as a block from the parent memory
 * context when the free list is empty.
 */

void
isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
/*
 * Sets the fillcount.
 *
 * Additional requirements:
 *	limit > 0
 */

ISC_LANG_ENDDECLS

#endif /* ISC_MEM_H */