1 /* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 7 * 8 * See the COPYRIGHT file distributed with this work for additional 9 * information regarding copyright ownership. 10 */ 11 12 #ifndef ISC_MEM_H 13 #define ISC_MEM_H 1 14 15 /*! \file isc/mem.h */ 16 17 #include <stdbool.h> 18 #include <stdio.h> 19 20 #include <isc/attributes.h> 21 #include <isc/lang.h> 22 #include <isc/mutex.h> 23 #include <isc/types.h> 24 25 ISC_LANG_BEGINDECLS 26 27 #define ISC_MEM_LOWATER 0 28 #define ISC_MEM_HIWATER 1 29 typedef void (*isc_mem_water_t)(void *, int); 30 31 /*% 32 * Define ISC_MEM_TRACKLINES=1 to turn on detailed tracing of memory 33 * allocation and freeing by file and line number. 34 */ 35 #ifndef ISC_MEM_TRACKLINES 36 #define ISC_MEM_TRACKLINES 0 37 #endif /* ifndef ISC_MEM_TRACKLINES */ 38 39 extern unsigned int isc_mem_debugging; 40 extern unsigned int isc_mem_defaultflags; 41 42 /*@{*/ 43 #define ISC_MEM_DEBUGTRACE 0x00000001U 44 #define ISC_MEM_DEBUGRECORD 0x00000002U 45 #define ISC_MEM_DEBUGUSAGE 0x00000004U 46 #define ISC_MEM_DEBUGALL 0x0000001FU 47 /*!< 48 * The variable isc_mem_debugging holds a set of flags for 49 * turning certain memory debugging options on or off at 50 * runtime. It is initialized to the value ISC_MEM_DEGBUGGING, 51 * which is 0 by default but may be overridden at compile time. 52 * The following flags can be specified: 53 * 54 * \li #ISC_MEM_DEBUGTRACE 55 * Log each allocation and free to isc_lctx. 56 * 57 * \li #ISC_MEM_DEBUGRECORD 58 * Remember each allocation, and match them up on free. 59 * Crash if a free doesn't match an allocation. 60 * 61 * \li #ISC_MEM_DEBUGUSAGE 62 * If a hi_water mark is set, print the maximum inuse memory 63 * every time it is raised once it exceeds the hi_water mark. 64 */ 65 /*@}*/ 66 67 #if ISC_MEM_TRACKLINES 68 #define _ISC_MEM_FILELINE , __FILE__, __LINE__ 69 #define _ISC_MEM_FLARG , const char *, unsigned int 70 #else /* if ISC_MEM_TRACKLINES */ 71 #define _ISC_MEM_FILELINE 72 #define _ISC_MEM_FLARG 73 #endif /* if ISC_MEM_TRACKLINES */ 74 75 /* 76 * Flags for isc_mem_create() calls. 77 */ 78 #define ISC_MEMFLAG_RESERVED1 0x00000001 /* reserved, obsoleted, don't use */ 79 #define ISC_MEMFLAG_RESERVED2 0x00000002 /* reserved, obsoleted, don't use */ 80 #define ISC_MEMFLAG_FILL \ 81 0x00000004 /* fill with pattern after alloc and frees */ 82 83 /*% 84 * Define ISC_MEM_DEFAULTFILL=1 to turn filling the memory with pattern 85 * after alloc and free. 86 */ 87 #if ISC_MEM_DEFAULTFILL 88 #define ISC_MEMFLAG_DEFAULT ISC_MEMFLAG_FILL 89 #else /* if !ISC_MEM_USE_INTERNAL_MALLOC */ 90 #define ISC_MEMFLAG_DEFAULT 0 91 #endif /* if !ISC_MEM_USE_INTERNAL_MALLOC */ 92 93 /*% 94 * isc_mem_putanddetach() is a convenience function for use where you 95 * have a structure with an attached memory context. 96 * 97 * Given: 98 * 99 * \code 100 * struct { 101 * ... 102 * isc_mem_t *mctx; 103 * ... 104 * } *ptr; 105 * 106 * isc_mem_t *mctx; 107 * 108 * isc_mem_putanddetach(&ptr->mctx, ptr, sizeof(*ptr)); 109 * \endcode 110 * 111 * is the equivalent of: 112 * 113 * \code 114 * mctx = NULL; 115 * isc_mem_attach(ptr->mctx, &mctx); 116 * isc_mem_detach(&ptr->mctx); 117 * isc_mem_put(mctx, ptr, sizeof(*ptr)); 118 * isc_mem_detach(&mctx); 119 * \endcode 120 */ 121 122 /*% 123 * These functions are actually implemented in isc__mem_<function> 124 * (two underscores). The single-underscore macros are used to pass 125 * __FILE__ and __LINE__, and in the case of the put functions, to 126 * set the pointer being freed to NULL in the calling function. 127 * 128 * Many of these functions have a further isc___mem_<function> 129 * (three underscores) implementation, which is called indirectly 130 * via the isc_memmethods structure in the mctx so that dynamically 131 * loaded modules can use them even if named is statically linked. 132 */ 133 134 #define ISCMEMFUNC(sfx) isc__mem_##sfx 135 #define ISCMEMPOOLFUNC(sfx) isc__mempool_##sfx 136 137 #define isc_mem_get(c, s) ISCMEMFUNC(get)((c), (s)_ISC_MEM_FILELINE) 138 #define isc_mem_reget(c, p, o, n) \ 139 ISCMEMFUNC(reget)((c), (p), (o), (n)_ISC_MEM_FILELINE) 140 #define isc_mem_allocate(c, s) ISCMEMFUNC(allocate)((c), (s)_ISC_MEM_FILELINE) 141 #define isc_mem_reallocate(c, p, s) \ 142 ISCMEMFUNC(reallocate)((c), (p), (s)_ISC_MEM_FILELINE) 143 #define isc_mem_strdup(c, p) ISCMEMFUNC(strdup)((c), (p)_ISC_MEM_FILELINE) 144 #define isc_mem_strndup(c, p, l) \ 145 ISCMEMFUNC(strndup)((c), (p), (l)_ISC_MEM_FILELINE) 146 #define isc_mempool_get(c) ISCMEMPOOLFUNC(get)((c)_ISC_MEM_FILELINE) 147 148 #define isc_mem_put(c, p, s) \ 149 do { \ 150 ISCMEMFUNC(put)((c), (p), (s)_ISC_MEM_FILELINE); \ 151 (p) = NULL; \ 152 } while (0) 153 #define isc_mem_putanddetach(c, p, s) \ 154 do { \ 155 ISCMEMFUNC(putanddetach)((c), (p), (s)_ISC_MEM_FILELINE); \ 156 (p) = NULL; \ 157 } while (0) 158 #define isc_mem_free(c, p) \ 159 do { \ 160 ISCMEMFUNC(free)((c), (p)_ISC_MEM_FILELINE); \ 161 (p) = NULL; \ 162 } while (0) 163 #define isc_mempool_put(c, p) \ 164 do { \ 165 ISCMEMPOOLFUNC(put)((c), (p)_ISC_MEM_FILELINE); \ 166 (p) = NULL; \ 167 } while (0) 168 169 /*@{*/ 170 #define isc_mem_create(cp) ISCMEMFUNC(create)((cp)_ISC_MEM_FILELINE) 171 void ISCMEMFUNC(create)(isc_mem_t **_ISC_MEM_FLARG); 172 173 /*!< 174 * \brief Create a memory context. 175 * 176 * Requires: 177 * mctxp != NULL && *mctxp == NULL */ 178 /*@}*/ 179 180 /*@{*/ 181 void 182 isc_mem_attach(isc_mem_t *, isc_mem_t **); 183 #define isc_mem_detach(cp) ISCMEMFUNC(detach)((cp)_ISC_MEM_FILELINE) 184 void ISCMEMFUNC(detach)(isc_mem_t **_ISC_MEM_FLARG); 185 /*!< 186 * \brief Attach to / detach from a memory context. 187 * 188 * This is intended for applications that use multiple memory contexts 189 * in such a way that it is not obvious when the last allocations from 190 * a given context has been freed and destroying the context is safe. 191 * 192 * Most applications do not need to call these functions as they can 193 * simply create a single memory context at the beginning of main() 194 * and destroy it at the end of main(), thereby guaranteeing that it 195 * is not destroyed while there are outstanding allocations. 196 */ 197 /*@}*/ 198 199 #define isc_mem_destroy(cp) ISCMEMFUNC(destroy)((cp)_ISC_MEM_FILELINE) 200 void ISCMEMFUNC(destroy)(isc_mem_t **_ISC_MEM_FLARG); 201 /*%< 202 * Destroy a memory context. 203 */ 204 205 void 206 isc_mem_stats(isc_mem_t *mctx, FILE *out); 207 /*%< 208 * Print memory usage statistics for 'mctx' on the stream 'out'. 209 */ 210 211 void 212 isc_mem_setdestroycheck(isc_mem_t *mctx, bool on); 213 /*%< 214 * If 'on' is true, 'mctx' will check for memory leaks when 215 * destroyed and abort the program if any are present. 216 */ 217 218 size_t 219 isc_mem_inuse(isc_mem_t *mctx); 220 /*%< 221 * Get an estimate of the amount of memory in use in 'mctx', in bytes. 222 * This includes quantization overhead, but does not include memory 223 * allocated from the system but not yet used. 224 */ 225 226 size_t 227 isc_mem_maxinuse(isc_mem_t *mctx); 228 /*%< 229 * Get an estimate of the largest amount of memory that has been in 230 * use in 'mctx' at any time. 231 */ 232 233 size_t 234 isc_mem_total(isc_mem_t *mctx); 235 /*%< 236 * Get the total amount of memory in 'mctx', in bytes, including memory 237 * not yet used. 238 */ 239 240 size_t 241 isc_mem_malloced(isc_mem_t *ctx); 242 /*%< 243 * Get an estimate of the amount of memory allocated in 'mctx', in bytes. 244 */ 245 246 size_t 247 isc_mem_maxmalloced(isc_mem_t *ctx); 248 /*%< 249 * Get an estimate of the largest amount of memory that has been 250 * allocated in 'mctx' at any time. 251 */ 252 253 bool 254 isc_mem_isovermem(isc_mem_t *mctx); 255 /*%< 256 * Return true iff the memory context is in "over memory" state, i.e., 257 * a hiwater mark has been set and the used amount of memory has exceeds 258 * the mark. 259 */ 260 261 void 262 isc_mem_clearwater(isc_mem_t *mctx); 263 void 264 isc_mem_setwater(isc_mem_t *mctx, isc_mem_water_t water, void *water_arg, 265 size_t hiwater, size_t lowater); 266 /*%< 267 * Set high and low water marks for this memory context. 268 * 269 * When the memory usage of 'mctx' exceeds 'hiwater', 270 * '(water)(water_arg, #ISC_MEM_HIWATER)' will be called. 'water' needs 271 * to call isc_mem_waterack() with #ISC_MEM_HIWATER to acknowledge the 272 * state change. 'water' may be called multiple times. 273 * 274 * When the usage drops below 'lowater', 'water' will again be called, 275 * this time with #ISC_MEM_LOWATER. 'water' need to calls 276 * isc_mem_waterack() with #ISC_MEM_LOWATER to acknowledge the change. 277 * 278 * static void 279 * water(void *arg, int mark) { 280 * struct foo *foo = arg; 281 * 282 * LOCK(&foo->marklock); 283 * if (foo->mark != mark) { 284 * foo->mark = mark; 285 * .... 286 * isc_mem_waterack(foo->mctx, mark); 287 * } 288 * UNLOCK(&foo->marklock); 289 * } 290 * 291 * if 'water' is set to NULL, the 'hiwater' and 'lowater' must set to 0, and 292 * high- and low-water processing are disabled for this memory context. There's 293 * a convenient function isc_mem_clearwater(). 294 * 295 * Requires: 296 * 297 *\li If 'water' is NULL, 'hiwater' and 'lowater' must be set to 0. 298 *\li If 'water' and 'water_arg' have previously been set, they are 299 unchanged. 300 *\li 'hiwater' >= 'lowater' 301 */ 302 303 void 304 isc_mem_waterack(isc_mem_t *ctx, int mark); 305 /*%< 306 * Called to acknowledge changes in signaled by calls to 'water'. 307 */ 308 309 void 310 isc_mem_checkdestroyed(FILE *file); 311 /*%< 312 * Check that all memory contexts have been destroyed. 313 * Prints out those that have not been. 314 * Fatally fails if there are still active contexts. 315 */ 316 317 unsigned int 318 isc_mem_references(isc_mem_t *ctx); 319 /*%< 320 * Return the current reference count. 321 */ 322 323 void 324 isc_mem_setname(isc_mem_t *ctx, const char *name); 325 /*%< 326 * Name 'ctx'. 327 * 328 * Notes: 329 * 330 *\li Only the first 15 characters of 'name' will be copied. 331 * 332 * Requires: 333 * 334 *\li 'ctx' is a valid ctx. 335 */ 336 337 const char * 338 isc_mem_getname(isc_mem_t *ctx); 339 /*%< 340 * Get the name of 'ctx', as previously set using isc_mem_setname(). 341 * 342 * Requires: 343 *\li 'ctx' is a valid ctx. 344 * 345 * Returns: 346 *\li A non-NULL pointer to a null-terminated string. 347 * If the ctx has not been named, the string is 348 * empty. 349 */ 350 351 #ifdef HAVE_LIBXML2 352 int 353 isc_mem_renderxml(void *writer0); 354 /*%< 355 * Render all contexts' statistics and status in XML for writer. 356 */ 357 #endif /* HAVE_LIBXML2 */ 358 359 #ifdef HAVE_JSON_C 360 isc_result_t 361 isc_mem_renderjson(void *memobj0); 362 /*%< 363 * Render all contexts' statistics and status in JSON. 364 */ 365 #endif /* HAVE_JSON_C */ 366 367 /* 368 * Memory pools 369 */ 370 371 #define isc_mempool_create(c, s, mp) \ 372 isc__mempool_create((c), (s), (mp)_ISC_MEM_FILELINE) 373 void 374 isc__mempool_create(isc_mem_t *restrict mctx, const size_t element_size, 375 isc_mempool_t **mpctxp _ISC_MEM_FLARG); 376 /*%< 377 * Create a memory pool. 378 * 379 * Requires: 380 *\li mctx is a valid memory context. 381 *\li size > 0 382 *\li mpctxp != NULL and *mpctxp == NULL 383 * 384 * Defaults: 385 *\li freemax = 1 386 *\li fillcount = 1 387 * 388 * Returns: 389 *\li #ISC_R_NOMEMORY -- not enough memory to create pool 390 *\li #ISC_R_SUCCESS -- all is well. 391 */ 392 393 #define isc_mempool_destroy(mp) isc__mempool_destroy((mp)_ISC_MEM_FILELINE) 394 void 395 isc__mempool_destroy(isc_mempool_t **restrict mpctxp _ISC_MEM_FLARG); 396 /*%< 397 * Destroy a memory pool. 398 * 399 * Requires: 400 *\li mpctxp != NULL && *mpctxp is a valid pool. 401 *\li The pool has no un"put" allocations outstanding 402 */ 403 404 void 405 isc_mempool_setname(isc_mempool_t *restrict mpctx, const char *name); 406 /*%< 407 * Associate a name with a memory pool. At most 15 characters may be 408 *used. 409 * 410 * Requires: 411 *\li mpctx is a valid pool. 412 *\li name != NULL; 413 */ 414 415 /* 416 * The following functions get/set various parameters. Note that due to 417 * the unlocked nature of pools these are potentially random values 418 *unless the imposed externally provided locking protocols are followed. 419 * 420 * Also note that the quota limits will not always take immediate 421 * effect. 422 * 423 * All functions require (in addition to other requirements): 424 * mpctx is a valid memory pool 425 */ 426 427 unsigned int 428 isc_mempool_getfreemax(isc_mempool_t *restrict mpctx); 429 /*%< 430 * Returns the maximum allowed size of the free list. 431 */ 432 433 void 434 isc_mempool_setfreemax(isc_mempool_t *restrict mpctx, const unsigned int limit); 435 /*%< 436 * Sets the maximum allowed size of the free list. 437 */ 438 439 unsigned int 440 isc_mempool_getfreecount(isc_mempool_t *restrict mpctx); 441 /*%< 442 * Returns current size of the free list. 443 */ 444 445 unsigned int 446 isc_mempool_getallocated(isc_mempool_t *restrict mpctx); 447 /*%< 448 * Returns the number of items allocated from this pool. 449 */ 450 451 unsigned int 452 isc_mempool_getfillcount(isc_mempool_t *restrict mpctx); 453 /*%< 454 * Returns the number of items allocated as a block from the parent 455 * memory context when the free list is empty. 456 */ 457 458 void 459 isc_mempool_setfillcount(isc_mempool_t *restrict mpctx, 460 const unsigned int limit); 461 /*%< 462 * Sets the fillcount. 463 * 464 * Additional requirements: 465 *\li limit > 0 466 */ 467 468 #if defined(UNIT_TESTING) && defined(malloc) 469 /* 470 * cmocka.h redefined malloc as a macro, we #undef it 471 * to avoid replacing ISC_ATTR_MALLOC with garbage. 472 */ 473 #pragma push_macro("malloc") 474 #undef malloc 475 #define POP_MALLOC_MACRO 1 476 #endif 477 478 /* 479 * Pseudo-private functions for use via macros. Do not call directly. 480 */ 481 void ISCMEMFUNC(putanddetach)(isc_mem_t **, void *, size_t _ISC_MEM_FLARG); 482 void ISCMEMFUNC(put)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG); 483 void ISCMEMFUNC(free)(isc_mem_t *, void *_ISC_MEM_FLARG); 484 485 ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMFUNC(put), 2) 486 void *ISCMEMFUNC(get)(isc_mem_t *, size_t _ISC_MEM_FLARG); 487 488 ISC_ATTR_DEALLOCATOR_IDX(ISCMEMFUNC(put), 2) 489 void *ISCMEMFUNC(reget)(isc_mem_t *, void *, size_t, size_t _ISC_MEM_FLARG); 490 491 ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMFUNC(free), 2) 492 void *ISCMEMFUNC(allocate)(isc_mem_t *, size_t _ISC_MEM_FLARG); 493 494 ISC_ATTR_DEALLOCATOR_IDX(ISCMEMFUNC(free), 2) 495 void *ISCMEMFUNC(reallocate)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG); 496 497 ISC_ATTR_RETURNS_NONNULL 498 ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMFUNC(free), 2) 499 char *ISCMEMFUNC(strdup)(isc_mem_t *, const char *_ISC_MEM_FLARG); 500 501 ISC_ATTR_RETURNS_NONNULL 502 ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMFUNC(free), 2) 503 char *ISCMEMFUNC(strndup)(isc_mem_t *, const char *, size_t _ISC_MEM_FLARG); 504 505 ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMPOOLFUNC(put), 2) 506 void *ISCMEMPOOLFUNC(get)(isc_mempool_t *_ISC_MEM_FLARG); 507 508 void ISCMEMPOOLFUNC(put)(isc_mempool_t *, void *_ISC_MEM_FLARG); 509 510 #ifdef POP_MALLOC_MACRO 511 /* 512 * Restore cmocka.h macro for malloc. 513 */ 514 #pragma pop_macro("malloc") 515 #endif 516 517 ISC_LANG_ENDDECLS 518 519 #endif /* ISC_MEM_H */ 520