00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <stddef.h>
00025
00026 #include <limits.h>
00027
00028 #include <isc/bind9.h>
00029 #include <isc/json.h>
00030 #include <isc/magic.h>
00031 #include <isc/mem.h>
00032 #include <isc/msgs.h>
00033 #include <isc/once.h>
00034 #include <isc/ondestroy.h>
00035 #include <isc/string.h>
00036 #include <isc/mutex.h>
00037 #include <isc/print.h>
00038 #include <isc/util.h>
00039 #include <isc/xml.h>
00040
00041 #define MCTXLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) LOCK(l)
00042 #define MCTXUNLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) UNLOCK(l)
00043
00044 #ifndef ISC_MEM_DEBUGGING
00045 #define ISC_MEM_DEBUGGING 0
00046 #endif
00047 LIBISC_EXTERNAL_DATA unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING;
00048 LIBISC_EXTERNAL_DATA unsigned int isc_mem_defaultflags = ISC_MEMFLAG_DEFAULT;
00049
00050
00051
00052
00053
00054 #define DEF_MAX_SIZE 1100
00055 #define DEF_MEM_TARGET 4096
00056 #define ALIGNMENT_SIZE 8U
00057 #define NUM_BASIC_BLOCKS 64
00058 #define TABLE_INCREMENT 1024
00059 #define DEBUGLIST_COUNT 1024
00060
00061
00062
00063
00064 typedef struct isc__mem isc__mem_t;
00065 typedef struct isc__mempool isc__mempool_t;
00066
00067 #if ISC_MEM_TRACKLINES
00068 typedef struct debuglink debuglink_t;
00069 struct debuglink {
00070 ISC_LINK(debuglink_t) link;
00071 const void *ptr[DEBUGLIST_COUNT];
00072 size_t size[DEBUGLIST_COUNT];
00073 const char *file[DEBUGLIST_COUNT];
00074 unsigned int line[DEBUGLIST_COUNT];
00075 unsigned int count;
00076 };
00077
00078 #define FLARG_PASS , file, line
00079 #define FLARG , const char *file, unsigned int line
00080 #else
00081 #define FLARG_PASS
00082 #define FLARG
00083 #endif
00084
00085 typedef struct element element;
00086 struct element {
00087 element * next;
00088 };
00089
00090 typedef struct {
00091
00092
00093
00094 union {
00095 size_t size;
00096 isc__mem_t *ctx;
00097 char bytes[ALIGNMENT_SIZE];
00098 } u;
00099 } size_info;
00100
00101 struct stats {
00102 unsigned long gets;
00103 unsigned long totalgets;
00104 unsigned long blocks;
00105 unsigned long freefrags;
00106 };
00107
00108 #define MEM_MAGIC ISC_MAGIC('M', 'e', 'm', 'C')
00109 #define VALID_CONTEXT(c) ISC_MAGIC_VALID(c, MEM_MAGIC)
00110
00111 #if ISC_MEM_TRACKLINES
00112 typedef ISC_LIST(debuglink_t) debuglist_t;
00113 #endif
00114
00115
00116
00117 static ISC_LIST(isc__mem_t) contexts;
00118
00119 static isc_once_t once = ISC_ONCE_INIT;
00120 static isc_mutex_t contextslock;
00121 static isc_mutex_t createlock;
00122
00123
00124
00125
00126
00127 static isc_uint64_t totallost;
00128
00129 struct isc__mem {
00130 isc_mem_t common;
00131 isc_ondestroy_t ondestroy;
00132 unsigned int flags;
00133 isc_mutex_t lock;
00134 isc_memalloc_t memalloc;
00135 isc_memfree_t memfree;
00136 void * arg;
00137 size_t max_size;
00138 isc_boolean_t checkfree;
00139 struct stats * stats;
00140 unsigned int references;
00141 char name[16];
00142 void * tag;
00143 size_t quota;
00144 size_t total;
00145 size_t inuse;
00146 size_t maxinuse;
00147 size_t hi_water;
00148 size_t lo_water;
00149 isc_boolean_t hi_called;
00150 isc_boolean_t is_overmem;
00151 isc_mem_water_t water;
00152 void * water_arg;
00153 ISC_LIST(isc__mempool_t) pools;
00154 unsigned int poolcnt;
00155
00156
00157 size_t mem_target;
00158 element ** freelists;
00159 element * basic_blocks;
00160 unsigned char ** basic_table;
00161 unsigned int basic_table_count;
00162 unsigned int basic_table_size;
00163 unsigned char * lowest;
00164 unsigned char * highest;
00165
00166 #if ISC_MEM_TRACKLINES
00167 debuglist_t * debuglist;
00168 unsigned int debuglistcnt;
00169 #endif
00170
00171 unsigned int memalloc_failures;
00172 ISC_LINK(isc__mem_t) link;
00173 };
00174
00175 #define MEMPOOL_MAGIC ISC_MAGIC('M', 'E', 'M', 'p')
00176 #define VALID_MEMPOOL(c) ISC_MAGIC_VALID(c, MEMPOOL_MAGIC)
00177
00178 struct isc__mempool {
00179
00180 isc_mempool_t common;
00181 isc_mutex_t *lock;
00182 isc__mem_t *mctx;
00183
00184 ISC_LINK(isc__mempool_t) link;
00185
00186 element *items;
00187 size_t size;
00188 unsigned int maxalloc;
00189 unsigned int allocated;
00190 unsigned int freecount;
00191 unsigned int freemax;
00192 unsigned int fillcount;
00193
00194 unsigned int gets;
00195
00196 #if ISC_MEMPOOL_NAMES
00197 char name[16];
00198 #endif
00199 };
00200
00201
00202
00203
00204
00205 #if ! ISC_MEM_TRACKLINES
00206 #define ADD_TRACE(a, b, c, d, e)
00207 #define DELETE_TRACE(a, b, c, d, e)
00208 #define ISC_MEMFUNC_SCOPE
00209 #else
00210 #define ADD_TRACE(a, b, c, d, e) \
00211 do { \
00212 if ((isc_mem_debugging & (ISC_MEM_DEBUGTRACE | \
00213 ISC_MEM_DEBUGRECORD)) != 0 && \
00214 b != NULL) \
00215 add_trace_entry(a, b, c, d, e); \
00216 } while (0)
00217 #define DELETE_TRACE(a, b, c, d, e) delete_trace_entry(a, b, c, d, e)
00218
00219 static void
00220 print_active(isc__mem_t *ctx, FILE *out);
00221
00222
00223
00224
00225
00226
00227
00228 isc_result_t
00229 isc__mem_create2(size_t init_max_size, size_t target_size,
00230 isc_mem_t **ctxp, unsigned int flags);
00231 void
00232 isc__mem_attach(isc_mem_t *source, isc_mem_t **targetp);
00233 void
00234 isc__mem_detach(isc_mem_t **ctxp);
00235 void
00236 isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG);
00237 void
00238 isc__mem_destroy(isc_mem_t **ctxp);
00239 isc_result_t
00240 isc__mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event);
00241 void *
00242 isc___mem_get(isc_mem_t *ctx, size_t size FLARG);
00243 void
00244 isc___mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG);
00245 void
00246 isc__mem_stats(isc_mem_t *ctx, FILE *out);
00247 void *
00248 isc___mem_allocate(isc_mem_t *ctx, size_t size FLARG);
00249 void *
00250 isc___mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG);
00251 void
00252 isc___mem_free(isc_mem_t *ctx, void *ptr FLARG);
00253 char *
00254 isc___mem_strdup(isc_mem_t *mctx, const char *s FLARG);
00255 void
00256 isc__mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag);
00257 void
00258 isc__mem_setquota(isc_mem_t *ctx, size_t quota);
00259 size_t
00260 isc__mem_getquota(isc_mem_t *ctx);
00261 size_t
00262 isc__mem_inuse(isc_mem_t *ctx);
00263 size_t
00264 isc__mem_maxinuse(isc_mem_t *ctx);
00265 size_t
00266 isc__mem_total(isc_mem_t *ctx);
00267 isc_boolean_t
00268 isc__mem_isovermem(isc_mem_t *ctx);
00269 void
00270 isc__mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
00271 size_t hiwater, size_t lowater);
00272 void
00273 isc__mem_waterack(isc_mem_t *ctx0, int flag);
00274 void
00275 isc__mem_setname(isc_mem_t *ctx, const char *name, void *tag);
00276 const char *
00277 isc__mem_getname(isc_mem_t *ctx);
00278 void *
00279 isc__mem_gettag(isc_mem_t *ctx);
00280 isc_result_t
00281 isc__mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp);
00282 void
00283 isc__mempool_setname(isc_mempool_t *mpctx, const char *name);
00284 void
00285 isc__mempool_destroy(isc_mempool_t **mpctxp);
00286 void
00287 isc__mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock);
00288 void *
00289 isc___mempool_get(isc_mempool_t *mpctx FLARG);
00290 void
00291 isc___mempool_put(isc_mempool_t *mpctx, void *mem FLARG);
00292 void
00293 isc__mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit);
00294 unsigned int
00295 isc__mempool_getfreemax(isc_mempool_t *mpctx);
00296 unsigned int
00297 isc__mempool_getfreecount(isc_mempool_t *mpctx);
00298 void
00299 isc__mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit);
00300 unsigned int
00301 isc__mempool_getmaxalloc(isc_mempool_t *mpctx);
00302 unsigned int
00303 isc__mempool_getallocated(isc_mempool_t *mpctx);
00304 void
00305 isc__mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
00306 unsigned int
00307 isc__mempool_getfillcount(isc_mempool_t *mpctx);
00308 void
00309 isc__mem_printactive(isc_mem_t *ctx0, FILE *file);
00310 void
00311 isc__mem_printallactive(FILE *file);
00312 unsigned int
00313 isc__mem_references(isc_mem_t *ctx0);
00314 #endif
00315
00316 static struct isc__memmethods {
00317 isc_memmethods_t methods;
00318
00319
00320
00321
00322 void *createx, *create, *create2, *ondestroy, *stats,
00323 *setquota, *getquota, *setname, *getname, *gettag;
00324 } memmethods = {
00325 {
00326 isc__mem_attach,
00327 isc__mem_detach,
00328 isc__mem_destroy,
00329 isc___mem_get,
00330 isc___mem_put,
00331 isc___mem_putanddetach,
00332 isc___mem_allocate,
00333 isc___mem_reallocate,
00334 isc___mem_strdup,
00335 isc___mem_free,
00336 isc__mem_setdestroycheck,
00337 isc__mem_setwater,
00338 isc__mem_waterack,
00339 isc__mem_inuse,
00340 isc__mem_maxinuse,
00341 isc__mem_total,
00342 isc__mem_isovermem,
00343 isc__mempool_create
00344 },
00345 (void *)isc_mem_createx,
00346 (void *)isc_mem_create,
00347 (void *)isc_mem_create2,
00348 (void *)isc_mem_ondestroy,
00349 (void *)isc_mem_stats,
00350 (void *)isc_mem_setquota,
00351 (void *)isc_mem_getquota,
00352 (void *)isc_mem_setname,
00353 (void *)isc_mem_getname,
00354 (void *)isc_mem_gettag
00355 };
00356
00357 static struct isc__mempoolmethods {
00358 isc_mempoolmethods_t methods;
00359
00360
00361
00362
00363 void *getfreemax, *getfreecount, *getmaxalloc, *getfillcount;
00364 } mempoolmethods = {
00365 {
00366 isc__mempool_destroy,
00367 isc___mempool_get,
00368 isc___mempool_put,
00369 isc__mempool_getallocated,
00370 isc__mempool_setmaxalloc,
00371 isc__mempool_setfreemax,
00372 isc__mempool_setname,
00373 isc__mempool_associatelock,
00374 isc__mempool_setfillcount
00375 },
00376 (void *)isc_mempool_getfreemax,
00377 (void *)isc_mempool_getfreecount,
00378 (void *)isc_mempool_getmaxalloc,
00379 (void *)isc_mempool_getfillcount
00380 };
00381
00382 #if ISC_MEM_TRACKLINES
00383
00384
00385
00386 static inline void
00387 add_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size FLARG) {
00388 debuglink_t *dl;
00389 unsigned int i;
00390 size_t mysize = size;
00391
00392 if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
00393 fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
00394 ISC_MSG_ADDTRACE,
00395 "add %p size %u "
00396 "file %s line %u mctx %p\n"),
00397 ptr, size, file, line, mctx);
00398
00399 if (mctx->debuglist == NULL)
00400 return;
00401
00402 if (mysize > mctx->max_size)
00403 mysize = mctx->max_size;
00404
00405 dl = ISC_LIST_HEAD(mctx->debuglist[mysize]);
00406 while (dl != NULL) {
00407 if (dl->count == DEBUGLIST_COUNT)
00408 goto next;
00409 for (i = 0; i < DEBUGLIST_COUNT; i++) {
00410 if (dl->ptr[i] == NULL) {
00411 dl->ptr[i] = ptr;
00412 dl->size[i] = size;
00413 dl->file[i] = file;
00414 dl->line[i] = line;
00415 dl->count++;
00416 return;
00417 }
00418 }
00419 next:
00420 dl = ISC_LIST_NEXT(dl, link);
00421 }
00422
00423 dl = malloc(sizeof(debuglink_t));
00424 INSIST(dl != NULL);
00425
00426 ISC_LINK_INIT(dl, link);
00427 for (i = 1; i < DEBUGLIST_COUNT; i++) {
00428 dl->ptr[i] = NULL;
00429 dl->size[i] = 0;
00430 dl->file[i] = NULL;
00431 dl->line[i] = 0;
00432 }
00433
00434 dl->ptr[0] = ptr;
00435 dl->size[0] = size;
00436 dl->file[0] = file;
00437 dl->line[0] = line;
00438 dl->count = 1;
00439
00440 ISC_LIST_PREPEND(mctx->debuglist[mysize], dl, link);
00441 mctx->debuglistcnt++;
00442 }
00443
00444 static inline void
00445 delete_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size,
00446 const char *file, unsigned int line)
00447 {
00448 debuglink_t *dl;
00449 unsigned int i;
00450
00451 if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
00452 fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
00453 ISC_MSG_DELTRACE,
00454 "del %p size %u "
00455 "file %s line %u mctx %p\n"),
00456 ptr, size, file, line, mctx);
00457
00458 if (mctx->debuglist == NULL)
00459 return;
00460
00461 if (size > mctx->max_size)
00462 size = mctx->max_size;
00463
00464 dl = ISC_LIST_HEAD(mctx->debuglist[size]);
00465 while (dl != NULL) {
00466 for (i = 0; i < DEBUGLIST_COUNT; i++) {
00467 if (dl->ptr[i] == ptr) {
00468 dl->ptr[i] = NULL;
00469 dl->size[i] = 0;
00470 dl->file[i] = NULL;
00471 dl->line[i] = 0;
00472
00473 INSIST(dl->count > 0);
00474 dl->count--;
00475 if (dl->count == 0) {
00476 ISC_LIST_UNLINK(mctx->debuglist[size],
00477 dl, link);
00478 free(dl);
00479 }
00480 return;
00481 }
00482 }
00483 dl = ISC_LIST_NEXT(dl, link);
00484 }
00485
00486
00487
00488
00489
00490 INSIST(dl != NULL);
00491 }
00492 #endif
00493
00494 static inline size_t
00495 rmsize(size_t size) {
00496
00497
00498
00499 return (size & (~(ALIGNMENT_SIZE - 1)));
00500 }
00501
00502 static inline size_t
00503 quantize(size_t size) {
00504
00505
00506
00507
00508
00509
00510 if (size == 0U)
00511 return (ALIGNMENT_SIZE);
00512 return ((size + ALIGNMENT_SIZE - 1) & (~(ALIGNMENT_SIZE - 1)));
00513 }
00514
00515 static inline isc_boolean_t
00516 more_basic_blocks(isc__mem_t *ctx) {
00517 void *new;
00518 unsigned char *curr, *next;
00519 unsigned char *first, *last;
00520 unsigned char **table;
00521 unsigned int table_size;
00522 size_t increment;
00523 int i;
00524
00525
00526
00527
00528
00529
00530 increment = NUM_BASIC_BLOCKS * ctx->mem_target;
00531 if (ctx->quota != 0U && ctx->total + increment > ctx->quota)
00532 return (ISC_FALSE);
00533
00534 INSIST(ctx->basic_table_count <= ctx->basic_table_size);
00535 if (ctx->basic_table_count == ctx->basic_table_size) {
00536 table_size = ctx->basic_table_size + TABLE_INCREMENT;
00537 table = (ctx->memalloc)(ctx->arg,
00538 table_size * sizeof(unsigned char *));
00539 if (table == NULL) {
00540 ctx->memalloc_failures++;
00541 return (ISC_FALSE);
00542 }
00543 if (ctx->basic_table_size != 0) {
00544 memmove(table, ctx->basic_table,
00545 ctx->basic_table_size *
00546 sizeof(unsigned char *));
00547 (ctx->memfree)(ctx->arg, ctx->basic_table);
00548 }
00549 ctx->basic_table = table;
00550 ctx->basic_table_size = table_size;
00551 }
00552
00553 new = (ctx->memalloc)(ctx->arg, NUM_BASIC_BLOCKS * ctx->mem_target);
00554 if (new == NULL) {
00555 ctx->memalloc_failures++;
00556 return (ISC_FALSE);
00557 }
00558 ctx->total += increment;
00559 ctx->basic_table[ctx->basic_table_count] = new;
00560 ctx->basic_table_count++;
00561
00562 curr = new;
00563 next = curr + ctx->mem_target;
00564 for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) {
00565 ((element *)curr)->next = (element *)next;
00566 curr = next;
00567 next += ctx->mem_target;
00568 }
00569
00570
00571
00572
00573 ((element *)curr)->next = NULL;
00574 first = new;
00575 last = first + NUM_BASIC_BLOCKS * ctx->mem_target - 1;
00576 if (first < ctx->lowest || ctx->lowest == NULL)
00577 ctx->lowest = first;
00578 if (last > ctx->highest)
00579 ctx->highest = last;
00580 ctx->basic_blocks = new;
00581
00582 return (ISC_TRUE);
00583 }
00584
00585 static inline isc_boolean_t
00586 more_frags(isc__mem_t *ctx, size_t new_size) {
00587 int i, frags;
00588 size_t total_size;
00589 void *new;
00590 unsigned char *curr, *next;
00591
00592
00593
00594
00595
00596 if (ctx->basic_blocks == NULL) {
00597 if (!more_basic_blocks(ctx)) {
00598
00599
00600
00601
00602
00603
00604
00605 return (ISC_FALSE);
00606 }
00607 }
00608
00609 total_size = ctx->mem_target;
00610 new = ctx->basic_blocks;
00611 ctx->basic_blocks = ctx->basic_blocks->next;
00612 frags = (int)(total_size / new_size);
00613 ctx->stats[new_size].blocks++;
00614 ctx->stats[new_size].freefrags += frags;
00615
00616
00617
00618
00619 curr = new;
00620 next = curr + new_size;
00621 total_size -= new_size;
00622 for (i = 0; i < (frags - 1); i++) {
00623 ((element *)curr)->next = (element *)next;
00624 curr = next;
00625 next += new_size;
00626 total_size -= new_size;
00627 }
00628
00629
00630
00631 total_size = rmsize(total_size);
00632 if (total_size > 0U) {
00633 ((element *)next)->next = ctx->freelists[total_size];
00634 ctx->freelists[total_size] = (element *)next;
00635 ctx->stats[total_size].freefrags++;
00636 }
00637
00638
00639
00640
00641 ((element *)curr)->next = NULL;
00642 ctx->freelists[new_size] = new;
00643
00644 return (ISC_TRUE);
00645 }
00646
00647 static inline void *
00648 mem_getunlocked(isc__mem_t *ctx, size_t size) {
00649 size_t new_size = quantize(size);
00650 void *ret;
00651
00652 if (new_size >= ctx->max_size) {
00653
00654
00655
00656 if (ctx->quota != 0U && ctx->total + size > ctx->quota) {
00657 ret = NULL;
00658 goto done;
00659 }
00660 ret = (ctx->memalloc)(ctx->arg, size);
00661 if (ret == NULL) {
00662 ctx->memalloc_failures++;
00663 goto done;
00664 }
00665 ctx->total += size;
00666 ctx->inuse += size;
00667 ctx->stats[ctx->max_size].gets++;
00668 ctx->stats[ctx->max_size].totalgets++;
00669
00670
00671
00672
00673
00674 new_size = size;
00675 goto done;
00676 }
00677
00678
00679
00680
00681
00682
00683 if (ctx->freelists[new_size] == NULL && !more_frags(ctx, new_size))
00684 return (NULL);
00685
00686
00687
00688
00689 ret = ctx->freelists[new_size];
00690 ctx->freelists[new_size] = ctx->freelists[new_size]->next;
00691
00692
00693
00694
00695
00696
00697
00698 ctx->stats[size].gets++;
00699 ctx->stats[size].totalgets++;
00700 ctx->stats[new_size].freefrags--;
00701 ctx->inuse += new_size;
00702
00703 done:
00704
00705 #if ISC_MEM_FILL
00706 if (ret != NULL)
00707 memset(ret, 0xbe, new_size);
00708 #endif
00709
00710 return (ret);
00711 }
00712
00713 #if ISC_MEM_FILL && ISC_MEM_CHECKOVERRUN
00714 static inline void
00715 check_overrun(void *mem, size_t size, size_t new_size) {
00716 unsigned char *cp;
00717
00718 cp = (unsigned char *)mem;
00719 cp += size;
00720 while (size < new_size) {
00721 INSIST(*cp == 0xbe);
00722 cp++;
00723 size++;
00724 }
00725 }
00726 #endif
00727
00728
00729 static inline void
00730 mem_putunlocked(isc__mem_t *ctx, void *mem, size_t size) {
00731 size_t new_size = quantize(size);
00732
00733 if (new_size >= ctx->max_size) {
00734
00735
00736
00737 #if ISC_MEM_FILL
00738 memset(mem, 0xde, size);
00739 #endif
00740 (ctx->memfree)(ctx->arg, mem);
00741 INSIST(ctx->stats[ctx->max_size].gets != 0U);
00742 ctx->stats[ctx->max_size].gets--;
00743 INSIST(size <= ctx->inuse);
00744 ctx->inuse -= size;
00745 return;
00746 }
00747
00748 #if ISC_MEM_FILL
00749 #if ISC_MEM_CHECKOVERRUN
00750 check_overrun(mem, size, new_size);
00751 #endif
00752 memset(mem, 0xde, new_size);
00753 #endif
00754
00755
00756
00757
00758 ((element *)mem)->next = ctx->freelists[new_size];
00759 ctx->freelists[new_size] = (element *)mem;
00760
00761
00762
00763
00764
00765
00766
00767 INSIST(ctx->stats[size].gets != 0U);
00768 ctx->stats[size].gets--;
00769 ctx->stats[new_size].freefrags++;
00770 ctx->inuse -= new_size;
00771 }
00772
00773
00774
00775
00776 static inline void *
00777 mem_get(isc__mem_t *ctx, size_t size) {
00778 char *ret;
00779
00780 #if ISC_MEM_CHECKOVERRUN
00781 size += 1;
00782 #endif
00783
00784 ret = (ctx->memalloc)(ctx->arg, size);
00785 if (ret == NULL)
00786 ctx->memalloc_failures++;
00787
00788 #if ISC_MEM_FILL
00789 if (ret != NULL)
00790 memset(ret, 0xbe, size);
00791 #else
00792 # if ISC_MEM_CHECKOVERRUN
00793 if (ret != NULL)
00794 ret[size-1] = 0xbe;
00795 # endif
00796 #endif
00797
00798 return (ret);
00799 }
00800
00801
00802
00803
00804
00805 static inline void
00806 mem_put(isc__mem_t *ctx, void *mem, size_t size) {
00807 #if ISC_MEM_CHECKOVERRUN
00808 INSIST(((unsigned char *)mem)[size] == 0xbe);
00809 #endif
00810 #if ISC_MEM_FILL
00811 memset(mem, 0xde, size);
00812 #else
00813 UNUSED(size);
00814 #endif
00815 (ctx->memfree)(ctx->arg, mem);
00816 }
00817
00818
00819
00820
00821 static inline void
00822 mem_getstats(isc__mem_t *ctx, size_t size) {
00823 ctx->total += size;
00824 ctx->inuse += size;
00825
00826 if (size > ctx->max_size) {
00827 ctx->stats[ctx->max_size].gets++;
00828 ctx->stats[ctx->max_size].totalgets++;
00829 } else {
00830 ctx->stats[size].gets++;
00831 ctx->stats[size].totalgets++;
00832 }
00833 }
00834
00835
00836
00837
00838 static inline void
00839 mem_putstats(isc__mem_t *ctx, void *ptr, size_t size) {
00840 UNUSED(ptr);
00841
00842 INSIST(ctx->inuse >= size);
00843 ctx->inuse -= size;
00844
00845 if (size > ctx->max_size) {
00846 INSIST(ctx->stats[ctx->max_size].gets > 0U);
00847 ctx->stats[ctx->max_size].gets--;
00848 } else {
00849 INSIST(ctx->stats[size].gets > 0U);
00850 ctx->stats[size].gets--;
00851 }
00852 }
00853
00854
00855
00856
00857
00858 static void *
00859 default_memalloc(void *arg, size_t size) {
00860 UNUSED(arg);
00861 if (size == 0U)
00862 size = 1;
00863 return (malloc(size));
00864 }
00865
00866 static void
00867 default_memfree(void *arg, void *ptr) {
00868 UNUSED(arg);
00869 free(ptr);
00870 }
00871
00872 static void
00873 initialize_action(void) {
00874 RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
00875 RUNTIME_CHECK(isc_mutex_init(&contextslock) == ISC_R_SUCCESS);
00876 ISC_LIST_INIT(contexts);
00877 totallost = 0;
00878 }
00879
00880
00881
00882
00883
00884 isc_result_t
00885 isc_mem_createx(size_t init_max_size, size_t target_size,
00886 isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
00887 isc_mem_t **ctxp)
00888 {
00889 return (isc_mem_createx2(init_max_size, target_size, memalloc, memfree,
00890 arg, ctxp, isc_mem_defaultflags));
00891
00892 }
00893
00894 isc_result_t
00895 isc_mem_createx2(size_t init_max_size, size_t target_size,
00896 isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
00897 isc_mem_t **ctxp, unsigned int flags)
00898 {
00899 isc__mem_t *ctx;
00900 isc_result_t result;
00901
00902 REQUIRE(ctxp != NULL && *ctxp == NULL);
00903 REQUIRE(memalloc != NULL);
00904 REQUIRE(memfree != NULL);
00905
00906 INSIST((ALIGNMENT_SIZE & (ALIGNMENT_SIZE - 1)) == 0);
00907
00908 RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
00909
00910 ctx = (memalloc)(arg, sizeof(*ctx));
00911 if (ctx == NULL)
00912 return (ISC_R_NOMEMORY);
00913
00914 if ((flags & ISC_MEMFLAG_NOLOCK) == 0) {
00915 result = isc_mutex_init(&ctx->lock);
00916 if (result != ISC_R_SUCCESS) {
00917 (memfree)(arg, ctx);
00918 return (result);
00919 }
00920 }
00921
00922 if (init_max_size == 0U)
00923 ctx->max_size = DEF_MAX_SIZE;
00924 else
00925 ctx->max_size = init_max_size;
00926 ctx->flags = flags;
00927 ctx->references = 1;
00928 memset(ctx->name, 0, sizeof(ctx->name));
00929 ctx->tag = NULL;
00930 ctx->quota = 0;
00931 ctx->total = 0;
00932 ctx->inuse = 0;
00933 ctx->maxinuse = 0;
00934 ctx->hi_water = 0;
00935 ctx->lo_water = 0;
00936 ctx->hi_called = ISC_FALSE;
00937 ctx->is_overmem = ISC_FALSE;
00938 ctx->water = NULL;
00939 ctx->water_arg = NULL;
00940 ctx->common.impmagic = MEM_MAGIC;
00941 ctx->common.magic = ISCAPI_MCTX_MAGIC;
00942 ctx->common.methods = (isc_memmethods_t *)&memmethods;
00943 isc_ondestroy_init(&ctx->ondestroy);
00944 ctx->memalloc = memalloc;
00945 ctx->memfree = memfree;
00946 ctx->arg = arg;
00947 ctx->stats = NULL;
00948 ctx->checkfree = ISC_TRUE;
00949 #if ISC_MEM_TRACKLINES
00950 ctx->debuglist = NULL;
00951 ctx->debuglistcnt = 0;
00952 #endif
00953 ISC_LIST_INIT(ctx->pools);
00954 ctx->poolcnt = 0;
00955 ctx->freelists = NULL;
00956 ctx->basic_blocks = NULL;
00957 ctx->basic_table = NULL;
00958 ctx->basic_table_count = 0;
00959 ctx->basic_table_size = 0;
00960 ctx->lowest = NULL;
00961 ctx->highest = NULL;
00962
00963 ctx->stats = (memalloc)(arg,
00964 (ctx->max_size+1) * sizeof(struct stats));
00965 if (ctx->stats == NULL) {
00966 result = ISC_R_NOMEMORY;
00967 goto error;
00968 }
00969 memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof(struct stats));
00970
00971 if ((flags & ISC_MEMFLAG_INTERNAL) != 0) {
00972 if (target_size == 0U)
00973 ctx->mem_target = DEF_MEM_TARGET;
00974 else
00975 ctx->mem_target = target_size;
00976 ctx->freelists = (memalloc)(arg, ctx->max_size *
00977 sizeof(element *));
00978 if (ctx->freelists == NULL) {
00979 result = ISC_R_NOMEMORY;
00980 goto error;
00981 }
00982 memset(ctx->freelists, 0,
00983 ctx->max_size * sizeof(element *));
00984 }
00985
00986 #if ISC_MEM_TRACKLINES
00987 if ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0) {
00988 unsigned int i;
00989
00990 ctx->debuglist = (memalloc)(arg,
00991 (ctx->max_size+1) * sizeof(debuglist_t));
00992 if (ctx->debuglist == NULL) {
00993 result = ISC_R_NOMEMORY;
00994 goto error;
00995 }
00996 for (i = 0; i <= ctx->max_size; i++)
00997 ISC_LIST_INIT(ctx->debuglist[i]);
00998 }
00999 #endif
01000
01001 ctx->memalloc_failures = 0;
01002
01003 LOCK(&contextslock);
01004 ISC_LIST_INITANDAPPEND(contexts, ctx, link);
01005 UNLOCK(&contextslock);
01006
01007 *ctxp = (isc_mem_t *)ctx;
01008 return (ISC_R_SUCCESS);
01009
01010 error:
01011 if (ctx != NULL) {
01012 if (ctx->stats != NULL)
01013 (memfree)(arg, ctx->stats);
01014 if (ctx->freelists != NULL)
01015 (memfree)(arg, ctx->freelists);
01016 #if ISC_MEM_TRACKLINES
01017 if (ctx->debuglist != NULL)
01018 (ctx->memfree)(ctx->arg, ctx->debuglist);
01019 #endif
01020 if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
01021 DESTROYLOCK(&ctx->lock);
01022 (memfree)(arg, ctx);
01023 }
01024
01025 return (result);
01026 }
01027
01028 static void
01029 destroy(isc__mem_t *ctx) {
01030 unsigned int i;
01031 isc_ondestroy_t ondest;
01032
01033 LOCK(&contextslock);
01034 ISC_LIST_UNLINK(contexts, ctx, link);
01035 totallost += ctx->inuse;
01036 UNLOCK(&contextslock);
01037
01038 ctx->common.impmagic = 0;
01039 ctx->common.magic = 0;
01040
01041 INSIST(ISC_LIST_EMPTY(ctx->pools));
01042
01043 #if ISC_MEM_TRACKLINES
01044 if (ctx->debuglist != NULL) {
01045 if (ctx->checkfree) {
01046 for (i = 0; i <= ctx->max_size; i++) {
01047 if (!ISC_LIST_EMPTY(ctx->debuglist[i]))
01048 print_active(ctx, stderr);
01049 INSIST(ISC_LIST_EMPTY(ctx->debuglist[i]));
01050 }
01051 } else {
01052 debuglink_t *dl;
01053
01054 for (i = 0; i <= ctx->max_size; i++)
01055 for (dl = ISC_LIST_HEAD(ctx->debuglist[i]);
01056 dl != NULL;
01057 dl = ISC_LIST_HEAD(ctx->debuglist[i])) {
01058 ISC_LIST_UNLINK(ctx->debuglist[i],
01059 dl, link);
01060 free(dl);
01061 }
01062 }
01063 (ctx->memfree)(ctx->arg, ctx->debuglist);
01064 }
01065 #endif
01066 INSIST(ctx->references == 0);
01067
01068 if (ctx->checkfree) {
01069 for (i = 0; i <= ctx->max_size; i++) {
01070 if (ctx->stats[i].gets != 0U) {
01071 fprintf(stderr,
01072 "Failing assertion due to probable "
01073 "leaked memory in context %p (\"%s\") "
01074 "(stats[%u].gets == %lu).\n",
01075 ctx, ctx->name, i, ctx->stats[i].gets);
01076 #if ISC_MEM_TRACKLINES
01077 print_active(ctx, stderr);
01078 #endif
01079 INSIST(ctx->stats[i].gets == 0U);
01080 }
01081 }
01082 }
01083
01084 (ctx->memfree)(ctx->arg, ctx->stats);
01085
01086 if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
01087 for (i = 0; i < ctx->basic_table_count; i++)
01088 (ctx->memfree)(ctx->arg, ctx->basic_table[i]);
01089 (ctx->memfree)(ctx->arg, ctx->freelists);
01090 if (ctx->basic_table != NULL)
01091 (ctx->memfree)(ctx->arg, ctx->basic_table);
01092 }
01093
01094 ondest = ctx->ondestroy;
01095
01096 if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
01097 DESTROYLOCK(&ctx->lock);
01098 (ctx->memfree)(ctx->arg, ctx);
01099
01100 isc_ondestroy_notify(&ondest, ctx);
01101 }
01102
01103 void
01104 isc__mem_attach(isc_mem_t *source0, isc_mem_t **targetp) {
01105 isc__mem_t *source = (isc__mem_t *)source0;
01106
01107 REQUIRE(VALID_CONTEXT(source));
01108 REQUIRE(targetp != NULL && *targetp == NULL);
01109
01110 MCTXLOCK(source, &source->lock);
01111 source->references++;
01112 MCTXUNLOCK(source, &source->lock);
01113
01114 *targetp = (isc_mem_t *)source;
01115 }
01116
01117 void
01118 isc__mem_detach(isc_mem_t **ctxp) {
01119 isc__mem_t *ctx;
01120 isc_boolean_t want_destroy = ISC_FALSE;
01121
01122 REQUIRE(ctxp != NULL);
01123 ctx = (isc__mem_t *)*ctxp;
01124 REQUIRE(VALID_CONTEXT(ctx));
01125
01126 MCTXLOCK(ctx, &ctx->lock);
01127 INSIST(ctx->references > 0);
01128 ctx->references--;
01129 if (ctx->references == 0)
01130 want_destroy = ISC_TRUE;
01131 MCTXUNLOCK(ctx, &ctx->lock);
01132
01133 if (want_destroy)
01134 destroy(ctx);
01135
01136 *ctxp = NULL;
01137 }
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149 void
01150 isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
01151 isc__mem_t *ctx;
01152 isc_boolean_t want_destroy = ISC_FALSE;
01153 size_info *si;
01154 size_t oldsize;
01155
01156 REQUIRE(ctxp != NULL);
01157 ctx = (isc__mem_t *)*ctxp;
01158 REQUIRE(VALID_CONTEXT(ctx));
01159 REQUIRE(ptr != NULL);
01160
01161
01162
01163
01164
01165 *ctxp = NULL;
01166
01167 if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) {
01168 if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {
01169 si = &(((size_info *)ptr)[-1]);
01170 oldsize = si->u.size - ALIGNMENT_SIZE;
01171 if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
01172 oldsize -= ALIGNMENT_SIZE;
01173 INSIST(oldsize == size);
01174 }
01175 isc__mem_free((isc_mem_t *)ctx, ptr FLARG_PASS);
01176
01177 MCTXLOCK(ctx, &ctx->lock);
01178 ctx->references--;
01179 if (ctx->references == 0)
01180 want_destroy = ISC_TRUE;
01181 MCTXUNLOCK(ctx, &ctx->lock);
01182 if (want_destroy)
01183 destroy(ctx);
01184
01185 return;
01186 }
01187
01188 MCTXLOCK(ctx, &ctx->lock);
01189
01190 DELETE_TRACE(ctx, ptr, size, file, line);
01191
01192 if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
01193 mem_putunlocked(ctx, ptr, size);
01194 } else {
01195 mem_putstats(ctx, ptr, size);
01196 mem_put(ctx, ptr, size);
01197 }
01198
01199 INSIST(ctx->references > 0);
01200 ctx->references--;
01201 if (ctx->references == 0)
01202 want_destroy = ISC_TRUE;
01203
01204 MCTXUNLOCK(ctx, &ctx->lock);
01205
01206 if (want_destroy)
01207 destroy(ctx);
01208 }
01209
01210 void
01211 isc__mem_destroy(isc_mem_t **ctxp) {
01212 isc__mem_t *ctx;
01213
01214
01215
01216
01217
01218
01219 REQUIRE(ctxp != NULL);
01220 ctx = (isc__mem_t *)*ctxp;
01221 REQUIRE(VALID_CONTEXT(ctx));
01222
01223 MCTXLOCK(ctx, &ctx->lock);
01224 #if ISC_MEM_TRACKLINES
01225 if (ctx->references != 1)
01226 print_active(ctx, stderr);
01227 #endif
01228 REQUIRE(ctx->references == 1);
01229 ctx->references--;
01230 MCTXUNLOCK(ctx, &ctx->lock);
01231
01232 destroy(ctx);
01233
01234 *ctxp = NULL;
01235 }
01236
01237 isc_result_t
01238 isc_mem_ondestroy(isc_mem_t *ctx0, isc_task_t *task, isc_event_t **event) {
01239 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01240 isc_result_t res;
01241
01242 MCTXLOCK(ctx, &ctx->lock);
01243 res = isc_ondestroy_register(&ctx->ondestroy, task, event);
01244 MCTXUNLOCK(ctx, &ctx->lock);
01245
01246 return (res);
01247 }
01248
01249 void *
01250 isc___mem_get(isc_mem_t *ctx0, size_t size FLARG) {
01251 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01252 void *ptr;
01253 isc_boolean_t call_water = ISC_FALSE;
01254
01255 REQUIRE(VALID_CONTEXT(ctx));
01256
01257 if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0)
01258 return (isc__mem_allocate(ctx0, size FLARG_PASS));
01259
01260 if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
01261 MCTXLOCK(ctx, &ctx->lock);
01262 ptr = mem_getunlocked(ctx, size);
01263 } else {
01264 ptr = mem_get(ctx, size);
01265 MCTXLOCK(ctx, &ctx->lock);
01266 if (ptr != NULL)
01267 mem_getstats(ctx, size);
01268 }
01269
01270 ADD_TRACE(ctx, ptr, size, file, line);
01271 if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water) {
01272 ctx->is_overmem = ISC_TRUE;
01273 if (!ctx->hi_called)
01274 call_water = ISC_TRUE;
01275 }
01276 if (ctx->inuse > ctx->maxinuse) {
01277 ctx->maxinuse = ctx->inuse;
01278 if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
01279 (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0)
01280 fprintf(stderr, "maxinuse = %lu\n",
01281 (unsigned long)ctx->inuse);
01282 }
01283 MCTXUNLOCK(ctx, &ctx->lock);
01284
01285 if (call_water && (ctx->water != NULL))
01286 (ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
01287
01288 return (ptr);
01289 }
01290
01291 void
01292 isc___mem_put(isc_mem_t *ctx0, void *ptr, size_t size FLARG) {
01293 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01294 isc_boolean_t call_water = ISC_FALSE;
01295 size_info *si;
01296 size_t oldsize;
01297
01298 REQUIRE(VALID_CONTEXT(ctx));
01299 REQUIRE(ptr != NULL);
01300
01301 if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) {
01302 if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {
01303 si = &(((size_info *)ptr)[-1]);
01304 oldsize = si->u.size - ALIGNMENT_SIZE;
01305 if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
01306 oldsize -= ALIGNMENT_SIZE;
01307 INSIST(oldsize == size);
01308 }
01309 isc__mem_free((isc_mem_t *)ctx, ptr FLARG_PASS);
01310 return;
01311 }
01312
01313 MCTXLOCK(ctx, &ctx->lock);
01314
01315 DELETE_TRACE(ctx, ptr, size, file, line);
01316
01317 if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
01318 mem_putunlocked(ctx, ptr, size);
01319 } else {
01320 mem_putstats(ctx, ptr, size);
01321 mem_put(ctx, ptr, size);
01322 }
01323
01324
01325
01326
01327
01328
01329 if ((ctx->inuse < ctx->lo_water) || (ctx->lo_water == 0U)) {
01330 ctx->is_overmem = ISC_FALSE;
01331 if (ctx->hi_called)
01332 call_water = ISC_TRUE;
01333 }
01334
01335 MCTXUNLOCK(ctx, &ctx->lock);
01336
01337 if (call_water && (ctx->water != NULL))
01338 (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
01339 }
01340
01341 void
01342 isc__mem_waterack(isc_mem_t *ctx0, int flag) {
01343 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01344
01345 REQUIRE(VALID_CONTEXT(ctx));
01346
01347 MCTXLOCK(ctx, &ctx->lock);
01348 if (flag == ISC_MEM_LOWATER)
01349 ctx->hi_called = ISC_FALSE;
01350 else if (flag == ISC_MEM_HIWATER)
01351 ctx->hi_called = ISC_TRUE;
01352 MCTXUNLOCK(ctx, &ctx->lock);
01353 }
01354
01355 #if ISC_MEM_TRACKLINES
01356 static void
01357 print_active(isc__mem_t *mctx, FILE *out) {
01358 if (mctx->debuglist != NULL) {
01359 debuglink_t *dl;
01360 unsigned int i, j;
01361 const char *format;
01362 isc_boolean_t found;
01363
01364 fprintf(out, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
01365 ISC_MSG_DUMPALLOC,
01366 "Dump of all outstanding "
01367 "memory allocations:\n"));
01368 found = ISC_FALSE;
01369 format = isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
01370 ISC_MSG_PTRFILELINE,
01371 "\tptr %p size %u file %s line %u\n");
01372 for (i = 0; i <= mctx->max_size; i++) {
01373 dl = ISC_LIST_HEAD(mctx->debuglist[i]);
01374
01375 if (dl != NULL)
01376 found = ISC_TRUE;
01377
01378 while (dl != NULL) {
01379 for (j = 0; j < DEBUGLIST_COUNT; j++)
01380 if (dl->ptr[j] != NULL)
01381 fprintf(out, format,
01382 dl->ptr[j],
01383 dl->size[j],
01384 dl->file[j],
01385 dl->line[j]);
01386 dl = ISC_LIST_NEXT(dl, link);
01387 }
01388 }
01389 if (!found)
01390 fputs(isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
01391 ISC_MSG_NONE, "\tNone.\n"), out);
01392 }
01393 }
01394 #endif
01395
01396
01397
01398
01399 void
01400 isc_mem_stats(isc_mem_t *ctx0, FILE *out) {
01401 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01402 size_t i;
01403 const struct stats *s;
01404 const isc__mempool_t *pool;
01405
01406 REQUIRE(VALID_CONTEXT(ctx));
01407 MCTXLOCK(ctx, &ctx->lock);
01408
01409 for (i = 0; i <= ctx->max_size; i++) {
01410 s = &ctx->stats[i];
01411
01412 if (s->totalgets == 0U && s->gets == 0U)
01413 continue;
01414 fprintf(out, "%s%5lu: %11lu gets, %11lu rem",
01415 (i == ctx->max_size) ? ">=" : " ",
01416 (unsigned long) i, s->totalgets, s->gets);
01417 if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0 &&
01418 (s->blocks != 0U || s->freefrags != 0U))
01419 fprintf(out, " (%lu bl, %lu ff)",
01420 s->blocks, s->freefrags);
01421 fputc('\n', out);
01422 }
01423
01424
01425
01426
01427
01428
01429
01430
01431 pool = ISC_LIST_HEAD(ctx->pools);
01432 if (pool != NULL) {
01433 fprintf(out, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
01434 ISC_MSG_POOLSTATS,
01435 "[Pool statistics]\n"));
01436 fprintf(out, "%15s %10s %10s %10s %10s %10s %10s %10s %1s\n",
01437 isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
01438 ISC_MSG_POOLNAME, "name"),
01439 isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
01440 ISC_MSG_POOLSIZE, "size"),
01441 isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
01442 ISC_MSG_POOLMAXALLOC, "maxalloc"),
01443 isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
01444 ISC_MSG_POOLALLOCATED, "allocated"),
01445 isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
01446 ISC_MSG_POOLFREECOUNT, "freecount"),
01447 isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
01448 ISC_MSG_POOLFREEMAX, "freemax"),
01449 isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
01450 ISC_MSG_POOLFILLCOUNT, "fillcount"),
01451 isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
01452 ISC_MSG_POOLGETS, "gets"),
01453 "L");
01454 }
01455 while (pool != NULL) {
01456 fprintf(out, "%15s %10lu %10u %10u %10u %10u %10u %10u %s\n",
01457 #if ISC_MEMPOOL_NAMES
01458 pool->name,
01459 #else
01460 "(not tracked)",
01461 #endif
01462 (unsigned long) pool->size, pool->maxalloc,
01463 pool->allocated, pool->freecount, pool->freemax,
01464 pool->fillcount, pool->gets,
01465 (pool->lock == NULL ? "N" : "Y"));
01466 pool = ISC_LIST_NEXT(pool, link);
01467 }
01468
01469 #if ISC_MEM_TRACKLINES
01470 print_active(ctx, out);
01471 #endif
01472
01473 MCTXUNLOCK(ctx, &ctx->lock);
01474 }
01475
01476
01477
01478
01479
01480
01481 static void *
01482 mem_allocateunlocked(isc_mem_t *ctx0, size_t size) {
01483 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01484 size_info *si;
01485
01486 size += ALIGNMENT_SIZE;
01487 if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
01488 size += ALIGNMENT_SIZE;
01489
01490 if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0)
01491 si = mem_getunlocked(ctx, size);
01492 else
01493 si = mem_get(ctx, size);
01494
01495 if (si == NULL)
01496 return (NULL);
01497 if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) {
01498 si->u.ctx = ctx;
01499 si++;
01500 }
01501 si->u.size = size;
01502 return (&si[1]);
01503 }
01504
01505 void *
01506 isc___mem_allocate(isc_mem_t *ctx0, size_t size FLARG) {
01507 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01508 size_info *si;
01509 isc_boolean_t call_water = ISC_FALSE;
01510
01511 REQUIRE(VALID_CONTEXT(ctx));
01512
01513 MCTXLOCK(ctx, &ctx->lock);
01514 si = mem_allocateunlocked((isc_mem_t *)ctx, size);
01515 if (((ctx->flags & ISC_MEMFLAG_INTERNAL) == 0) && (si != NULL))
01516 mem_getstats(ctx, si[-1].u.size);
01517
01518 #if ISC_MEM_TRACKLINES
01519 ADD_TRACE(ctx, si, si[-1].u.size, file, line);
01520 #endif
01521 if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
01522 !ctx->is_overmem) {
01523 ctx->is_overmem = ISC_TRUE;
01524 }
01525
01526 if (ctx->hi_water != 0U && !ctx->hi_called &&
01527 ctx->inuse > ctx->hi_water) {
01528 ctx->hi_called = ISC_TRUE;
01529 call_water = ISC_TRUE;
01530 }
01531 if (ctx->inuse > ctx->maxinuse) {
01532 ctx->maxinuse = ctx->inuse;
01533 if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
01534 (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0)
01535 fprintf(stderr, "maxinuse = %lu\n",
01536 (unsigned long)ctx->inuse);
01537 }
01538 MCTXUNLOCK(ctx, &ctx->lock);
01539
01540 if (call_water)
01541 (ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
01542
01543 return (si);
01544 }
01545
01546 void *
01547 isc___mem_reallocate(isc_mem_t *ctx0, void *ptr, size_t size FLARG) {
01548 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01549 void *new_ptr = NULL;
01550 size_t oldsize, copysize;
01551
01552 REQUIRE(VALID_CONTEXT(ctx));
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565 if (size > 0U) {
01566 new_ptr = isc__mem_allocate(ctx0, size FLARG_PASS);
01567 if (new_ptr != NULL && ptr != NULL) {
01568 oldsize = (((size_info *)ptr)[-1]).u.size;
01569 INSIST(oldsize >= ALIGNMENT_SIZE);
01570 oldsize -= ALIGNMENT_SIZE;
01571 if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) {
01572 INSIST(oldsize >= ALIGNMENT_SIZE);
01573 oldsize -= ALIGNMENT_SIZE;
01574 }
01575 copysize = (oldsize > size) ? size : oldsize;
01576 memmove(new_ptr, ptr, copysize);
01577 isc__mem_free(ctx0, ptr FLARG_PASS);
01578 }
01579 } else if (ptr != NULL)
01580 isc__mem_free(ctx0, ptr FLARG_PASS);
01581
01582 return (new_ptr);
01583 }
01584
01585 void
01586 isc___mem_free(isc_mem_t *ctx0, void *ptr FLARG) {
01587 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01588 size_info *si;
01589 size_t size;
01590 isc_boolean_t call_water= ISC_FALSE;
01591
01592 REQUIRE(VALID_CONTEXT(ctx));
01593 REQUIRE(ptr != NULL);
01594
01595 if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) {
01596 si = &(((size_info *)ptr)[-2]);
01597 REQUIRE(si->u.ctx == ctx);
01598 size = si[1].u.size;
01599 } else {
01600 si = &(((size_info *)ptr)[-1]);
01601 size = si->u.size;
01602 }
01603
01604 MCTXLOCK(ctx, &ctx->lock);
01605
01606 DELETE_TRACE(ctx, ptr, size, file, line);
01607
01608 if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
01609 mem_putunlocked(ctx, si, size);
01610 } else {
01611 mem_putstats(ctx, si, size);
01612 mem_put(ctx, si, size);
01613 }
01614
01615
01616
01617
01618
01619
01620 if (ctx->is_overmem &&
01621 (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
01622 ctx->is_overmem = ISC_FALSE;
01623 }
01624
01625 if (ctx->hi_called &&
01626 (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
01627 ctx->hi_called = ISC_FALSE;
01628
01629 if (ctx->water != NULL)
01630 call_water = ISC_TRUE;
01631 }
01632 MCTXUNLOCK(ctx, &ctx->lock);
01633
01634 if (call_water)
01635 (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
01636 }
01637
01638
01639
01640
01641
01642
01643 char *
01644 isc___mem_strdup(isc_mem_t *mctx0, const char *s FLARG) {
01645 isc__mem_t *mctx = (isc__mem_t *)mctx0;
01646 size_t len;
01647 char *ns;
01648
01649 REQUIRE(VALID_CONTEXT(mctx));
01650 REQUIRE(s != NULL);
01651
01652 len = strlen(s);
01653
01654 ns = isc__mem_allocate((isc_mem_t *)mctx, len + 1 FLARG_PASS);
01655
01656 if (ns != NULL)
01657 strncpy(ns, s, len + 1);
01658
01659 return (ns);
01660 }
01661
01662 void
01663 isc__mem_setdestroycheck(isc_mem_t *ctx0, isc_boolean_t flag) {
01664 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01665
01666 REQUIRE(VALID_CONTEXT(ctx));
01667 MCTXLOCK(ctx, &ctx->lock);
01668
01669 ctx->checkfree = flag;
01670
01671 MCTXUNLOCK(ctx, &ctx->lock);
01672 }
01673
01674
01675
01676
01677
01678 void
01679 isc_mem_setquota(isc_mem_t *ctx0, size_t quota) {
01680 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01681
01682 REQUIRE(VALID_CONTEXT(ctx));
01683 MCTXLOCK(ctx, &ctx->lock);
01684
01685 ctx->quota = quota;
01686
01687 MCTXUNLOCK(ctx, &ctx->lock);
01688 }
01689
01690 size_t
01691 isc_mem_getquota(isc_mem_t *ctx0) {
01692 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01693 size_t quota;
01694
01695 REQUIRE(VALID_CONTEXT(ctx));
01696 MCTXLOCK(ctx, &ctx->lock);
01697
01698 quota = ctx->quota;
01699
01700 MCTXUNLOCK(ctx, &ctx->lock);
01701
01702 return (quota);
01703 }
01704
01705 size_t
01706 isc__mem_inuse(isc_mem_t *ctx0) {
01707 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01708 size_t inuse;
01709
01710 REQUIRE(VALID_CONTEXT(ctx));
01711 MCTXLOCK(ctx, &ctx->lock);
01712
01713 inuse = ctx->inuse;
01714
01715 MCTXUNLOCK(ctx, &ctx->lock);
01716
01717 return (inuse);
01718 }
01719
01720 size_t
01721 isc__mem_maxinuse(isc_mem_t *ctx0) {
01722 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01723 size_t maxinuse;
01724
01725 REQUIRE(VALID_CONTEXT(ctx));
01726 MCTXLOCK(ctx, &ctx->lock);
01727
01728 maxinuse = ctx->maxinuse;
01729
01730 MCTXUNLOCK(ctx, &ctx->lock);
01731
01732 return (maxinuse);
01733 }
01734
01735 size_t
01736 isc__mem_total(isc_mem_t *ctx0) {
01737 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01738 size_t total;
01739
01740 REQUIRE(VALID_CONTEXT(ctx));
01741 MCTXLOCK(ctx, &ctx->lock);
01742
01743 total = ctx->total;
01744
01745 MCTXUNLOCK(ctx, &ctx->lock);
01746
01747 return (total);
01748 }
01749
01750 void
01751 isc__mem_setwater(isc_mem_t *ctx0, isc_mem_water_t water, void *water_arg,
01752 size_t hiwater, size_t lowater)
01753 {
01754 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01755 isc_boolean_t callwater = ISC_FALSE;
01756 isc_mem_water_t oldwater;
01757 void *oldwater_arg;
01758
01759 REQUIRE(VALID_CONTEXT(ctx));
01760 REQUIRE(hiwater >= lowater);
01761
01762 MCTXLOCK(ctx, &ctx->lock);
01763 oldwater = ctx->water;
01764 oldwater_arg = ctx->water_arg;
01765 if (water == NULL) {
01766 callwater = ctx->hi_called;
01767 ctx->water = NULL;
01768 ctx->water_arg = NULL;
01769 ctx->hi_water = 0;
01770 ctx->lo_water = 0;
01771 } else {
01772 if (ctx->hi_called &&
01773 (ctx->water != water || ctx->water_arg != water_arg ||
01774 ctx->inuse < lowater || lowater == 0U))
01775 callwater = ISC_TRUE;
01776 ctx->water = water;
01777 ctx->water_arg = water_arg;
01778 ctx->hi_water = hiwater;
01779 ctx->lo_water = lowater;
01780 }
01781 MCTXUNLOCK(ctx, &ctx->lock);
01782
01783 if (callwater && oldwater != NULL)
01784 (oldwater)(oldwater_arg, ISC_MEM_LOWATER);
01785 }
01786
01787 isc_boolean_t
01788 isc__mem_isovermem(isc_mem_t *ctx0) {
01789 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01790
01791 REQUIRE(VALID_CONTEXT(ctx));
01792
01793
01794
01795
01796
01797
01798 return (ctx->is_overmem);
01799 }
01800
01801 void
01802 isc_mem_setname(isc_mem_t *ctx0, const char *name, void *tag) {
01803 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01804
01805 REQUIRE(VALID_CONTEXT(ctx));
01806
01807 LOCK(&ctx->lock);
01808 memset(ctx->name, 0, sizeof(ctx->name));
01809 strncpy(ctx->name, name, sizeof(ctx->name) - 1);
01810 ctx->tag = tag;
01811 UNLOCK(&ctx->lock);
01812 }
01813
01814 const char *
01815 isc_mem_getname(isc_mem_t *ctx0) {
01816 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01817
01818 REQUIRE(VALID_CONTEXT(ctx));
01819
01820 if (ctx->name[0] == 0)
01821 return ("");
01822
01823 return (ctx->name);
01824 }
01825
01826 void *
01827 isc_mem_gettag(isc_mem_t *ctx0) {
01828 isc__mem_t *ctx = (isc__mem_t *)ctx0;
01829
01830 REQUIRE(VALID_CONTEXT(ctx));
01831
01832 return (ctx->tag);
01833 }
01834
01835
01836
01837
01838
01839 isc_result_t
01840 isc__mempool_create(isc_mem_t *mctx0, size_t size, isc_mempool_t **mpctxp) {
01841 isc__mem_t *mctx = (isc__mem_t *)mctx0;
01842 isc__mempool_t *mpctx;
01843
01844 REQUIRE(VALID_CONTEXT(mctx));
01845 REQUIRE(size > 0U);
01846 REQUIRE(mpctxp != NULL && *mpctxp == NULL);
01847
01848
01849
01850
01851
01852 mpctx = isc_mem_get((isc_mem_t *)mctx, sizeof(isc__mempool_t));
01853 if (mpctx == NULL)
01854 return (ISC_R_NOMEMORY);
01855
01856 mpctx->common.methods = (isc_mempoolmethods_t *)&mempoolmethods;
01857 mpctx->common.impmagic = MEMPOOL_MAGIC;
01858 mpctx->common.magic = ISCAPI_MPOOL_MAGIC;
01859 mpctx->lock = NULL;
01860 mpctx->mctx = mctx;
01861 mpctx->size = size;
01862 mpctx->maxalloc = UINT_MAX;
01863 mpctx->allocated = 0;
01864 mpctx->freecount = 0;
01865 mpctx->freemax = 1;
01866 mpctx->fillcount = 1;
01867 mpctx->gets = 0;
01868 #if ISC_MEMPOOL_NAMES
01869 mpctx->name[0] = 0;
01870 #endif
01871 mpctx->items = NULL;
01872
01873 *mpctxp = (isc_mempool_t *)mpctx;
01874
01875 MCTXLOCK(mctx, &mctx->lock);
01876 ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link);
01877 mctx->poolcnt++;
01878 MCTXUNLOCK(mctx, &mctx->lock);
01879
01880 return (ISC_R_SUCCESS);
01881 }
01882
01883 void
01884 isc__mempool_setname(isc_mempool_t *mpctx0, const char *name) {
01885 isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
01886
01887 REQUIRE(name != NULL);
01888 REQUIRE(VALID_MEMPOOL(mpctx));
01889
01890 #if ISC_MEMPOOL_NAMES
01891 if (mpctx->lock != NULL)
01892 LOCK(mpctx->lock);
01893
01894 strncpy(mpctx->name, name, sizeof(mpctx->name) - 1);
01895 mpctx->name[sizeof(mpctx->name) - 1] = '\0';
01896
01897 if (mpctx->lock != NULL)
01898 UNLOCK(mpctx->lock);
01899 #else
01900 UNUSED(mpctx);
01901 UNUSED(name);
01902 #endif
01903 }
01904
01905 void
01906 isc__mempool_destroy(isc_mempool_t **mpctxp) {
01907 isc__mempool_t *mpctx;
01908 isc__mem_t *mctx;
01909 isc_mutex_t *lock;
01910 element *item;
01911
01912 REQUIRE(mpctxp != NULL);
01913 mpctx = (isc__mempool_t *)*mpctxp;
01914 REQUIRE(VALID_MEMPOOL(mpctx));
01915 #if ISC_MEMPOOL_NAMES
01916 if (mpctx->allocated > 0)
01917 UNEXPECTED_ERROR(__FILE__, __LINE__,
01918 "isc__mempool_destroy(): mempool %s "
01919 "leaked memory",
01920 mpctx->name);
01921 #endif
01922 REQUIRE(mpctx->allocated == 0);
01923
01924 mctx = mpctx->mctx;
01925
01926 lock = mpctx->lock;
01927
01928 if (lock != NULL)
01929 LOCK(lock);
01930
01931
01932
01933
01934 MCTXLOCK(mctx, &mctx->lock);
01935 while (mpctx->items != NULL) {
01936 INSIST(mpctx->freecount > 0);
01937 mpctx->freecount--;
01938 item = mpctx->items;
01939 mpctx->items = item->next;
01940
01941 if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
01942 mem_putunlocked(mctx, item, mpctx->size);
01943 } else {
01944 mem_putstats(mctx, item, mpctx->size);
01945 mem_put(mctx, item, mpctx->size);
01946 }
01947 }
01948 MCTXUNLOCK(mctx, &mctx->lock);
01949
01950
01951
01952
01953 MCTXLOCK(mctx, &mctx->lock);
01954 ISC_LIST_UNLINK(mctx->pools, mpctx, link);
01955 mctx->poolcnt--;
01956 MCTXUNLOCK(mctx, &mctx->lock);
01957
01958 mpctx->common.impmagic = 0;
01959 mpctx->common.magic = 0;
01960
01961 isc_mem_put((isc_mem_t *)mpctx->mctx, mpctx, sizeof(isc__mempool_t));
01962
01963 if (lock != NULL)
01964 UNLOCK(lock);
01965
01966 *mpctxp = NULL;
01967 }
01968
01969 void
01970 isc__mempool_associatelock(isc_mempool_t *mpctx0, isc_mutex_t *lock) {
01971 isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
01972
01973 REQUIRE(VALID_MEMPOOL(mpctx));
01974 REQUIRE(mpctx->lock == NULL);
01975 REQUIRE(lock != NULL);
01976
01977 mpctx->lock = lock;
01978 }
01979
01980 void *
01981 isc___mempool_get(isc_mempool_t *mpctx0 FLARG) {
01982 isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
01983 element *item;
01984 isc__mem_t *mctx;
01985 unsigned int i;
01986
01987 REQUIRE(VALID_MEMPOOL(mpctx));
01988
01989 mctx = mpctx->mctx;
01990
01991 if (mpctx->lock != NULL)
01992 LOCK(mpctx->lock);
01993
01994
01995
01996
01997 if (mpctx->allocated >= mpctx->maxalloc) {
01998 item = NULL;
01999 goto out;
02000 }
02001
02002
02003
02004
02005 item = mpctx->items;
02006 if (item != NULL) {
02007 mpctx->items = item->next;
02008 INSIST(mpctx->freecount > 0);
02009 mpctx->freecount--;
02010 mpctx->gets++;
02011 mpctx->allocated++;
02012 goto out;
02013 }
02014
02015
02016
02017
02018
02019 MCTXLOCK(mctx, &mctx->lock);
02020 for (i = 0; i < mpctx->fillcount; i++) {
02021 if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
02022 item = mem_getunlocked(mctx, mpctx->size);
02023 } else {
02024 item = mem_get(mctx, mpctx->size);
02025 if (item != NULL)
02026 mem_getstats(mctx, mpctx->size);
02027 }
02028 if (item == NULL)
02029 break;
02030 item->next = mpctx->items;
02031 mpctx->items = item;
02032 mpctx->freecount++;
02033 }
02034 MCTXUNLOCK(mctx, &mctx->lock);
02035
02036
02037
02038
02039 item = mpctx->items;
02040 if (item == NULL)
02041 goto out;
02042
02043 mpctx->items = item->next;
02044 mpctx->freecount--;
02045 mpctx->gets++;
02046 mpctx->allocated++;
02047
02048 out:
02049 if (mpctx->lock != NULL)
02050 UNLOCK(mpctx->lock);
02051
02052 #if ISC_MEM_TRACKLINES
02053 if (item != NULL) {
02054 MCTXLOCK(mctx, &mctx->lock);
02055 ADD_TRACE(mctx, item, mpctx->size, file, line);
02056 MCTXUNLOCK(mctx, &mctx->lock);
02057 }
02058 #endif
02059
02060 return (item);
02061 }
02062
02063
02064 void
02065 isc___mempool_put(isc_mempool_t *mpctx0, void *mem FLARG) {
02066 isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
02067 isc__mem_t *mctx;
02068 element *item;
02069
02070 REQUIRE(VALID_MEMPOOL(mpctx));
02071 REQUIRE(mem != NULL);
02072
02073 mctx = mpctx->mctx;
02074
02075 if (mpctx->lock != NULL)
02076 LOCK(mpctx->lock);
02077
02078 INSIST(mpctx->allocated > 0);
02079 mpctx->allocated--;
02080
02081 #if ISC_MEM_TRACKLINES
02082 MCTXLOCK(mctx, &mctx->lock);
02083 DELETE_TRACE(mctx, mem, mpctx->size, file, line);
02084 MCTXUNLOCK(mctx, &mctx->lock);
02085 #endif
02086
02087
02088
02089
02090 if (mpctx->freecount >= mpctx->freemax) {
02091 MCTXLOCK(mctx, &mctx->lock);
02092 if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
02093 mem_putunlocked(mctx, mem, mpctx->size);
02094 } else {
02095 mem_putstats(mctx, mem, mpctx->size);
02096 mem_put(mctx, mem, mpctx->size);
02097 }
02098 MCTXUNLOCK(mctx, &mctx->lock);
02099 if (mpctx->lock != NULL)
02100 UNLOCK(mpctx->lock);
02101 return;
02102 }
02103
02104
02105
02106
02107 mpctx->freecount++;
02108 item = (element *)mem;
02109 item->next = mpctx->items;
02110 mpctx->items = item;
02111
02112 if (mpctx->lock != NULL)
02113 UNLOCK(mpctx->lock);
02114 }
02115
02116
02117
02118
02119
02120 void
02121 isc__mempool_setfreemax(isc_mempool_t *mpctx0, unsigned int limit) {
02122 isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
02123
02124 REQUIRE(VALID_MEMPOOL(mpctx));
02125
02126 if (mpctx->lock != NULL)
02127 LOCK(mpctx->lock);
02128
02129 mpctx->freemax = limit;
02130
02131 if (mpctx->lock != NULL)
02132 UNLOCK(mpctx->lock);
02133 }
02134
02135 unsigned int
02136 isc_mempool_getfreemax(isc_mempool_t *mpctx0) {
02137 isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
02138 unsigned int freemax;
02139
02140 REQUIRE(VALID_MEMPOOL(mpctx));
02141
02142 if (mpctx->lock != NULL)
02143 LOCK(mpctx->lock);
02144
02145 freemax = mpctx->freemax;
02146
02147 if (mpctx->lock != NULL)
02148 UNLOCK(mpctx->lock);
02149
02150 return (freemax);
02151 }
02152
02153 unsigned int
02154 isc_mempool_getfreecount(isc_mempool_t *mpctx0) {
02155 isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
02156 unsigned int freecount;
02157
02158 REQUIRE(VALID_MEMPOOL(mpctx));
02159
02160 if (mpctx->lock != NULL)
02161 LOCK(mpctx->lock);
02162
02163 freecount = mpctx->freecount;
02164
02165 if (mpctx->lock != NULL)
02166 UNLOCK(mpctx->lock);
02167
02168 return (freecount);
02169 }
02170
02171 void
02172 isc__mempool_setmaxalloc(isc_mempool_t *mpctx0, unsigned int limit) {
02173 isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
02174
02175 REQUIRE(limit > 0);
02176
02177 REQUIRE(VALID_MEMPOOL(mpctx));
02178
02179 if (mpctx->lock != NULL)
02180 LOCK(mpctx->lock);
02181
02182 mpctx->maxalloc = limit;
02183
02184 if (mpctx->lock != NULL)
02185 UNLOCK(mpctx->lock);
02186 }
02187
02188 unsigned int
02189 isc_mempool_getmaxalloc(isc_mempool_t *mpctx0) {
02190 isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
02191 unsigned int maxalloc;
02192
02193 REQUIRE(VALID_MEMPOOL(mpctx));
02194
02195 if (mpctx->lock != NULL)
02196 LOCK(mpctx->lock);
02197
02198 maxalloc = mpctx->maxalloc;
02199
02200 if (mpctx->lock != NULL)
02201 UNLOCK(mpctx->lock);
02202
02203 return (maxalloc);
02204 }
02205
02206 unsigned int
02207 isc__mempool_getallocated(isc_mempool_t *mpctx0) {
02208 isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
02209 unsigned int allocated;
02210
02211 REQUIRE(VALID_MEMPOOL(mpctx));
02212
02213 if (mpctx->lock != NULL)
02214 LOCK(mpctx->lock);
02215
02216 allocated = mpctx->allocated;
02217
02218 if (mpctx->lock != NULL)
02219 UNLOCK(mpctx->lock);
02220
02221 return (allocated);
02222 }
02223
02224 void
02225 isc__mempool_setfillcount(isc_mempool_t *mpctx0, unsigned int limit) {
02226 isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
02227
02228 REQUIRE(limit > 0);
02229 REQUIRE(VALID_MEMPOOL(mpctx));
02230
02231 if (mpctx->lock != NULL)
02232 LOCK(mpctx->lock);
02233
02234 mpctx->fillcount = limit;
02235
02236 if (mpctx->lock != NULL)
02237 UNLOCK(mpctx->lock);
02238 }
02239
02240 unsigned int
02241 isc_mempool_getfillcount(isc_mempool_t *mpctx0) {
02242 isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
02243
02244 unsigned int fillcount;
02245
02246 REQUIRE(VALID_MEMPOOL(mpctx));
02247
02248 if (mpctx->lock != NULL)
02249 LOCK(mpctx->lock);
02250
02251 fillcount = mpctx->fillcount;
02252
02253 if (mpctx->lock != NULL)
02254 UNLOCK(mpctx->lock);
02255
02256 return (fillcount);
02257 }
02258
02259 isc_result_t
02260 isc__mem_register(void) {
02261 return (isc_mem_register(isc_mem_create2));
02262 }
02263
02264 void
02265 isc__mem_printactive(isc_mem_t *ctx0, FILE *file) {
02266 #if ISC_MEM_TRACKLINES
02267 isc__mem_t *ctx = (isc__mem_t *)ctx0;
02268
02269 REQUIRE(VALID_CONTEXT(ctx));
02270 REQUIRE(file != NULL);
02271
02272 print_active(ctx, file);
02273 #else
02274 UNUSED(ctx0);
02275 UNUSED(file);
02276 #endif
02277 }
02278
02279 void
02280 isc_mem_printallactive(FILE *file) {
02281 #if !ISC_MEM_TRACKLINES
02282 UNUSED(file);
02283 #else
02284 isc__mem_t *ctx;
02285
02286 RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
02287
02288 LOCK(&contextslock);
02289 for (ctx = ISC_LIST_HEAD(contexts);
02290 ctx != NULL;
02291 ctx = ISC_LIST_NEXT(ctx, link)) {
02292 fprintf(file, "context: %p\n", ctx);
02293 print_active(ctx, file);
02294 }
02295 UNLOCK(&contextslock);
02296 #endif
02297 }
02298
02299 void
02300 isc_mem_checkdestroyed(FILE *file) {
02301 #if !ISC_MEM_TRACKLINES
02302 UNUSED(file);
02303 #endif
02304
02305 RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
02306
02307 LOCK(&contextslock);
02308 if (!ISC_LIST_EMPTY(contexts)) {
02309 #if ISC_MEM_TRACKLINES
02310 isc__mem_t *ctx;
02311
02312 for (ctx = ISC_LIST_HEAD(contexts);
02313 ctx != NULL;
02314 ctx = ISC_LIST_NEXT(ctx, link)) {
02315 fprintf(file, "context: %p\n", ctx);
02316 print_active(ctx, file);
02317 }
02318 fflush(file);
02319 #endif
02320 INSIST(0);
02321 }
02322 UNLOCK(&contextslock);
02323 }
02324
02325 unsigned int
02326 isc_mem_references(isc_mem_t *ctx0) {
02327 isc__mem_t *ctx = (isc__mem_t *)ctx0;
02328 unsigned int references;
02329
02330 REQUIRE(VALID_CONTEXT(ctx));
02331
02332 MCTXLOCK(ctx, &ctx->lock);
02333 references = ctx->references;
02334 MCTXUNLOCK(ctx, &ctx->lock);
02335
02336 return (references);
02337 }
02338
02339 #if defined(HAVE_LIBXML2) || defined(HAVE_JSON)
02340 typedef struct summarystat {
02341 isc_uint64_t total;
02342 isc_uint64_t inuse;
02343 isc_uint64_t blocksize;
02344 isc_uint64_t contextsize;
02345 } summarystat_t;
02346 #endif
02347
02348 #ifdef HAVE_LIBXML2
02349 #define TRY0(a) do { xmlrc = (a); if (xmlrc < 0) goto error; } while(0)
02350 static int
02351 xml_renderctx(isc__mem_t *ctx, summarystat_t *summary,
02352 xmlTextWriterPtr writer)
02353 {
02354 int xmlrc;
02355
02356 REQUIRE(VALID_CONTEXT(ctx));
02357
02358 MCTXLOCK(ctx, &ctx->lock);
02359
02360 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "context"));
02361
02362 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "id"));
02363 TRY0(xmlTextWriterWriteFormatString(writer, "%p", ctx));
02364 TRY0(xmlTextWriterEndElement(writer));
02365
02366 if (ctx->name[0] != 0) {
02367 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "name"));
02368 TRY0(xmlTextWriterWriteFormatString(writer, "%s", ctx->name));
02369 TRY0(xmlTextWriterEndElement(writer));
02370 }
02371
02372 summary->contextsize += sizeof(*ctx) +
02373 (ctx->max_size + 1) * sizeof(struct stats) +
02374 ctx->max_size * sizeof(element *) +
02375 ctx->basic_table_count * sizeof(char *);
02376 #if ISC_MEM_TRACKLINES
02377 if (ctx->debuglist != NULL) {
02378 summary->contextsize +=
02379 (ctx->max_size + 1) * sizeof(debuglist_t) +
02380 ctx->debuglistcnt * sizeof(debuglink_t);
02381 }
02382 #endif
02383 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "references"));
02384 TRY0(xmlTextWriterWriteFormatString(writer, "%d", ctx->references));
02385 TRY0(xmlTextWriterEndElement(writer));
02386
02387 summary->total += ctx->total;
02388 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "total"));
02389 TRY0(xmlTextWriterWriteFormatString(writer,
02390 "%" ISC_PRINT_QUADFORMAT "u",
02391 (isc_uint64_t)ctx->total));
02392 TRY0(xmlTextWriterEndElement(writer));
02393
02394 summary->inuse += ctx->inuse;
02395 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "inuse"));
02396 TRY0(xmlTextWriterWriteFormatString(writer,
02397 "%" ISC_PRINT_QUADFORMAT "u",
02398 (isc_uint64_t)ctx->inuse));
02399 TRY0(xmlTextWriterEndElement(writer));
02400
02401 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "maxinuse"));
02402 TRY0(xmlTextWriterWriteFormatString(writer,
02403 "%" ISC_PRINT_QUADFORMAT "u",
02404 (isc_uint64_t)ctx->maxinuse));
02405 TRY0(xmlTextWriterEndElement(writer));
02406
02407 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "blocksize"));
02408 if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
02409 summary->blocksize += ctx->basic_table_count *
02410 NUM_BASIC_BLOCKS * ctx->mem_target;
02411 TRY0(xmlTextWriterWriteFormatString(writer,
02412 "%" ISC_PRINT_QUADFORMAT "u",
02413 (isc_uint64_t)
02414 ctx->basic_table_count *
02415 NUM_BASIC_BLOCKS *
02416 ctx->mem_target));
02417 } else
02418 TRY0(xmlTextWriterWriteFormatString(writer, "%s", "-"));
02419 TRY0(xmlTextWriterEndElement(writer));
02420
02421 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "pools"));
02422 TRY0(xmlTextWriterWriteFormatString(writer, "%u", ctx->poolcnt));
02423 TRY0(xmlTextWriterEndElement(writer));
02424 summary->contextsize += ctx->poolcnt * sizeof(isc_mempool_t);
02425
02426 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "hiwater"));
02427 TRY0(xmlTextWriterWriteFormatString(writer,
02428 "%" ISC_PRINT_QUADFORMAT "u",
02429 (isc_uint64_t)ctx->hi_water));
02430 TRY0(xmlTextWriterEndElement(writer));
02431
02432 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "lowater"));
02433 TRY0(xmlTextWriterWriteFormatString(writer,
02434 "%" ISC_PRINT_QUADFORMAT "u",
02435 (isc_uint64_t)ctx->lo_water));
02436 TRY0(xmlTextWriterEndElement(writer));
02437
02438 TRY0(xmlTextWriterEndElement(writer));
02439
02440 error:
02441 MCTXUNLOCK(ctx, &ctx->lock);
02442
02443 return (xmlrc);
02444 }
02445
02446 int
02447 isc_mem_renderxml(xmlTextWriterPtr writer) {
02448 isc__mem_t *ctx;
02449 summarystat_t summary;
02450 isc_uint64_t lost;
02451 int xmlrc;
02452
02453 memset(&summary, 0, sizeof(summary));
02454
02455 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "contexts"));
02456
02457 RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
02458
02459 LOCK(&contextslock);
02460 lost = totallost;
02461 for (ctx = ISC_LIST_HEAD(contexts);
02462 ctx != NULL;
02463 ctx = ISC_LIST_NEXT(ctx, link)) {
02464 xmlrc = xml_renderctx(ctx, &summary, writer);
02465 if (xmlrc < 0) {
02466 UNLOCK(&contextslock);
02467 goto error;
02468 }
02469 }
02470 UNLOCK(&contextslock);
02471
02472 TRY0(xmlTextWriterEndElement(writer));
02473
02474 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "summary"));
02475
02476 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "TotalUse"));
02477 TRY0(xmlTextWriterWriteFormatString(writer,
02478 "%" ISC_PRINT_QUADFORMAT "u",
02479 summary.total));
02480 TRY0(xmlTextWriterEndElement(writer));
02481
02482 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "InUse"));
02483 TRY0(xmlTextWriterWriteFormatString(writer,
02484 "%" ISC_PRINT_QUADFORMAT "u",
02485 summary.inuse));
02486 TRY0(xmlTextWriterEndElement(writer));
02487
02488 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "BlockSize"));
02489 TRY0(xmlTextWriterWriteFormatString(writer,
02490 "%" ISC_PRINT_QUADFORMAT "u",
02491 summary.blocksize));
02492 TRY0(xmlTextWriterEndElement(writer));
02493
02494 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ContextSize"));
02495 TRY0(xmlTextWriterWriteFormatString(writer,
02496 "%" ISC_PRINT_QUADFORMAT "u",
02497 summary.contextsize));
02498 TRY0(xmlTextWriterEndElement(writer));
02499
02500 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "Lost"));
02501 TRY0(xmlTextWriterWriteFormatString(writer,
02502 "%" ISC_PRINT_QUADFORMAT "u",
02503 lost));
02504 TRY0(xmlTextWriterEndElement(writer));
02505
02506 TRY0(xmlTextWriterEndElement(writer));
02507 error:
02508 return (xmlrc);
02509 }
02510
02511 #endif
02512
02513 #ifdef HAVE_JSON
02514 #define CHECKMEM(m) do { \
02515 if (m == NULL) { \
02516 result = ISC_R_NOMEMORY;\
02517 goto error;\
02518 } \
02519 } while(0)
02520
02521 static isc_result_t
02522 json_renderctx(isc__mem_t *ctx, summarystat_t *summary, json_object *array) {
02523 isc_result_t result = ISC_R_FAILURE;
02524 json_object *ctxobj, *obj;
02525 char buf[1024];
02526
02527 REQUIRE(VALID_CONTEXT(ctx));
02528 REQUIRE(summary != NULL);
02529 REQUIRE(array != NULL);
02530
02531 MCTXLOCK(ctx, &ctx->lock);
02532
02533 summary->contextsize += sizeof(*ctx) +
02534 (ctx->max_size + 1) * sizeof(struct stats) +
02535 ctx->max_size * sizeof(element *) +
02536 ctx->basic_table_count * sizeof(char *);
02537 summary->total += ctx->total;
02538 summary->inuse += ctx->inuse;
02539 if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0)
02540 summary->blocksize += ctx->basic_table_count *
02541 NUM_BASIC_BLOCKS * ctx->mem_target;
02542 #if ISC_MEM_TRACKLINES
02543 if (ctx->debuglist != NULL) {
02544 summary->contextsize +=
02545 (ctx->max_size + 1) * sizeof(debuglist_t) +
02546 ctx->debuglistcnt * sizeof(debuglink_t);
02547 }
02548 #endif
02549
02550 ctxobj = json_object_new_object();
02551 CHECKMEM(ctxobj);
02552
02553 sprintf(buf, "%p", ctx);
02554 obj = json_object_new_string(buf);
02555 CHECKMEM(obj);
02556 json_object_object_add(ctxobj, "id", obj);
02557
02558 if (ctx->name[0] != 0) {
02559 obj = json_object_new_string(ctx->name);
02560 CHECKMEM(obj);
02561 json_object_object_add(ctxobj, "name", obj);
02562 }
02563
02564 obj = json_object_new_int64(ctx->references);
02565 CHECKMEM(obj);
02566 json_object_object_add(ctxobj, "references", obj);
02567
02568 obj = json_object_new_int64(ctx->total);
02569 CHECKMEM(obj);
02570 json_object_object_add(ctxobj, "total", obj);
02571
02572 obj = json_object_new_int64(ctx->inuse);
02573 CHECKMEM(obj);
02574 json_object_object_add(ctxobj, "inuse", obj);
02575
02576 obj = json_object_new_int64(ctx->maxinuse);
02577 CHECKMEM(obj);
02578 json_object_object_add(ctxobj, "maxinuse", obj);
02579
02580 if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
02581 isc_uint64_t blocksize;
02582 blocksize = ctx->basic_table_count * NUM_BASIC_BLOCKS *
02583 ctx->mem_target;
02584 obj = json_object_new_int64(blocksize);
02585 CHECKMEM(obj);
02586 json_object_object_add(ctxobj, "blocksize", obj);
02587 }
02588
02589 obj = json_object_new_int64(ctx->poolcnt);
02590 CHECKMEM(obj);
02591 json_object_object_add(ctxobj, "pools", obj);
02592
02593 summary->contextsize += ctx->poolcnt * sizeof(isc_mempool_t);
02594
02595 obj = json_object_new_int64(ctx->hi_water);
02596 CHECKMEM(obj);
02597 json_object_object_add(ctxobj, "hiwater", obj);
02598
02599 obj = json_object_new_int64(ctx->lo_water);
02600 CHECKMEM(obj);
02601 json_object_object_add(ctxobj, "lowater", obj);
02602
02603 MCTXUNLOCK(ctx, &ctx->lock);
02604 json_object_array_add(array, ctxobj);
02605 return (ISC_R_SUCCESS);
02606
02607 error:
02608 MCTXUNLOCK(ctx, &ctx->lock);
02609 if (ctxobj != NULL)
02610 json_object_put(ctxobj);
02611 return (result);
02612 }
02613
02614 isc_result_t
02615 isc_mem_renderjson(json_object *memobj) {
02616 isc_result_t result = ISC_R_SUCCESS;
02617 isc__mem_t *ctx;
02618 summarystat_t summary;
02619 isc_uint64_t lost;
02620 json_object *ctxarray, *obj;
02621
02622 memset(&summary, 0, sizeof(summary));
02623 RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
02624
02625 ctxarray = json_object_new_array();
02626 CHECKMEM(ctxarray);
02627
02628 LOCK(&contextslock);
02629 lost = totallost;
02630 for (ctx = ISC_LIST_HEAD(contexts);
02631 ctx != NULL;
02632 ctx = ISC_LIST_NEXT(ctx, link)) {
02633 result = json_renderctx(ctx, &summary, ctxarray);
02634 if (result != ISC_R_SUCCESS) {
02635 UNLOCK(&contextslock);
02636 goto error;
02637 }
02638 }
02639 UNLOCK(&contextslock);
02640
02641 obj = json_object_new_int64(summary.total);
02642 CHECKMEM(obj);
02643 json_object_object_add(memobj, "TotalUse", obj);
02644
02645 obj = json_object_new_int64(summary.inuse);
02646 CHECKMEM(obj);
02647 json_object_object_add(memobj, "InUse", obj);
02648
02649 obj = json_object_new_int64(summary.blocksize);
02650 CHECKMEM(obj);
02651 json_object_object_add(memobj, "BlockSize", obj);
02652
02653 obj = json_object_new_int64(summary.contextsize);
02654 CHECKMEM(obj);
02655 json_object_object_add(memobj, "ContextSize", obj);
02656
02657 obj = json_object_new_int64(lost);
02658 CHECKMEM(obj);
02659 json_object_object_add(memobj, "Lost", obj);
02660
02661 json_object_object_add(memobj, "contexts", ctxarray);
02662 return (ISC_R_SUCCESS);
02663
02664 error:
02665 if (ctxarray != NULL)
02666 json_object_put(ctxarray);
02667 return (result);
02668 }
02669 #endif
02670
02671 static isc_memcreatefunc_t mem_createfunc = NULL;
02672
02673 isc_result_t
02674 isc_mem_register(isc_memcreatefunc_t createfunc) {
02675 isc_result_t result = ISC_R_SUCCESS;
02676
02677 RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
02678
02679 LOCK(&createlock);
02680 if (mem_createfunc == NULL)
02681 mem_createfunc = createfunc;
02682 else
02683 result = ISC_R_EXISTS;
02684 UNLOCK(&createlock);
02685
02686 return (result);
02687 }
02688
02689
02690 isc_result_t
02691 isc__mem_create2(size_t init_max_size, size_t target_size, isc_mem_t **mctxp,
02692 unsigned int flags)
02693 {
02694 isc_result_t result;
02695
02696 LOCK(&createlock);
02697
02698 REQUIRE(mem_createfunc != NULL);
02699 result = (*mem_createfunc)(init_max_size, target_size, mctxp, flags);
02700
02701 UNLOCK(&createlock);
02702
02703 return (result);
02704 }
02705
02706 isc_result_t
02707 isc_mem_create(size_t init_max_size, size_t target_size, isc_mem_t **mctxp) {
02708 isc_result_t result;
02709
02710 if (isc_bind9)
02711 return (isc_mem_createx2(init_max_size, target_size,
02712 default_memalloc, default_memfree,
02713 NULL, mctxp, isc_mem_defaultflags));
02714 LOCK(&createlock);
02715
02716 REQUIRE(mem_createfunc != NULL);
02717 result = (*mem_createfunc)(init_max_size, target_size, mctxp,
02718 isc_mem_defaultflags);
02719
02720 UNLOCK(&createlock);
02721
02722 return (result);
02723 }
02724
02725 isc_result_t
02726 isc_mem_create2(size_t init_max_size, size_t target_size, isc_mem_t **mctxp,
02727 unsigned int flags)
02728 {
02729 if (isc_bind9)
02730 return (isc_mem_createx2(init_max_size, target_size,
02731 default_memalloc, default_memfree,
02732 NULL, mctxp, flags));
02733
02734 return (isc_mem_createx2(init_max_size, target_size,
02735 default_memalloc, default_memfree,
02736 NULL, mctxp, flags));
02737 }
02738
02739 void
02740 isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
02741 REQUIRE(ISCAPI_MCTX_VALID(source));
02742 REQUIRE(targetp != NULL && *targetp == NULL);
02743
02744 if (isc_bind9)
02745 isc__mem_attach(source, targetp);
02746 else
02747 source->methods->attach(source, targetp);
02748
02749 ENSURE(*targetp == source);
02750 }
02751
02752 void
02753 isc_mem_detach(isc_mem_t **mctxp) {
02754 REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
02755
02756 if (isc_bind9)
02757 isc__mem_detach(mctxp);
02758 else
02759 (*mctxp)->methods->detach(mctxp);
02760
02761 ENSURE(*mctxp == NULL);
02762 }
02763
02764 void
02765 isc_mem_destroy(isc_mem_t **mctxp) {
02766 REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
02767
02768 if (isc_bind9)
02769 isc__mem_destroy(mctxp);
02770 else
02771 (*mctxp)->methods->destroy(mctxp);
02772
02773 ENSURE(*mctxp == NULL);
02774 }
02775
02776 void
02777 isc_mem_setdestroycheck(isc_mem_t *mctx, isc_boolean_t flag) {
02778 REQUIRE(ISCAPI_MCTX_VALID(mctx));
02779
02780 mctx->methods->setdestroycheck(mctx, flag);
02781 }
02782
02783 void
02784 isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
02785 size_t hiwater, size_t lowater)
02786 {
02787 REQUIRE(ISCAPI_MCTX_VALID(ctx));
02788
02789 if (isc_bind9)
02790 isc__mem_setwater(ctx, water, water_arg, hiwater, lowater);
02791 else
02792 ctx->methods->setwater(ctx, water, water_arg, hiwater, lowater);
02793 }
02794
02795 void
02796 isc_mem_waterack(isc_mem_t *ctx, int flag) {
02797 REQUIRE(ISCAPI_MCTX_VALID(ctx));
02798
02799 if (isc_bind9)
02800 isc__mem_waterack(ctx, flag);
02801 else
02802 ctx->methods->waterack(ctx, flag);
02803 }
02804
02805 size_t
02806 isc_mem_inuse(isc_mem_t *mctx) {
02807 REQUIRE(ISCAPI_MCTX_VALID(mctx));
02808
02809 if (isc_bind9)
02810 return (isc__mem_inuse(mctx));
02811
02812 return (mctx->methods->inuse(mctx));
02813 }
02814
02815 size_t
02816 isc_mem_maxinuse(isc_mem_t *mctx) {
02817 REQUIRE(ISCAPI_MCTX_VALID(mctx));
02818
02819 if (isc_bind9)
02820 return (isc__mem_maxinuse(mctx));
02821
02822 return (mctx->methods->maxinuse(mctx));
02823 }
02824
02825 size_t
02826 isc_mem_total(isc_mem_t *mctx) {
02827 REQUIRE(ISCAPI_MCTX_VALID(mctx));
02828
02829 if (isc_bind9)
02830 return (isc__mem_total(mctx));
02831
02832 return (mctx->methods->total(mctx));
02833 }
02834
02835 isc_boolean_t
02836 isc_mem_isovermem(isc_mem_t *mctx) {
02837 REQUIRE(ISCAPI_MCTX_VALID(mctx));
02838
02839 if (isc_bind9)
02840 return (isc__mem_isovermem(mctx));
02841
02842 return (mctx->methods->isovermem(mctx));
02843 }
02844
02845
02846 isc_result_t
02847 isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
02848 REQUIRE(ISCAPI_MCTX_VALID(mctx));
02849
02850 return (mctx->methods->mpcreate(mctx, size, mpctxp));
02851 }
02852
02853 void
02854 isc_mempool_destroy(isc_mempool_t **mpctxp) {
02855 REQUIRE(mpctxp != NULL && ISCAPI_MPOOL_VALID(*mpctxp));
02856
02857 if (isc_bind9)
02858 isc__mempool_destroy(mpctxp);
02859 else
02860 (*mpctxp)->methods->destroy(mpctxp);
02861
02862 ENSURE(*mpctxp == NULL);
02863 }
02864
02865 unsigned int
02866 isc_mempool_getallocated(isc_mempool_t *mpctx) {
02867 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
02868
02869 if (isc_bind9)
02870 return (isc__mempool_getallocated(mpctx));
02871
02872 return (mpctx->methods->getallocated(mpctx));
02873 }
02874
02875 void
02876 isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
02877 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
02878
02879 if (isc_bind9)
02880 isc__mempool_setmaxalloc(mpctx, limit);
02881 else
02882 mpctx->methods->setmaxalloc(mpctx, limit);
02883 }
02884
02885 void
02886 isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
02887 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
02888
02889 if (isc_bind9)
02890 isc__mempool_setfreemax(mpctx, limit);
02891 else
02892 mpctx->methods->setfreemax(mpctx, limit);
02893 }
02894
02895 void
02896 isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
02897 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
02898
02899 if (isc_bind9)
02900 isc__mempool_setname(mpctx, name);
02901 else
02902 mpctx->methods->setname(mpctx, name);
02903 }
02904
02905 void
02906 isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
02907 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
02908
02909 if (isc_bind9)
02910 isc__mempool_associatelock(mpctx, lock);
02911 else
02912 mpctx->methods->associatelock(mpctx, lock);
02913 }
02914
02915 void
02916 isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
02917 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
02918
02919 if (isc_bind9)
02920 isc__mempool_setfillcount(mpctx, limit);
02921 else
02922 mpctx->methods->setfillcount(mpctx, limit);
02923 }
02924
02925 void *
02926 isc__mem_get(isc_mem_t *mctx, size_t size FLARG) {
02927 REQUIRE(ISCAPI_MCTX_VALID(mctx));
02928
02929 if (isc_bind9)
02930 return (isc___mem_get(mctx, size FLARG_PASS));
02931
02932 return (mctx->methods->memget(mctx, size FLARG_PASS));
02933
02934 }
02935
02936 void
02937 isc__mem_put(isc_mem_t *mctx, void *ptr, size_t size FLARG) {
02938 REQUIRE(ISCAPI_MCTX_VALID(mctx));
02939
02940 if (isc_bind9)
02941 isc___mem_put(mctx, ptr, size FLARG_PASS);
02942 else
02943 mctx->methods->memput(mctx, ptr, size FLARG_PASS);
02944 }
02945
02946 void
02947 isc__mem_putanddetach(isc_mem_t **mctxp, void *ptr, size_t size FLARG) {
02948 REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
02949
02950 if (isc_bind9)
02951 isc___mem_putanddetach(mctxp, ptr, size FLARG_PASS);
02952 else
02953 (*mctxp)->methods->memputanddetach(mctxp, ptr, size FLARG_PASS);
02954
02955
02956
02957
02958
02959 }
02960
02961 void *
02962 isc__mem_allocate(isc_mem_t *mctx, size_t size FLARG) {
02963 REQUIRE(ISCAPI_MCTX_VALID(mctx));
02964
02965 if (isc_bind9)
02966 return (isc___mem_allocate(mctx, size FLARG_PASS));
02967
02968 return (mctx->methods->memallocate(mctx, size FLARG_PASS));
02969 }
02970
02971 void *
02972 isc__mem_reallocate(isc_mem_t *mctx, void *ptr, size_t size FLARG) {
02973 REQUIRE(ISCAPI_MCTX_VALID(mctx));
02974
02975 if (isc_bind9)
02976 return (isc___mem_reallocate(mctx, ptr, size FLARG_PASS));
02977
02978 return (mctx->methods->memreallocate(mctx, ptr, size FLARG_PASS));
02979 }
02980
02981 char *
02982 isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
02983 REQUIRE(ISCAPI_MCTX_VALID(mctx));
02984
02985 if (isc_bind9)
02986 return (isc___mem_strdup(mctx, s FLARG_PASS));
02987
02988 return (mctx->methods->memstrdup(mctx, s FLARG_PASS));
02989 }
02990
02991 void
02992 isc__mem_free(isc_mem_t *mctx, void *ptr FLARG) {
02993 REQUIRE(ISCAPI_MCTX_VALID(mctx));
02994
02995 if (isc_bind9)
02996 isc___mem_free(mctx, ptr FLARG_PASS);
02997 else
02998 mctx->methods->memfree(mctx, ptr FLARG_PASS);
02999 }
03000
03001 void *
03002 isc__mempool_get(isc_mempool_t *mpctx FLARG) {
03003 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
03004
03005 if (isc_bind9)
03006 return (isc___mempool_get(mpctx FLARG_PASS));
03007
03008 return (mpctx->methods->get(mpctx FLARG_PASS));
03009 }
03010
03011 void
03012 isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
03013 REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
03014
03015 if (isc_bind9)
03016 isc___mempool_put(mpctx, mem FLARG_PASS);
03017 else
03018 mpctx->methods->put(mpctx, mem FLARG_PASS);
03019 }