xref: /netbsd-src/external/mpl/dhcp/bind/dist/lib/isc/include/isc/mem.h (revision 4afad4b7fa6d4a0d3dedf41d1587a7250710ae54)
1 /*	$NetBSD: mem.h,v 1.1 2024/02/18 20:57:53 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 #ifndef ISC_MEM_H
17 #define ISC_MEM_H 1
18 
19 /*! \file isc/mem.h */
20 
21 #include <stdbool.h>
22 #include <stdio.h>
23 
24 #include <isc/lang.h>
25 #include <isc/mutex.h>
26 #include <isc/platform.h>
27 #include <isc/types.h>
28 #include <isc/util.h>
29 
30 ISC_LANG_BEGINDECLS
31 
32 #define ISC_MEM_LOWATER 0
33 #define ISC_MEM_HIWATER 1
34 typedef void (*isc_mem_water_t)(void *, int);
35 
36 /*%
37  * Define ISC_MEM_TRACKLINES=1 to turn on detailed tracing of memory
38  * allocation and freeing by file and line number.
39  */
40 #ifndef ISC_MEM_TRACKLINES
41 #define ISC_MEM_TRACKLINES 1
42 #endif /* ifndef ISC_MEM_TRACKLINES */
43 
44 /*%
45  * Define ISC_MEM_CHECKOVERRUN=1 to turn on checks for using memory outside
46  * the requested space.  This will increase the size of each allocation.
47  *
48  * If we are performing a Coverity static analysis then ISC_MEM_CHECKOVERRUN
49  * can hide bugs that would otherwise discovered so force to zero.
50  */
51 #ifdef __COVERITY__
52 #undef ISC_MEM_CHECKOVERRUN
53 #define ISC_MEM_CHECKOVERRUN 0
54 #endif /* ifdef __COVERITY__ */
55 #ifndef ISC_MEM_CHECKOVERRUN
56 #define ISC_MEM_CHECKOVERRUN 1
57 #endif /* ifndef ISC_MEM_CHECKOVERRUN */
58 
59 /*%
60  * Define ISC_MEMPOOL_NAMES=1 to make memory pools store a symbolic
61  * name so that the leaking pool can be more readily identified in
62  * case of a memory leak.
63  */
64 #ifndef ISC_MEMPOOL_NAMES
65 #define ISC_MEMPOOL_NAMES 1
66 #endif /* ifndef ISC_MEMPOOL_NAMES */
67 
68 LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging;
69 LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_defaultflags;
70 
71 /*@{*/
72 #define ISC_MEM_DEBUGTRACE  0x00000001U
73 #define ISC_MEM_DEBUGRECORD 0x00000002U
74 #define ISC_MEM_DEBUGUSAGE  0x00000004U
75 #define ISC_MEM_DEBUGSIZE   0x00000008U
76 #define ISC_MEM_DEBUGCTX    0x00000010U
77 #define ISC_MEM_DEBUGALL    0x0000001FU
78 /*!<
79  * The variable isc_mem_debugging holds a set of flags for
80  * turning certain memory debugging options on or off at
81  * runtime.  It is initialized to the value ISC_MEM_DEGBUGGING,
82  * which is 0 by default but may be overridden at compile time.
83  * The following flags can be specified:
84  *
85  * \li #ISC_MEM_DEBUGTRACE
86  *	Log each allocation and free to isc_lctx.
87  *
88  * \li #ISC_MEM_DEBUGRECORD
89  *	Remember each allocation, and match them up on free.
90  *	Crash if a free doesn't match an allocation.
91  *
92  * \li #ISC_MEM_DEBUGUSAGE
93  *	If a hi_water mark is set, print the maximum inuse memory
94  *	every time it is raised once it exceeds the hi_water mark.
95  *
96  * \li #ISC_MEM_DEBUGSIZE
97  *	Check the size argument being passed to isc_mem_put() matches
98  *	that passed to isc_mem_get().
99  *
100  * \li #ISC_MEM_DEBUGCTX
101  *	Check the mctx argument being passed to isc_mem_put() matches
102  *	that passed to isc_mem_get().
103  */
104 /*@}*/
105 
106 #if ISC_MEM_TRACKLINES
107 #define _ISC_MEM_FILELINE , __FILE__, __LINE__
108 #define _ISC_MEM_FLARG	  , const char *, unsigned int
109 #else /* if ISC_MEM_TRACKLINES */
110 #define _ISC_MEM_FILELINE
111 #define _ISC_MEM_FLARG
112 #endif /* if ISC_MEM_TRACKLINES */
113 
114 /*!
115  * Define ISC_MEM_USE_INTERNAL_MALLOC=1 to use the internal malloc()
116  * implementation in preference to the system one.  The internal malloc()
117  * is very space-efficient, and quite fast on uniprocessor systems.  It
118  * performs poorly on multiprocessor machines.
119  * JT: we can overcome the performance issue on multiprocessor machines
120  * by carefully separating memory contexts.
121  */
122 
123 #if !defined(ISC_MEM_USE_INTERNAL_MALLOC) && !__SANITIZE_ADDRESS__
124 #define ISC_MEM_USE_INTERNAL_MALLOC 0
125 #endif /* ifndef ISC_MEM_USE_INTERNAL_MALLOC */
126 
127 /*
128  * Flags for isc_mem_create() calls.
129  */
130 #define ISC_MEMFLAG_RESERVED 0x00000001 /* reserved, obsoleted, don't use */
131 #define ISC_MEMFLAG_INTERNAL 0x00000002 /* use internal malloc */
132 #define ISC_MEMFLAG_FILL \
133 	0x00000004 /* fill with pattern after alloc and frees */
134 
135 /*%
136  * Define ISC_MEM_DEFAULTFILL=1 to turn filling the memory with pattern
137  * after alloc and free.
138  */
139 #if !ISC_MEM_USE_INTERNAL_MALLOC
140 
141 #if ISC_MEM_DEFAULTFILL
142 #define ISC_MEMFLAG_DEFAULT ISC_MEMFLAG_FILL
143 #else /* if ISC_MEM_DEFAULTFILL */
144 #define ISC_MEMFLAG_DEFAULT 0
145 #endif /* if ISC_MEM_DEFAULTFILL */
146 
147 #else /* if !ISC_MEM_USE_INTERNAL_MALLOC */
148 
149 #if ISC_MEM_DEFAULTFILL
150 #define ISC_MEMFLAG_DEFAULT ISC_MEMFLAG_INTERNAL | ISC_MEMFLAG_FILL
151 #else /* if ISC_MEM_DEFAULTFILL */
152 #define ISC_MEMFLAG_DEFAULT ISC_MEMFLAG_INTERNAL
153 #endif /* if ISC_MEM_DEFAULTFILL */
154 
155 #endif /* if !ISC_MEM_USE_INTERNAL_MALLOC */
156 
157 /*%
158  * isc_mem_putanddetach() is a convenience function for use where you
159  * have a structure with an attached memory context.
160  *
161  * Given:
162  *
163  * \code
164  * struct {
165  *	...
166  *	isc_mem_t *mctx;
167  *	...
168  * } *ptr;
169  *
170  * isc_mem_t *mctx;
171  *
172  * isc_mem_putanddetach(&ptr->mctx, ptr, sizeof(*ptr));
173  * \endcode
174  *
175  * is the equivalent of:
176  *
177  * \code
178  * mctx = NULL;
179  * isc_mem_attach(ptr->mctx, &mctx);
180  * isc_mem_detach(&ptr->mctx);
181  * isc_mem_put(mctx, ptr, sizeof(*ptr));
182  * isc_mem_detach(&mctx);
183  * \endcode
184  */
185 
186 /*% memory and memory pool methods */
187 typedef struct isc_memmethods {
188 	void *(*memget)(isc_mem_t *mctx, size_t size _ISC_MEM_FLARG);
189 	void (*memput)(isc_mem_t *mctx, void *ptr, size_t size _ISC_MEM_FLARG);
190 	void (*memputanddetach)(isc_mem_t **mctxp, void *ptr,
191 				size_t size _ISC_MEM_FLARG);
192 	void *(*memallocate)(isc_mem_t *mctx, size_t size _ISC_MEM_FLARG);
193 	void *(*memreallocate)(isc_mem_t *mctx, void *ptr,
194 			       size_t size _ISC_MEM_FLARG);
195 	char *(*memstrdup)(isc_mem_t *mctx, const char *s _ISC_MEM_FLARG);
196 	char *(*memstrndup)(isc_mem_t *mctx, const char *s,
197 			    size_t size _ISC_MEM_FLARG);
198 	void (*memfree)(isc_mem_t *mctx, void *ptr _ISC_MEM_FLARG);
199 } isc_memmethods_t;
200 
201 /*%
202  * This structure is actually just the common prefix of a memory context
203  * implementation's version of an isc_mem_t.
204  * \brief
205  * Direct use of this structure by clients is forbidden.  mctx implementations
206  * may change the structure.  'magic' must be ISCAPI_MCTX_MAGIC for any of the
207  * isc_mem_ routines to work.  mctx implementations must maintain all mctx
208  * invariants.
209  */
210 struct isc_mem {
211 	unsigned int	  impmagic;
212 	unsigned int	  magic;
213 	isc_memmethods_t *methods;
214 };
215 
216 #define ISCAPI_MCTX_MAGIC    ISC_MAGIC('A', 'm', 'c', 'x')
217 #define ISCAPI_MCTX_VALID(m) ((m) != NULL && (m)->magic == ISCAPI_MCTX_MAGIC)
218 
219 /*%
220  * This is the common prefix of a memory pool context.  The same note as
221  * that for the mem structure applies.
222  */
223 struct isc_mempool {
224 	unsigned int impmagic;
225 	unsigned int magic;
226 };
227 
228 #define ISCAPI_MPOOL_MAGIC ISC_MAGIC('A', 'm', 'p', 'l')
229 #define ISCAPI_MPOOL_VALID(mp) \
230 	((mp) != NULL && (mp)->magic == ISCAPI_MPOOL_MAGIC)
231 
232 /*%
233  * These functions are actually implemented in isc__mem_<function>
234  * (two underscores). The single-underscore macros are used to pass
235  * __FILE__ and __LINE__, and in the case of the put functions, to
236  * set the pointer being freed to NULL in the calling function.
237  *
238  * Many of these functions have a further isc___mem_<function>
239  * (three underscores) implementation, which is called indirectly
240  * via the isc_memmethods structure in the mctx so that dynamically
241  * loaded modules can use them even if named is statically linked.
242  */
243 
244 #define ISCMEMFUNC(sfx)	    isc__mem_##sfx
245 #define ISCMEMPOOLFUNC(sfx) isc__mempool_##sfx
246 
247 #define isc_mem_get(c, s)      ISCMEMFUNC(get)((c), (s)_ISC_MEM_FILELINE)
248 #define isc_mem_allocate(c, s) ISCMEMFUNC(allocate)((c), (s)_ISC_MEM_FILELINE)
249 #define isc_mem_reallocate(c, p, s) \
250 	ISCMEMFUNC(reallocate)((c), (p), (s)_ISC_MEM_FILELINE)
251 #define isc_mem_strdup(c, p) ISCMEMFUNC(strdup)((c), (p)_ISC_MEM_FILELINE)
252 #define isc_mem_strndup(c, p, s) \
253 	ISCMEMFUNC(strndup)((c), (p), (s)_ISC_MEM_FILELINE)
254 #define isc_mempool_get(c) ISCMEMPOOLFUNC(get)((c)_ISC_MEM_FILELINE)
255 
256 #define isc_mem_put(c, p, s)                                     \
257 	do {                                                     \
258 		ISCMEMFUNC(put)((c), (p), (s)_ISC_MEM_FILELINE); \
259 		(p) = NULL;                                      \
260 	} while (0)
261 #define isc_mem_putanddetach(c, p, s)                                     \
262 	do {                                                              \
263 		ISCMEMFUNC(putanddetach)((c), (p), (s)_ISC_MEM_FILELINE); \
264 		(p) = NULL;                                               \
265 	} while (0)
266 #define isc_mem_free(c, p)                                   \
267 	do {                                                 \
268 		ISCMEMFUNC(free)((c), (p)_ISC_MEM_FILELINE); \
269 		(p) = NULL;                                  \
270 	} while (0)
271 #define isc_mempool_put(c, p)                                   \
272 	do {                                                    \
273 		ISCMEMPOOLFUNC(put)((c), (p)_ISC_MEM_FILELINE); \
274 		(p) = NULL;                                     \
275 	} while (0)
276 
277 /*@{*/
278 void
279 isc_mem_create(isc_mem_t **mctxp);
280 
281 /*!<
282  * \brief Create a memory context.
283  *
284  * Requires:
285  * mctxp != NULL && *mctxp == NULL */
286 /*@}*/
287 
288 /*@{*/
289 void
290 isc_mem_attach(isc_mem_t *, isc_mem_t **);
291 void
292 isc_mem_detach(isc_mem_t **);
293 /*!<
294  * \brief Attach to / detach from a memory context.
295  *
296  * This is intended for applications that use multiple memory contexts
297  * in such a way that it is not obvious when the last allocations from
298  * a given context has been freed and destroying the context is safe.
299  *
300  * Most applications do not need to call these functions as they can
301  * simply create a single memory context at the beginning of main()
302  * and destroy it at the end of main(), thereby guaranteeing that it
303  * is not destroyed while there are outstanding allocations.
304  */
305 /*@}*/
306 
307 void
308 isc_mem_destroy(isc_mem_t **);
309 /*%<
310  * Destroy a memory context.
311  */
312 
313 void
314 isc_mem_stats(isc_mem_t *mctx, FILE *out);
315 /*%<
316  * Print memory usage statistics for 'mctx' on the stream 'out'.
317  */
318 
319 void
320 isc_mem_setdestroycheck(isc_mem_t *mctx, bool on);
321 /*%<
322  * If 'on' is true, 'mctx' will check for memory leaks when
323  * destroyed and abort the program if any are present.
324  */
325 
326 size_t
327 isc_mem_inuse(isc_mem_t *mctx);
328 /*%<
329  * Get an estimate of the amount of memory in use in 'mctx', in bytes.
330  * This includes quantization overhead, but does not include memory
331  * allocated from the system but not yet used.
332  */
333 
334 size_t
335 isc_mem_maxinuse(isc_mem_t *mctx);
336 /*%<
337  * Get an estimate of the largest amount of memory that has been in
338  * use in 'mctx' at any time.
339  */
340 
341 size_t
342 isc_mem_total(isc_mem_t *mctx);
343 /*%<
344  * Get the total amount of memory in 'mctx', in bytes, including memory
345  * not yet used.
346  */
347 
348 bool
349 isc_mem_isovermem(isc_mem_t *mctx);
350 /*%<
351  * Return true iff the memory context is in "over memory" state, i.e.,
352  * a hiwater mark has been set and the used amount of memory has exceeds
353  * the mark.
354  */
355 
356 void
357 isc_mem_setwater(isc_mem_t *mctx, isc_mem_water_t water, void *water_arg,
358 		 size_t hiwater, size_t lowater);
359 /*%<
360  * Set high and low water marks for this memory context.
361  *
362  * When the memory usage of 'mctx' exceeds 'hiwater',
363  * '(water)(water_arg, #ISC_MEM_HIWATER)' will be called.  'water' needs to
364  * call isc_mem_waterack() with #ISC_MEM_HIWATER to acknowledge the state
365  * change.  'water' may be called multiple times.
366  *
367  * When the usage drops below 'lowater', 'water' will again be called, this
368  * time with #ISC_MEM_LOWATER.  'water' need to calls isc_mem_waterack() with
369  * #ISC_MEM_LOWATER to acknowledge the change.
370  *
371  *	static void
372  *	water(void *arg, int mark) {
373  *		struct foo *foo = arg;
374  *
375  *		LOCK(&foo->marklock);
376  *		if (foo->mark != mark) {
377  * 			foo->mark = mark;
378  *			....
379  *			isc_mem_waterack(foo->mctx, mark);
380  *		}
381  *		UNLOCK(&foo->marklock);
382  *	}
383  *
384  * If 'water' is NULL then 'water_arg', 'hi_water' and 'lo_water' are
385  * ignored and the state is reset.
386  *
387  * Requires:
388  *
389  *	'water' is not NULL.
390  *	hi_water >= lo_water
391  */
392 
393 void
394 isc_mem_waterack(isc_mem_t *ctx, int mark);
395 /*%<
396  * Called to acknowledge changes in signaled by calls to 'water'.
397  */
398 
399 void
400 isc_mem_checkdestroyed(FILE *file);
401 /*%<
402  * Check that all memory contexts have been destroyed.
403  * Prints out those that have not been.
404  * Fatally fails if there are still active contexts.
405  */
406 
407 unsigned int
408 isc_mem_references(isc_mem_t *ctx);
409 /*%<
410  * Return the current reference count.
411  */
412 
413 void
414 isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag);
415 /*%<
416  * Name 'ctx'.
417  *
418  * Notes:
419  *
420  *\li	Only the first 15 characters of 'name' will be copied.
421  *
422  *\li	'tag' is for debugging purposes only.
423  *
424  * Requires:
425  *
426  *\li	'ctx' is a valid ctx.
427  */
428 
429 const char *
430 isc_mem_getname(isc_mem_t *ctx);
431 /*%<
432  * Get the name of 'ctx', as previously set using isc_mem_setname().
433  *
434  * Requires:
435  *\li	'ctx' is a valid ctx.
436  *
437  * Returns:
438  *\li	A non-NULL pointer to a null-terminated string.
439  * 	If the ctx has not been named, the string is
440  * 	empty.
441  */
442 
443 void *
444 isc_mem_gettag(isc_mem_t *ctx);
445 /*%<
446  * Get the tag value for  'task', as previously set using isc_mem_setname().
447  *
448  * Requires:
449  *\li	'ctx' is a valid ctx.
450  *
451  * Notes:
452  *\li	This function is for debugging purposes only.
453  *
454  * Requires:
455  *\li	'ctx' is a valid task.
456  */
457 
458 #ifdef HAVE_LIBXML2
459 int
460 isc_mem_renderxml(void *writer0);
461 /*%<
462  * Render all contexts' statistics and status in XML for writer.
463  */
464 #endif /* HAVE_LIBXML2 */
465 
466 #ifdef HAVE_JSON_C
467 isc_result_t
468 isc_mem_renderjson(void *memobj0);
469 /*%<
470  * Render all contexts' statistics and status in JSON.
471  */
472 #endif /* HAVE_JSON_C */
473 
474 /*
475  * Memory pools
476  */
477 
478 void
479 isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp);
480 /*%<
481  * Create a memory pool.
482  *
483  * Requires:
484  *\li	mctx is a valid memory context.
485  *\li	size > 0
486  *\li	mpctxp != NULL and *mpctxp == NULL
487  *
488  * Defaults:
489  *\li	maxalloc = UINT_MAX
490  *\li	freemax = 1
491  *\li	fillcount = 1
492  *
493  * Returns:
494  *\li	#ISC_R_NOMEMORY		-- not enough memory to create pool
495  *\li	#ISC_R_SUCCESS		-- all is well.
496  */
497 
498 void
499 isc_mempool_destroy(isc_mempool_t **mpctxp);
500 /*%<
501  * Destroy a memory pool.
502  *
503  * Requires:
504  *\li	mpctxp != NULL && *mpctxp is a valid pool.
505  *\li	The pool has no un"put" allocations outstanding
506  */
507 
508 void
509 isc_mempool_setname(isc_mempool_t *mpctx, const char *name);
510 /*%<
511  * Associate a name with a memory pool.  At most 15 characters may be used.
512  *
513  * Requires:
514  *\li	mpctx is a valid pool.
515  *\li	name != NULL;
516  */
517 
518 /*
519  * The following functions get/set various parameters.  Note that due to
520  * the unlocked nature of pools these are potentially random values unless
521  * the imposed externally provided locking protocols are followed.
522  *
523  * Also note that the quota limits will not always take immediate effect.
524  * For instance, setting "maxalloc" to a number smaller than the currently
525  * allocated count is permitted.  New allocations will be refused until
526  * the count drops below this threshold.
527  *
528  * All functions require (in addition to other requirements):
529  *	mpctx is a valid memory pool
530  */
531 
532 unsigned int
533 isc_mempool_getfreemax(isc_mempool_t *mpctx);
534 /*%<
535  * Returns the maximum allowed size of the free list.
536  */
537 
538 void
539 isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit);
540 /*%<
541  * Sets the maximum allowed size of the free list.
542  */
543 
544 unsigned int
545 isc_mempool_getfreecount(isc_mempool_t *mpctx);
546 /*%<
547  * Returns current size of the free list.
548  */
549 
550 unsigned int
551 isc_mempool_getmaxalloc(isc_mempool_t *mpctx);
552 /*!<
553  * Returns the maximum allowed number of allocations.
554  */
555 
556 void
557 isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit);
558 /*%<
559  * Sets the maximum allowed number of allocations.
560  *
561  * Additional requirements:
562  *\li	limit > 0
563  */
564 
565 unsigned int
566 isc_mempool_getallocated(isc_mempool_t *mpctx);
567 /*%<
568  * Returns the number of items allocated from this pool.
569  */
570 
571 unsigned int
572 isc_mempool_getfillcount(isc_mempool_t *mpctx);
573 /*%<
574  * Returns the number of items allocated as a block from the parent memory
575  * context when the free list is empty.
576  */
577 
578 void
579 isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
580 /*%<
581  * Sets the fillcount.
582  *
583  * Additional requirements:
584  *\li	limit > 0
585  */
586 
587 #if defined(UNIT_TESTING) && defined(malloc)
588 /*
589  * cmocka.h redefined malloc as a macro, we #undef it
590  * to avoid replacing ISC_ATTR_MALLOC with garbage.
591  */
592 #pragma push_macro("malloc")
593 #undef malloc
594 #define POP_MALLOC_MACRO 1
595 #endif
596 
597 /*
598  * Pseudo-private functions for use via macros.  Do not call directly.
599  */
600 void ISCMEMFUNC(putanddetach)(isc_mem_t **, void *, size_t _ISC_MEM_FLARG);
601 void ISCMEMFUNC(put)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
602 void ISCMEMFUNC(free)(isc_mem_t *, void *_ISC_MEM_FLARG);
603 
604 ISC_ATTR_RETURNS_NONNULL
605 ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMFUNC(put), 2)
606 void *ISCMEMFUNC(get)(isc_mem_t *, size_t _ISC_MEM_FLARG);
607 
608 ISC_ATTR_RETURNS_NONNULL
609 ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMFUNC(free), 2)
610 void *ISCMEMFUNC(allocate)(isc_mem_t *, size_t _ISC_MEM_FLARG);
611 
612 ISC_ATTR_RETURNS_NONNULL
613 ISC_ATTR_DEALLOCATOR_IDX(ISCMEMFUNC(free), 2)
614 void *ISCMEMFUNC(reallocate)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
615 
616 ISC_ATTR_RETURNS_NONNULL
617 ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMFUNC(free), 2)
618 char *ISCMEMFUNC(strdup)(isc_mem_t *, const char *_ISC_MEM_FLARG);
619 char *ISCMEMFUNC(strndup)(isc_mem_t *, const char *, size_t _ISC_MEM_FLARG);
620 
621 ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMPOOLFUNC(put), 2)
622 void *ISCMEMPOOLFUNC(get)(isc_mempool_t *_ISC_MEM_FLARG);
623 
624 void ISCMEMPOOLFUNC(put)(isc_mempool_t *, void *_ISC_MEM_FLARG);
625 
626 #ifdef POP_MALLOC_MACRO
627 /*
628  * Restore cmocka.h macro for malloc.
629  */
630 #pragma pop_macro("malloc")
631 #endif
632 
633 ISC_LANG_ENDDECLS
634 
635 #endif /* ISC_MEM_H */
636