~andreserl/ubuntu/lucid/bind9/bind9-apport-533601

« back to all changes in this revision

Viewing changes to lib/isc/mem.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones, LaMont Jones, Internet Software Consortium, Inc, localization folks
  • Date: 2008-08-02 14:20:20 UTC
  • mfrom: (1.2.1 upstream) (6.1.24 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080802142020-l1hon9jy8lbbjxmg
[LaMont Jones]

* default to using resolvconf if it is installed
* fix sonames and dependencies.  Closes: #149259, #492418
* Do not build-depend libcap2-dev on non-linux.  Closes: #493392
* drop unused query-loc manpage.  Closes: #492564
* lwresd: Deliver /etc/bind directory.  Closes: #490027
* fix query-source comment in default install

[Internet Software Consortium, Inc]

* 9.5.0-P2.  Closes: #492949

[localization folks]

* l10n: Spanish debconf translation.  Closes: #492425 (Ignacio Mondino)
* l10n: Swedish debconf templates.  Closes: #491369 (Martin Ågren)
* l10n: Japanese debconf translations.  Closes: #492048 (Hideki Yamane
  (Debian-JP))
* l10n: Finnish translation.  Closes: #490630 (Esko Arajärvi)
* l10n: Italian debconf translations.  Closes: #492587 (Alessandro Vietta)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2004, 2005  Internet Systems Consortium, Inc. ("ISC")
 
2
 * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
3
3
 * Copyright (C) 1997-2003  Internet Software Consortium.
4
4
 *
5
 
 * Permission to use, copy, modify, and distribute this software for any
 
5
 * Permission to use, copy, modify, and/or distribute this software for any
6
6
 * purpose with or without fee is hereby granted, provided that the above
7
7
 * copyright notice and this permission notice appear in all copies.
8
8
 *
15
15
 * PERFORMANCE OF THIS SOFTWARE.
16
16
 */
17
17
 
18
 
/* $Id: mem.c,v 1.98.2.7.2.7 2005/03/17 03:58:32 marka Exp $ */
 
18
/* $Id: mem.c,v 1.137.16.4 2008/03/31 23:46:42 tbox Exp $ */
 
19
 
 
20
/*! \file */
19
21
 
20
22
#include <config.h>
21
23
 
28
30
#include <isc/magic.h>
29
31
#include <isc/mem.h>
30
32
#include <isc/msgs.h>
 
33
#include <isc/once.h>
31
34
#include <isc/ondestroy.h>
32
35
#include <isc/string.h>
33
 
 
34
36
#include <isc/mutex.h>
 
37
#include <isc/print.h>
35
38
#include <isc/util.h>
 
39
#include <isc/xml.h>
 
40
 
 
41
#define MCTXLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) LOCK(l)
 
42
#define MCTXUNLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) UNLOCK(l)
36
43
 
37
44
#ifndef ISC_MEM_DEBUGGING
38
45
#define ISC_MEM_DEBUGGING 0
40
47
LIBISC_EXTERNAL_DATA unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING;
41
48
 
42
49
/*
43
 
 * Define ISC_MEM_USE_INTERNAL_MALLOC=1 to use the internal malloc()
44
 
 * implementation in preference to the system one.  The internal malloc()
45
 
 * is very space-efficient, and quite fast on uniprocessor systems.  It
46
 
 * performs poorly on multiprocessor machines.
47
 
 */
48
 
#ifndef ISC_MEM_USE_INTERNAL_MALLOC
49
 
#define ISC_MEM_USE_INTERNAL_MALLOC 0
50
 
#endif
51
 
 
52
 
/*
53
50
 * Constants.
54
51
 */
55
52
 
56
53
#define DEF_MAX_SIZE            1100
57
54
#define DEF_MEM_TARGET          4096
58
 
#define ALIGNMENT_SIZE          8               /* must be a power of 2 */
59
 
#define NUM_BASIC_BLOCKS        64              /* must be > 1 */
 
55
#define ALIGNMENT_SIZE          8               /*%< must be a power of 2 */
 
56
#define NUM_BASIC_BLOCKS        64              /*%< must be > 1 */
60
57
#define TABLE_INCREMENT         1024
61
58
#define DEBUGLIST_COUNT         1024
62
59
 
87
84
};
88
85
 
89
86
typedef struct {
90
 
        /*
 
87
        /*!
91
88
         * This structure must be ALIGNMENT_SIZE bytes.
92
89
         */
93
90
        union {
94
91
                size_t          size;
 
92
                isc_mem_t       *ctx;
95
93
                char            bytes[ALIGNMENT_SIZE];
96
94
        } u;
97
95
} size_info;
99
97
struct stats {
100
98
        unsigned long           gets;
101
99
        unsigned long           totalgets;
102
 
#if ISC_MEM_USE_INTERNAL_MALLOC
103
100
        unsigned long           blocks;
104
101
        unsigned long           freefrags;
105
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
106
102
};
107
103
 
108
104
#define MEM_MAGIC               ISC_MAGIC('M', 'e', 'm', 'C')
112
108
typedef ISC_LIST(debuglink_t)   debuglist_t;
113
109
#endif
114
110
 
 
111
/* List of all active memory contexts. */
 
112
 
 
113
static ISC_LIST(isc_mem_t)      contexts;
 
114
static isc_once_t               once = ISC_ONCE_INIT;
 
115
static isc_mutex_t              lock;
 
116
 
 
117
/*%
 
118
 * Total size of lost memory due to a bug of external library.
 
119
 * Locked by the global lock.
 
120
 */
 
121
static isc_uint64_t             totallost;
 
122
 
115
123
struct isc_mem {
116
124
        unsigned int            magic;
117
125
        isc_ondestroy_t         ondestroy;
 
126
        unsigned int            flags;
118
127
        isc_mutex_t             lock;
119
128
        isc_memalloc_t          memalloc;
120
129
        isc_memfree_t           memfree;
123
132
        isc_boolean_t           checkfree;
124
133
        struct stats *          stats;
125
134
        unsigned int            references;
 
135
        char                    name[16];
 
136
        void *                  tag;
126
137
        size_t                  quota;
127
138
        size_t                  total;
128
139
        size_t                  inuse;
133
144
        isc_mem_water_t         water;
134
145
        void *                  water_arg;
135
146
        ISC_LIST(isc_mempool_t) pools;
 
147
        unsigned int            poolcnt;
136
148
 
137
 
#if ISC_MEM_USE_INTERNAL_MALLOC
 
149
        /*  ISC_MEMFLAG_INTERNAL */
138
150
        size_t                  mem_target;
139
151
        element **              freelists;
140
152
        element *               basic_blocks;
143
155
        unsigned int            basic_table_size;
144
156
        unsigned char *         lowest;
145
157
        unsigned char *         highest;
146
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
147
158
 
148
159
#if ISC_MEM_TRACKLINES
149
160
        debuglist_t *           debuglist;
 
161
        unsigned int            debuglistcnt;
150
162
#endif
151
163
 
152
164
        unsigned int            memalloc_failures;
 
165
        ISC_LINK(isc_mem_t)     link;
153
166
};
154
167
 
155
168
#define MEMPOOL_MAGIC           ISC_MAGIC('M', 'E', 'M', 'p')
157
170
 
158
171
struct isc_mempool {
159
172
        /* always unlocked */
160
 
        unsigned int    magic;          /* magic number */
161
 
        isc_mutex_t    *lock;           /* optional lock */
162
 
        isc_mem_t      *mctx;           /* our memory context */
163
 
        /* locked via the memory context's lock */
164
 
        ISC_LINK(isc_mempool_t) link;   /* next pool in this mem context */
165
 
        /* optionally locked from here down */
166
 
        element        *items;          /* low water item list */
167
 
        size_t          size;           /* size of each item on this pool */
168
 
        unsigned int    maxalloc;       /* max number of items allowed */
169
 
        unsigned int    allocated;      /* # of items currently given out */
170
 
        unsigned int    freecount;      /* # of items on reserved list */
171
 
        unsigned int    freemax;        /* # of items allowed on free list */
172
 
        unsigned int    fillcount;      /* # of items to fetch on each fill */
173
 
        /* Stats only. */
174
 
        unsigned int    gets;           /* # of requests to this pool */
175
 
        /* Debugging only. */
 
173
        unsigned int    magic;          /*%< magic number */
 
174
        isc_mutex_t    *lock;           /*%< optional lock */
 
175
        isc_mem_t      *mctx;           /*%< our memory context */
 
176
        /*%< locked via the memory context's lock */
 
177
        ISC_LINK(isc_mempool_t) link;   /*%< next pool in this mem context */
 
178
        /*%< optionally locked from here down */
 
179
        element        *items;          /*%< low water item list */
 
180
        size_t          size;           /*%< size of each item on this pool */
 
181
        unsigned int    maxalloc;       /*%< max number of items allowed */
 
182
        unsigned int    allocated;      /*%< # of items currently given out */
 
183
        unsigned int    freecount;      /*%< # of items on reserved list */
 
184
        unsigned int    freemax;        /*%< # of items allowed on free list */
 
185
        unsigned int    fillcount;      /*%< # of items to fetch on each fill */
 
186
        /*%< Stats only. */
 
187
        unsigned int    gets;           /*%< # of requests to this pool */
 
188
        /*%< Debugging only. */
176
189
#if ISC_MEMPOOL_NAMES
177
 
        char            name[16];       /* printed name in stats reports */
 
190
        char            name[16];       /*%< printed name in stats reports */
178
191
#endif
179
192
};
180
193
 
191
204
                if ((isc_mem_debugging & (ISC_MEM_DEBUGTRACE | \
192
205
                                          ISC_MEM_DEBUGRECORD)) != 0 && \
193
206
                     b != NULL) \
194
 
                         add_trace_entry(a, b, c, d, e); \
 
207
                         add_trace_entry(a, b, c, d, e); \
195
208
        } while (0)
196
209
#define DELETE_TRACE(a, b, c, d, e)     delete_trace_entry(a, b, c, d, e)
197
210
 
198
211
static void
199
212
print_active(isc_mem_t *ctx, FILE *out);
200
213
 
201
 
/*
 
214
/*!
202
215
 * mctx must be locked.
203
216
 */
204
217
static inline void
257
270
        dl->count = 1;
258
271
 
259
272
        ISC_LIST_PREPEND(mctx->debuglist[size], dl, link);
 
273
        mctx->debuglistcnt++;
260
274
}
261
275
 
262
276
static inline void
309
323
}
310
324
#endif /* ISC_MEM_TRACKLINES */
311
325
 
312
 
#if ISC_MEM_USE_INTERNAL_MALLOC
313
326
static inline size_t
314
327
rmsize(size_t size) {
315
328
        /*
316
 
         * round down to ALIGNMENT_SIZE
 
329
         * round down to ALIGNMENT_SIZE
317
330
         */
318
331
        return (size & (~(ALIGNMENT_SIZE - 1)));
319
332
}
320
333
 
321
334
static inline size_t
322
335
quantize(size_t size) {
323
 
        /*
 
336
        /*!
324
337
         * Round up the result in order to get a size big
325
338
         * enough to satisfy the request and be aligned on ALIGNMENT_SIZE
326
339
         * byte boundaries.
327
340
         */
328
341
 
329
 
        if (size == 0)
 
342
        if (size == 0U)
330
343
                return (ALIGNMENT_SIZE);
331
344
        return ((size + ALIGNMENT_SIZE - 1) & (~(ALIGNMENT_SIZE - 1)));
332
345
}
347
360
         * Did we hit the quota for this context?
348
361
         */
349
362
        increment = NUM_BASIC_BLOCKS * ctx->mem_target;
350
 
        if (ctx->quota != 0 && ctx->total + increment > ctx->quota)
 
363
        if (ctx->quota != 0U && ctx->total + increment > ctx->quota)
351
364
                return (ISC_FALSE);
352
365
 
353
366
        INSIST(ctx->basic_table_count <= ctx->basic_table_size);
408
421
        void *new;
409
422
        unsigned char *curr, *next;
410
423
 
411
 
        /*
 
424
        /*!
412
425
         * Try to get more fragments by chopping up a basic block.
413
426
         */
414
427
 
448
461
         * Add the remaining fragment of the basic block to a free list.
449
462
         */
450
463
        total_size = rmsize(total_size);
451
 
        if (total_size > 0) {
 
464
        if (total_size > 0U) {
452
465
                ((element *)next)->next = ctx->freelists[total_size];
453
466
                ctx->freelists[total_size] = (element *)next;
454
467
                ctx->stats[total_size].freefrags++;
472
485
                /*
473
486
                 * memget() was called on something beyond our upper limit.
474
487
                 */
475
 
                if (ctx->quota != 0 && ctx->total + size > ctx->quota) {
 
488
                if (ctx->quota != 0U && ctx->total + size > ctx->quota) {
476
489
                        ret = NULL;
477
490
                        goto done;
478
491
                }
556
569
                memset(mem, 0xde, size); /* Mnemonic for "dead". */
557
570
#endif
558
571
                (ctx->memfree)(ctx->arg, mem);
559
 
                INSIST(ctx->stats[ctx->max_size].gets != 0);
 
572
                INSIST(ctx->stats[ctx->max_size].gets != 0U);
560
573
                ctx->stats[ctx->max_size].gets--;
561
574
                INSIST(size <= ctx->total);
562
575
                ctx->inuse -= size;
583
596
         * max. size (max_size) ends up getting recorded as a call to
584
597
         * max_size.
585
598
         */
586
 
        INSIST(ctx->stats[size].gets != 0);
 
599
        INSIST(ctx->stats[size].gets != 0U);
587
600
        ctx->stats[size].gets--;
588
601
        ctx->stats[new_size].freefrags++;
589
602
        ctx->inuse -= new_size;
590
603
}
591
604
 
592
 
#else /* ISC_MEM_USE_INTERNAL_MALLOC */
593
 
 
594
 
/*
 
605
/*!
595
606
 * Perform a malloc, doing memory filling and overrun detection as necessary.
596
607
 */
597
608
static inline void *
604
615
 
605
616
        ret = (ctx->memalloc)(ctx->arg, size);
606
617
        if (ret == NULL)
607
 
                ctx->memalloc_failures++;       
 
618
                ctx->memalloc_failures++;
608
619
 
609
620
#if ISC_MEM_FILL
610
621
        if (ret != NULL)
619
630
        return (ret);
620
631
}
621
632
 
622
 
/*
 
633
/*!
623
634
 * Perform a free, doing memory filling and overrun detection as necessary.
624
635
 */
625
636
static inline void
635
646
        (ctx->memfree)(ctx->arg, mem);
636
647
}
637
648
 
638
 
/*
 
649
/*!
639
650
 * Update internal counters after a memory get.
640
651
 */
641
652
static inline void
652
663
        }
653
664
}
654
665
 
655
 
/*
 
666
/*!
656
667
 * Update internal counters after a memory put.
657
668
 */
658
669
static inline void
671
682
        }
672
683
}
673
684
 
674
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
675
 
 
676
685
/*
677
686
 * Private.
678
687
 */
691
700
        free(ptr);
692
701
}
693
702
 
 
703
static void
 
704
initialize_action(void) {
 
705
        RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
 
706
        ISC_LIST_INIT(contexts);
 
707
        totallost = 0;
 
708
}
 
709
 
694
710
/*
695
711
 * Public.
696
712
 */
700
716
                isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
701
717
                isc_mem_t **ctxp)
702
718
{
 
719
        return (isc_mem_createx2(init_max_size, target_size, memalloc, memfree,
 
720
                                 arg, ctxp, ISC_MEMFLAG_DEFAULT));
 
721
 
 
722
}
 
723
 
 
724
isc_result_t
 
725
isc_mem_createx2(size_t init_max_size, size_t target_size,
 
726
                 isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
 
727
                 isc_mem_t **ctxp, unsigned int flags)
 
728
{
703
729
        isc_mem_t *ctx;
704
730
        isc_result_t result;
705
731
 
709
735
 
710
736
        INSIST((ALIGNMENT_SIZE & (ALIGNMENT_SIZE - 1)) == 0);
711
737
 
712
 
#if !ISC_MEM_USE_INTERNAL_MALLOC
713
 
        UNUSED(target_size);
714
 
#endif
 
738
        RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
715
739
 
716
740
        ctx = (memalloc)(arg, sizeof(*ctx));
717
741
        if (ctx == NULL)
718
742
                return (ISC_R_NOMEMORY);
719
743
 
720
 
        if (isc_mutex_init(&ctx->lock) != ISC_R_SUCCESS) {
721
 
                UNEXPECTED_ERROR(__FILE__, __LINE__,
722
 
                                 "isc_mutex_init() %s",
723
 
                                 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
724
 
                                                ISC_MSG_FAILED, "failed"));
725
 
                (memfree)(arg, ctx);
726
 
                return (ISC_R_UNEXPECTED);
 
744
        if ((flags & ISC_MEMFLAG_NOLOCK) == 0) {
 
745
                result = isc_mutex_init(&ctx->lock);
 
746
                if (result != ISC_R_SUCCESS) {
 
747
                        (memfree)(arg, ctx);
 
748
                        return (result);
 
749
                }
727
750
        }
728
751
 
729
752
        if (init_max_size == 0U)
730
753
                ctx->max_size = DEF_MAX_SIZE;
731
754
        else
732
755
                ctx->max_size = init_max_size;
 
756
        ctx->flags = flags;
733
757
        ctx->references = 1;
 
758
        memset(ctx->name, 0, sizeof(ctx->name));
 
759
        ctx->tag = NULL;
734
760
        ctx->quota = 0;
735
761
        ctx->total = 0;
736
762
        ctx->inuse = 0;
749
775
        ctx->checkfree = ISC_TRUE;
750
776
#if ISC_MEM_TRACKLINES
751
777
        ctx->debuglist = NULL;
 
778
        ctx->debuglistcnt = 0;
752
779
#endif
753
780
        ISC_LIST_INIT(ctx->pools);
754
 
 
755
 
#if ISC_MEM_USE_INTERNAL_MALLOC
 
781
        ctx->poolcnt = 0;
756
782
        ctx->freelists = NULL;
757
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
758
 
 
759
 
        ctx->stats = (memalloc)(arg,
760
 
                                (ctx->max_size+1) * sizeof(struct stats));
761
 
        if (ctx->stats == NULL) {
762
 
                result = ISC_R_NOMEMORY;
763
 
                goto error;
764
 
        }
765
 
        memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof(struct stats));
766
 
 
767
 
#if ISC_MEM_USE_INTERNAL_MALLOC
768
 
        if (target_size == 0)
769
 
                ctx->mem_target = DEF_MEM_TARGET;
770
 
        else
771
 
                ctx->mem_target = target_size;
772
 
        ctx->freelists = (memalloc)(arg, ctx->max_size * sizeof(element *));
773
 
        if (ctx->freelists == NULL) {
774
 
                result = ISC_R_NOMEMORY;
775
 
                goto error;
776
 
        }
777
 
        memset(ctx->freelists, 0,
778
 
               ctx->max_size * sizeof(element *));
779
783
        ctx->basic_blocks = NULL;
780
784
        ctx->basic_table = NULL;
781
785
        ctx->basic_table_count = 0;
782
786
        ctx->basic_table_size = 0;
783
787
        ctx->lowest = NULL;
784
788
        ctx->highest = NULL;
785
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
 
789
 
 
790
        ctx->stats = (memalloc)(arg,
 
791
                                (ctx->max_size+1) * sizeof(struct stats));
 
792
        if (ctx->stats == NULL) {
 
793
                result = ISC_R_NOMEMORY;
 
794
                goto error;
 
795
        }
 
796
        memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof(struct stats));
 
797
 
 
798
        if ((flags & ISC_MEMFLAG_INTERNAL) != 0) {
 
799
                if (target_size == 0U)
 
800
                        ctx->mem_target = DEF_MEM_TARGET;
 
801
                else
 
802
                        ctx->mem_target = target_size;
 
803
                ctx->freelists = (memalloc)(arg, ctx->max_size *
 
804
                                                 sizeof(element *));
 
805
                if (ctx->freelists == NULL) {
 
806
                        result = ISC_R_NOMEMORY;
 
807
                        goto error;
 
808
                }
 
809
                memset(ctx->freelists, 0,
 
810
                       ctx->max_size * sizeof(element *));
 
811
        }
786
812
 
787
813
#if ISC_MEM_TRACKLINES
788
814
        if ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0) {
801
827
 
802
828
        ctx->memalloc_failures = 0;
803
829
 
 
830
        LOCK(&lock);
 
831
        ISC_LIST_INITANDAPPEND(contexts, ctx, link);
 
832
        UNLOCK(&lock);
 
833
 
804
834
        *ctxp = ctx;
805
835
        return (ISC_R_SUCCESS);
806
836
 
808
838
        if (ctx != NULL) {
809
839
                if (ctx->stats != NULL)
810
840
                        (memfree)(arg, ctx->stats);
811
 
#if ISC_MEM_USE_INTERNAL_MALLOC
812
841
                if (ctx->freelists != NULL)
813
842
                        (memfree)(arg, ctx->freelists);
814
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
815
843
#if ISC_MEM_TRACKLINES
816
844
                if (ctx->debuglist != NULL)
817
845
                        (ctx->memfree)(ctx->arg, ctx->debuglist);
818
846
#endif /* ISC_MEM_TRACKLINES */
819
 
                DESTROYLOCK(&ctx->lock);
 
847
                if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
 
848
                        DESTROYLOCK(&ctx->lock);
820
849
                (memfree)(arg, ctx);
821
850
        }
822
851
 
827
856
isc_mem_create(size_t init_max_size, size_t target_size,
828
857
               isc_mem_t **ctxp)
829
858
{
830
 
        return (isc_mem_createx(init_max_size, target_size,
831
 
                                default_memalloc, default_memfree, NULL,
832
 
                                ctxp));
 
859
        return (isc_mem_createx2(init_max_size, target_size,
 
860
                                 default_memalloc, default_memfree, NULL,
 
861
                                 ctxp, ISC_MEMFLAG_DEFAULT));
 
862
}
 
863
 
 
864
isc_result_t
 
865
isc_mem_create2(size_t init_max_size, size_t target_size,
 
866
                isc_mem_t **ctxp, unsigned int flags)
 
867
{
 
868
        return (isc_mem_createx2(init_max_size, target_size,
 
869
                                 default_memalloc, default_memfree, NULL,
 
870
                                 ctxp, flags));
833
871
}
834
872
 
835
873
static void
839
877
 
840
878
        ctx->magic = 0;
841
879
 
842
 
#if ISC_MEM_USE_INTERNAL_MALLOC
 
880
        LOCK(&lock);
 
881
        ISC_LIST_UNLINK(contexts, ctx, link);
 
882
        totallost += ctx->inuse;
 
883
        UNLOCK(&lock);
 
884
 
843
885
        INSIST(ISC_LIST_EMPTY(ctx->pools));
844
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
845
886
 
846
887
#if ISC_MEM_TRACKLINES
847
888
        if (ctx->debuglist != NULL) {
859
900
                                     dl != NULL;
860
901
                                     dl = ISC_LIST_HEAD(ctx->debuglist[i])) {
861
902
                                        ISC_LIST_UNLINK(ctx->debuglist[i],
862
 
                                                        dl, link);
 
903
                                                        dl, link);
863
904
                                        free(dl);
864
905
                                }
865
906
                }
880
921
 
881
922
        (ctx->memfree)(ctx->arg, ctx->stats);
882
923
 
883
 
#if ISC_MEM_USE_INTERNAL_MALLOC
884
 
        for (i = 0; i < ctx->basic_table_count; i++)
885
 
                (ctx->memfree)(ctx->arg, ctx->basic_table[i]);
886
 
        (ctx->memfree)(ctx->arg, ctx->freelists);
887
 
        (ctx->memfree)(ctx->arg, ctx->basic_table);
888
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
 
924
        if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
 
925
                for (i = 0; i < ctx->basic_table_count; i++)
 
926
                        (ctx->memfree)(ctx->arg, ctx->basic_table[i]);
 
927
                (ctx->memfree)(ctx->arg, ctx->freelists);
 
928
                if (ctx->basic_table != NULL)
 
929
                        (ctx->memfree)(ctx->arg, ctx->basic_table);
 
930
        }
889
931
 
890
932
        ondest = ctx->ondestroy;
891
933
 
892
 
        DESTROYLOCK(&ctx->lock);
 
934
        if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
 
935
                DESTROYLOCK(&ctx->lock);
893
936
        (ctx->memfree)(ctx->arg, ctx);
894
937
 
895
938
        isc_ondestroy_notify(&ondest, ctx);
900
943
        REQUIRE(VALID_CONTEXT(source));
901
944
        REQUIRE(targetp != NULL && *targetp == NULL);
902
945
 
903
 
        LOCK(&source->lock);
 
946
        MCTXLOCK(source, &source->lock);
904
947
        source->references++;
905
 
        UNLOCK(&source->lock);
 
948
        MCTXUNLOCK(source, &source->lock);
906
949
 
907
950
        *targetp = source;
908
951
}
916
959
        ctx = *ctxp;
917
960
        REQUIRE(VALID_CONTEXT(ctx));
918
961
 
919
 
        LOCK(&ctx->lock);
 
962
        MCTXLOCK(ctx, &ctx->lock);
920
963
        INSIST(ctx->references > 0);
921
964
        ctx->references--;
922
965
        if (ctx->references == 0)
923
966
                want_destroy = ISC_TRUE;
924
 
        UNLOCK(&ctx->lock);
 
967
        MCTXUNLOCK(ctx, &ctx->lock);
925
968
 
926
969
        if (want_destroy)
927
970
                destroy(ctx);
943
986
isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
944
987
        isc_mem_t *ctx;
945
988
        isc_boolean_t want_destroy = ISC_FALSE;
 
989
        size_info *si;
 
990
        size_t oldsize;
946
991
 
947
992
        REQUIRE(ctxp != NULL);
948
993
        ctx = *ctxp;
955
1000
         */
956
1001
        *ctxp = NULL;
957
1002
 
958
 
#if ISC_MEM_USE_INTERNAL_MALLOC
959
 
        LOCK(&ctx->lock);
960
 
        mem_putunlocked(ctx, ptr, size);
961
 
#else /* ISC_MEM_USE_INTERNAL_MALLOC */
962
 
        mem_put(ctx, ptr, size);
963
 
        LOCK(&ctx->lock);
964
 
        mem_putstats(ctx, ptr, size);
965
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
 
1003
        if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) {
 
1004
                if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {
 
1005
                        si = &(((size_info *)ptr)[-1]);
 
1006
                        oldsize = si->u.size - ALIGNMENT_SIZE;
 
1007
                        if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
 
1008
                                oldsize -= ALIGNMENT_SIZE;
 
1009
                        INSIST(oldsize == size);
 
1010
                }
 
1011
                isc__mem_free(ctx, ptr FLARG_PASS);
 
1012
 
 
1013
                MCTXLOCK(ctx, &ctx->lock);
 
1014
                ctx->references--;
 
1015
                if (ctx->references == 0)
 
1016
                        want_destroy = ISC_TRUE;
 
1017
                MCTXUNLOCK(ctx, &ctx->lock);
 
1018
                if (want_destroy)
 
1019
                        destroy(ctx);
 
1020
 
 
1021
                return;
 
1022
        }
 
1023
 
 
1024
        if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
 
1025
                MCTXLOCK(ctx, &ctx->lock);
 
1026
                mem_putunlocked(ctx, ptr, size);
 
1027
        } else {
 
1028
                mem_put(ctx, ptr, size);
 
1029
                MCTXLOCK(ctx, &ctx->lock);
 
1030
                mem_putstats(ctx, ptr, size);
 
1031
        }
966
1032
 
967
1033
        DELETE_TRACE(ctx, ptr, size, file, line);
968
1034
        INSIST(ctx->references > 0);
970
1036
        if (ctx->references == 0)
971
1037
                want_destroy = ISC_TRUE;
972
1038
 
973
 
        UNLOCK(&ctx->lock);
 
1039
        MCTXUNLOCK(ctx, &ctx->lock);
974
1040
 
975
1041
        if (want_destroy)
976
1042
                destroy(ctx);
989
1055
        ctx = *ctxp;
990
1056
        REQUIRE(VALID_CONTEXT(ctx));
991
1057
 
992
 
        LOCK(&ctx->lock);
 
1058
        MCTXLOCK(ctx, &ctx->lock);
993
1059
#if ISC_MEM_TRACKLINES
994
1060
        if (ctx->references != 1)
995
1061
                print_active(ctx, stderr);
996
1062
#endif
997
1063
        REQUIRE(ctx->references == 1);
998
1064
        ctx->references--;
999
 
        UNLOCK(&ctx->lock);
 
1065
        MCTXUNLOCK(ctx, &ctx->lock);
1000
1066
 
1001
1067
        destroy(ctx);
1002
1068
 
1007
1073
isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) {
1008
1074
        isc_result_t res;
1009
1075
 
1010
 
        LOCK(&ctx->lock);
 
1076
        MCTXLOCK(ctx, &ctx->lock);
1011
1077
        res = isc_ondestroy_register(&ctx->ondestroy, task, event);
1012
 
        UNLOCK(&ctx->lock);
 
1078
        MCTXUNLOCK(ctx, &ctx->lock);
1013
1079
 
1014
1080
        return (res);
1015
1081
}
1022
1088
 
1023
1089
        REQUIRE(VALID_CONTEXT(ctx));
1024
1090
 
1025
 
#if ISC_MEM_USE_INTERNAL_MALLOC
1026
 
        LOCK(&ctx->lock);
1027
 
        ptr = mem_getunlocked(ctx, size);
1028
 
#else /* ISC_MEM_USE_INTERNAL_MALLOC */
1029
 
        ptr = mem_get(ctx, size);
1030
 
        LOCK(&ctx->lock);
1031
 
        if (ptr != NULL)
1032
 
                mem_getstats(ctx, size);
1033
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
 
1091
        if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0)
 
1092
                return (isc__mem_allocate(ctx, size FLARG_PASS));
 
1093
 
 
1094
        if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
 
1095
                MCTXLOCK(ctx, &ctx->lock);
 
1096
                ptr = mem_getunlocked(ctx, size);
 
1097
        } else {
 
1098
                ptr = mem_get(ctx, size);
 
1099
                MCTXLOCK(ctx, &ctx->lock);
 
1100
                if (ptr != NULL)
 
1101
                        mem_getstats(ctx, size);
 
1102
        }
1034
1103
 
1035
1104
        ADD_TRACE(ctx, ptr, size, file, line);
1036
1105
        if (ctx->hi_water != 0U && !ctx->hi_called &&
1037
1106
            ctx->inuse > ctx->hi_water) {
1038
 
                ctx->hi_called = ISC_TRUE;
1039
1107
                call_water = ISC_TRUE;
1040
1108
        }
1041
1109
        if (ctx->inuse > ctx->maxinuse) {
1045
1113
                        fprintf(stderr, "maxinuse = %lu\n",
1046
1114
                                (unsigned long)ctx->inuse);
1047
1115
        }
1048
 
        UNLOCK(&ctx->lock);
 
1116
        MCTXUNLOCK(ctx, &ctx->lock);
1049
1117
 
1050
1118
        if (call_water)
1051
1119
                (ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
1057
1125
isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
1058
1126
{
1059
1127
        isc_boolean_t call_water = ISC_FALSE;
 
1128
        size_info *si;
 
1129
        size_t oldsize;
1060
1130
 
1061
1131
        REQUIRE(VALID_CONTEXT(ctx));
1062
1132
        REQUIRE(ptr != NULL);
1063
1133
 
1064
 
#if ISC_MEM_USE_INTERNAL_MALLOC
1065
 
        LOCK(&ctx->lock);
1066
 
        mem_putunlocked(ctx, ptr, size);
1067
 
#else /* ISC_MEM_USE_INTERNAL_MALLOC */
1068
 
        mem_put(ctx, ptr, size);
1069
 
        LOCK(&ctx->lock);
1070
 
        mem_putstats(ctx, ptr, size);
1071
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
 
1134
        if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) {
 
1135
                if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {
 
1136
                        si = &(((size_info *)ptr)[-1]);
 
1137
                        oldsize = si->u.size - ALIGNMENT_SIZE;
 
1138
                        if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
 
1139
                                oldsize -= ALIGNMENT_SIZE;
 
1140
                        INSIST(oldsize == size);
 
1141
                }
 
1142
                isc__mem_free(ctx, ptr FLARG_PASS);
 
1143
                return;
 
1144
        }
 
1145
 
 
1146
        if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
 
1147
                MCTXLOCK(ctx, &ctx->lock);
 
1148
                mem_putunlocked(ctx, ptr, size);
 
1149
        } else {
 
1150
                mem_put(ctx, ptr, size);
 
1151
                MCTXLOCK(ctx, &ctx->lock);
 
1152
                mem_putstats(ctx, ptr, size);
 
1153
        }
1072
1154
 
1073
1155
        DELETE_TRACE(ctx, ptr, size, file, line);
1074
1156
 
1077
1159
         * when the context was pushed over hi_water but then had
1078
1160
         * isc_mem_setwater() called with 0 for hi_water and lo_water.
1079
1161
         */
1080
 
        if (ctx->hi_called && 
 
1162
        if (ctx->hi_called &&
1081
1163
            (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
1082
 
                ctx->hi_called = ISC_FALSE;
1083
 
 
1084
1164
                if (ctx->water != NULL)
1085
1165
                        call_water = ISC_TRUE;
1086
1166
        }
1087
 
        UNLOCK(&ctx->lock);
 
1167
        MCTXUNLOCK(ctx, &ctx->lock);
1088
1168
 
1089
1169
        if (call_water)
1090
1170
                (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
1091
1171
}
1092
1172
 
 
1173
void
 
1174
isc_mem_waterack(isc_mem_t *ctx, int flag) {
 
1175
        REQUIRE(VALID_CONTEXT(ctx));
 
1176
 
 
1177
        MCTXLOCK(ctx, &ctx->lock);
 
1178
        if (flag == ISC_MEM_LOWATER)
 
1179
                ctx->hi_called = ISC_FALSE;
 
1180
        else if (flag == ISC_MEM_HIWATER)
 
1181
                ctx->hi_called = ISC_TRUE;
 
1182
        MCTXUNLOCK(ctx, &ctx->lock);
 
1183
}
 
1184
 
1093
1185
#if ISC_MEM_TRACKLINES
1094
1186
static void
1095
1187
print_active(isc_mem_t *mctx, FILE *out) {
1105
1197
                                            "memory allocations:\n"));
1106
1198
                found = ISC_FALSE;
1107
1199
                format = isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
1108
 
                                        ISC_MSG_PTRFILELINE,
 
1200
                                        ISC_MSG_PTRFILELINE,
1109
1201
                                        "\tptr %p size %u file %s line %u\n");
1110
1202
                for (i = 0; i <= mctx->max_size; i++) {
1111
1203
                        dl = ISC_LIST_HEAD(mctx->debuglist[i]);
1112
 
                        
 
1204
 
1113
1205
                        if (dl != NULL)
1114
1206
                                found = ISC_TRUE;
1115
1207
 
1141
1233
        const isc_mempool_t *pool;
1142
1234
 
1143
1235
        REQUIRE(VALID_CONTEXT(ctx));
1144
 
        LOCK(&ctx->lock);
 
1236
        MCTXLOCK(ctx, &ctx->lock);
1145
1237
 
1146
1238
        for (i = 0; i <= ctx->max_size; i++) {
1147
1239
                s = &ctx->stats[i];
1151
1243
                fprintf(out, "%s%5lu: %11lu gets, %11lu rem",
1152
1244
                        (i == ctx->max_size) ? ">=" : "  ",
1153
1245
                        (unsigned long) i, s->totalgets, s->gets);
1154
 
#if ISC_MEM_USE_INTERNAL_MALLOC
1155
 
                if (s->blocks != 0 || s->freefrags != 0)
 
1246
                if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0 &&
 
1247
                    (s->blocks != 0U || s->freefrags != 0U))
1156
1248
                        fprintf(out, " (%lu bl, %lu ff)",
1157
1249
                                s->blocks, s->freefrags);
1158
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
1159
1250
                fputc('\n', out);
1160
1251
        }
1161
1252
 
1203
1294
        print_active(ctx, out);
1204
1295
#endif
1205
1296
 
1206
 
        UNLOCK(&ctx->lock);
 
1297
        MCTXUNLOCK(ctx, &ctx->lock);
1207
1298
}
1208
1299
 
1209
1300
/*
1216
1307
        size_info *si;
1217
1308
 
1218
1309
        size += ALIGNMENT_SIZE;
1219
 
#if ISC_MEM_USE_INTERNAL_MALLOC
1220
 
        si = mem_getunlocked(ctx, size);
1221
 
#else /* ISC_MEM_USE_INTERNAL_MALLOC */
1222
 
        si = mem_get(ctx, size);
1223
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
 
1310
        if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
 
1311
                size += ALIGNMENT_SIZE;
 
1312
 
 
1313
        if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0)
 
1314
                si = mem_getunlocked(ctx, size);
 
1315
        else
 
1316
                si = mem_get(ctx, size);
 
1317
 
1224
1318
        if (si == NULL)
1225
1319
                return (NULL);
 
1320
        if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) {
 
1321
                si->u.ctx = ctx;
 
1322
                si++;
 
1323
        }
1226
1324
        si->u.size = size;
1227
1325
        return (&si[1]);
1228
1326
}
1230
1328
void *
1231
1329
isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
1232
1330
        size_info *si;
 
1331
        isc_boolean_t call_water = ISC_FALSE;
1233
1332
 
1234
1333
        REQUIRE(VALID_CONTEXT(ctx));
1235
1334
 
1236
 
#if ISC_MEM_USE_INTERNAL_MALLOC
1237
 
        LOCK(&ctx->lock);
1238
 
        si = isc__mem_allocateunlocked(ctx, size);
1239
 
#else /* ISC_MEM_USE_INTERNAL_MALLOC */
1240
 
        si = isc__mem_allocateunlocked(ctx, size);
1241
 
        LOCK(&ctx->lock);
1242
 
        if (si != NULL)
1243
 
                mem_getstats(ctx, si[-1].u.size);
1244
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
 
1335
        if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
 
1336
                MCTXLOCK(ctx, &ctx->lock);
 
1337
                si = isc__mem_allocateunlocked(ctx, size);
 
1338
        } else {
 
1339
                si = isc__mem_allocateunlocked(ctx, size);
 
1340
                MCTXLOCK(ctx, &ctx->lock);
 
1341
                if (si != NULL)
 
1342
                        mem_getstats(ctx, si[-1].u.size);
 
1343
        }
1245
1344
 
1246
1345
#if ISC_MEM_TRACKLINES
1247
1346
        ADD_TRACE(ctx, si, si[-1].u.size, file, line);
1248
1347
#endif
 
1348
        if (ctx->hi_water != 0U && !ctx->hi_called &&
 
1349
            ctx->inuse > ctx->hi_water) {
 
1350
                ctx->hi_called = ISC_TRUE;
 
1351
                call_water = ISC_TRUE;
 
1352
        }
 
1353
        if (ctx->inuse > ctx->maxinuse) {
 
1354
                ctx->maxinuse = ctx->inuse;
 
1355
                if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
 
1356
                    (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0)
 
1357
                        fprintf(stderr, "maxinuse = %lu\n",
 
1358
                                (unsigned long)ctx->inuse);
 
1359
        }
 
1360
        MCTXUNLOCK(ctx, &ctx->lock);
1249
1361
 
1250
 
        UNLOCK(&ctx->lock);
 
1362
        if (call_water)
 
1363
                (ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
1251
1364
 
1252
1365
        return (si);
1253
1366
}
1256
1369
isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
1257
1370
        size_info *si;
1258
1371
        size_t size;
 
1372
        isc_boolean_t call_water= ISC_FALSE;
1259
1373
 
1260
1374
        REQUIRE(VALID_CONTEXT(ctx));
1261
1375
        REQUIRE(ptr != NULL);
1262
1376
 
1263
 
        si = &(((size_info *)ptr)[-1]);
1264
 
        size = si->u.size;
 
1377
        if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) {
 
1378
                si = &(((size_info *)ptr)[-2]);
 
1379
                REQUIRE(si->u.ctx == ctx);
 
1380
                size = si[1].u.size;
 
1381
        } else {
 
1382
                si = &(((size_info *)ptr)[-1]);
 
1383
                size = si->u.size;
 
1384
        }
1265
1385
 
1266
 
#if ISC_MEM_USE_INTERNAL_MALLOC
1267
 
        LOCK(&ctx->lock);
1268
 
        mem_putunlocked(ctx, si, size);
1269
 
#else /* ISC_MEM_USE_INTERNAL_MALLOC */
1270
 
        mem_put(ctx, si, size);
1271
 
        LOCK(&ctx->lock);
1272
 
        mem_putstats(ctx, si, size);
1273
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
 
1386
        if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
 
1387
                MCTXLOCK(ctx, &ctx->lock);
 
1388
                mem_putunlocked(ctx, si, size);
 
1389
        } else {
 
1390
                mem_put(ctx, si, size);
 
1391
                MCTXLOCK(ctx, &ctx->lock);
 
1392
                mem_putstats(ctx, si, size);
 
1393
        }
1274
1394
 
1275
1395
        DELETE_TRACE(ctx, ptr, size, file, line);
1276
1396
 
1277
 
        UNLOCK(&ctx->lock);
 
1397
        /*
 
1398
         * The check against ctx->lo_water == 0 is for the condition
 
1399
         * when the context was pushed over hi_water but then had
 
1400
         * isc_mem_setwater() called with 0 for hi_water and lo_water.
 
1401
         */
 
1402
        if (ctx->hi_called &&
 
1403
            (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
 
1404
                ctx->hi_called = ISC_FALSE;
 
1405
 
 
1406
                if (ctx->water != NULL)
 
1407
                        call_water = ISC_TRUE;
 
1408
        }
 
1409
        MCTXUNLOCK(ctx, &ctx->lock);
 
1410
 
 
1411
        if (call_water)
 
1412
                (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
1278
1413
}
1279
1414
 
1280
1415
 
1303
1438
void
1304
1439
isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
1305
1440
        REQUIRE(VALID_CONTEXT(ctx));
1306
 
        LOCK(&ctx->lock);
 
1441
        MCTXLOCK(ctx, &ctx->lock);
1307
1442
 
1308
1443
        ctx->checkfree = flag;
1309
1444
 
1310
 
        UNLOCK(&ctx->lock);
 
1445
        MCTXUNLOCK(ctx, &ctx->lock);
1311
1446
}
1312
1447
 
1313
1448
/*
1317
1452
void
1318
1453
isc_mem_setquota(isc_mem_t *ctx, size_t quota) {
1319
1454
        REQUIRE(VALID_CONTEXT(ctx));
1320
 
        LOCK(&ctx->lock);
 
1455
        MCTXLOCK(ctx, &ctx->lock);
1321
1456
 
1322
1457
        ctx->quota = quota;
1323
1458
 
1324
 
        UNLOCK(&ctx->lock);
 
1459
        MCTXUNLOCK(ctx, &ctx->lock);
1325
1460
}
1326
1461
 
1327
1462
size_t
1329
1464
        size_t quota;
1330
1465
 
1331
1466
        REQUIRE(VALID_CONTEXT(ctx));
1332
 
        LOCK(&ctx->lock);
 
1467
        MCTXLOCK(ctx, &ctx->lock);
1333
1468
 
1334
1469
        quota = ctx->quota;
1335
1470
 
1336
 
        UNLOCK(&ctx->lock);
 
1471
        MCTXUNLOCK(ctx, &ctx->lock);
1337
1472
 
1338
1473
        return (quota);
1339
1474
}
1343
1478
        size_t inuse;
1344
1479
 
1345
1480
        REQUIRE(VALID_CONTEXT(ctx));
1346
 
        LOCK(&ctx->lock);
 
1481
        MCTXLOCK(ctx, &ctx->lock);
1347
1482
 
1348
1483
        inuse = ctx->inuse;
1349
1484
 
1350
 
        UNLOCK(&ctx->lock);
 
1485
        MCTXUNLOCK(ctx, &ctx->lock);
1351
1486
 
1352
1487
        return (inuse);
1353
1488
}
1354
1489
 
1355
1490
void
1356
1491
isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
1357
 
                 size_t hiwater, size_t lowater)
 
1492
                 size_t hiwater, size_t lowater)
1358
1493
{
 
1494
        isc_boolean_t callwater = ISC_FALSE;
 
1495
        isc_mem_water_t oldwater;
 
1496
        void *oldwater_arg;
 
1497
 
1359
1498
        REQUIRE(VALID_CONTEXT(ctx));
1360
1499
        REQUIRE(hiwater >= lowater);
1361
1500
 
1362
 
        LOCK(&ctx->lock);
 
1501
        MCTXLOCK(ctx, &ctx->lock);
 
1502
        oldwater = ctx->water;
 
1503
        oldwater_arg = ctx->water_arg;
1363
1504
        if (water == NULL) {
 
1505
                callwater = ctx->hi_called;
1364
1506
                ctx->water = NULL;
1365
1507
                ctx->water_arg = NULL;
1366
1508
                ctx->hi_water = 0;
1367
1509
                ctx->lo_water = 0;
1368
1510
                ctx->hi_called = ISC_FALSE;
1369
1511
        } else {
 
1512
                if (ctx->hi_called &&
 
1513
                    (ctx->water != water || ctx->water_arg != water_arg ||
 
1514
                     ctx->inuse < lowater || lowater == 0U))
 
1515
                        callwater = ISC_TRUE;
1370
1516
                ctx->water = water;
1371
1517
                ctx->water_arg = water_arg;
1372
1518
                ctx->hi_water = hiwater;
1373
1519
                ctx->lo_water = lowater;
1374
1520
                ctx->hi_called = ISC_FALSE;
1375
1521
        }
 
1522
        MCTXUNLOCK(ctx, &ctx->lock);
 
1523
 
 
1524
        if (callwater && oldwater != NULL)
 
1525
                (oldwater)(oldwater_arg, ISC_MEM_LOWATER);
 
1526
}
 
1527
 
 
1528
void
 
1529
isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag) {
 
1530
        REQUIRE(VALID_CONTEXT(ctx));
 
1531
 
 
1532
        LOCK(&ctx->lock);
 
1533
        memset(ctx->name, 0, sizeof(ctx->name));
 
1534
        strncpy(ctx->name, name, sizeof(ctx->name) - 1);
 
1535
        ctx->tag = tag;
1376
1536
        UNLOCK(&ctx->lock);
1377
1537
}
1378
1538
 
 
1539
const char *
 
1540
isc_mem_getname(isc_mem_t *ctx) {
 
1541
        REQUIRE(VALID_CONTEXT(ctx));
 
1542
 
 
1543
        return (ctx->name);
 
1544
}
 
1545
 
 
1546
void *
 
1547
isc_mem_gettag(isc_mem_t *ctx) {
 
1548
        REQUIRE(VALID_CONTEXT(ctx));
 
1549
 
 
1550
        return (ctx->tag);
 
1551
}
 
1552
 
1379
1553
/*
1380
1554
 * Memory pool stuff
1381
1555
 */
1413
1587
 
1414
1588
        *mpctxp = mpctx;
1415
1589
 
1416
 
        LOCK(&mctx->lock);
 
1590
        MCTXLOCK(mctx, &mctx->lock);
1417
1591
        ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link);
1418
 
        UNLOCK(&mctx->lock);
 
1592
        mctx->poolcnt++;
 
1593
        MCTXUNLOCK(mctx, &mctx->lock);
1419
1594
 
1420
1595
        return (ISC_R_SUCCESS);
1421
1596
}
1468
1643
        /*
1469
1644
         * Return any items on the free list
1470
1645
         */
1471
 
        LOCK(&mctx->lock);
 
1646
        MCTXLOCK(mctx, &mctx->lock);
1472
1647
        while (mpctx->items != NULL) {
1473
1648
                INSIST(mpctx->freecount > 0);
1474
1649
                mpctx->freecount--;
1475
1650
                item = mpctx->items;
1476
1651
                mpctx->items = item->next;
1477
1652
 
1478
 
#if ISC_MEM_USE_INTERNAL_MALLOC
1479
 
                mem_putunlocked(mctx, item, mpctx->size);
1480
 
#else /* ISC_MEM_USE_INTERNAL_MALLOC */
1481
 
                mem_put(mctx, item, mpctx->size);
1482
 
                mem_putstats(mctx, item, mpctx->size);
1483
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
 
1653
                if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
 
1654
                        mem_putunlocked(mctx, item, mpctx->size);
 
1655
                } else {
 
1656
                        mem_put(mctx, item, mpctx->size);
 
1657
                        mem_putstats(mctx, item, mpctx->size);
 
1658
                }
1484
1659
        }
1485
 
        UNLOCK(&mctx->lock);
 
1660
        MCTXUNLOCK(mctx, &mctx->lock);
1486
1661
 
1487
1662
        /*
1488
1663
         * Remove our linked list entry from the memory context.
1489
1664
         */
1490
 
        LOCK(&mctx->lock);
 
1665
        MCTXLOCK(mctx, &mctx->lock);
1491
1666
        ISC_LIST_UNLINK(mctx->pools, mpctx, link);
1492
 
        UNLOCK(&mctx->lock);
 
1667
        mctx->poolcnt--;
 
1668
        MCTXUNLOCK(mctx, &mctx->lock);
1493
1669
 
1494
1670
        mpctx->magic = 0;
1495
1671
 
1548
1724
         * We need to dip into the well.  Lock the memory context here and
1549
1725
         * fill up our free list.
1550
1726
         */
1551
 
        LOCK(&mctx->lock);
 
1727
        MCTXLOCK(mctx, &mctx->lock);
1552
1728
        for (i = 0; i < mpctx->fillcount; i++) {
1553
 
#if ISC_MEM_USE_INTERNAL_MALLOC
1554
 
                item = mem_getunlocked(mctx, mpctx->size);
1555
 
#else /* ISC_MEM_USE_INTERNAL_MALLOC */
1556
 
                item = mem_get(mctx, mpctx->size);
1557
 
                if (item != NULL)
1558
 
                        mem_getstats(mctx, mpctx->size);
1559
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
 
1729
                if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
 
1730
                        item = mem_getunlocked(mctx, mpctx->size);
 
1731
                } else {
 
1732
                        item = mem_get(mctx, mpctx->size);
 
1733
                        if (item != NULL)
 
1734
                                mem_getstats(mctx, mpctx->size);
 
1735
                }
1560
1736
                if (item == NULL)
1561
1737
                        break;
1562
1738
                item->next = mpctx->items;
1563
1739
                mpctx->items = item;
1564
1740
                mpctx->freecount++;
1565
1741
        }
1566
 
        UNLOCK(&mctx->lock);
 
1742
        MCTXUNLOCK(mctx, &mctx->lock);
1567
1743
 
1568
1744
        /*
1569
1745
         * If we didn't get any items, return NULL.
1583
1759
 
1584
1760
#if ISC_MEM_TRACKLINES
1585
1761
        if (item != NULL) {
1586
 
                LOCK(&mctx->lock);
 
1762
                MCTXLOCK(mctx, &mctx->lock);
1587
1763
                ADD_TRACE(mctx, item, mpctx->size, file, line);
1588
 
                UNLOCK(&mctx->lock);
 
1764
                MCTXUNLOCK(mctx, &mctx->lock);
1589
1765
        }
1590
1766
#endif /* ISC_MEM_TRACKLINES */
1591
1767
 
1609
1785
        mpctx->allocated--;
1610
1786
 
1611
1787
#if ISC_MEM_TRACKLINES
1612
 
        LOCK(&mctx->lock);
 
1788
        MCTXLOCK(mctx, &mctx->lock);
1613
1789
        DELETE_TRACE(mctx, mem, mpctx->size, file, line);
1614
 
        UNLOCK(&mctx->lock);
 
1790
        MCTXUNLOCK(mctx, &mctx->lock);
1615
1791
#endif /* ISC_MEM_TRACKLINES */
1616
1792
 
1617
1793
        /*
1618
1794
         * If our free list is full, return this to the mctx directly.
1619
1795
         */
1620
1796
        if (mpctx->freecount >= mpctx->freemax) {
1621
 
#if ISC_MEM_USE_INTERNAL_MALLOC
1622
 
                LOCK(&mctx->lock);
1623
 
                mem_putunlocked(mctx, mem, mpctx->size);
1624
 
                UNLOCK(&mctx->lock);
1625
 
#else /* ISC_MEM_USE_INTERNAL_MALLOC */
1626
 
                mem_put(mctx, mem, mpctx->size);
1627
 
                LOCK(&mctx->lock);
1628
 
                mem_putstats(mctx, mem, mpctx->size);
1629
 
                UNLOCK(&mctx->lock);
1630
 
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
 
1797
                if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
 
1798
                        MCTXLOCK(mctx, &mctx->lock);
 
1799
                        mem_putunlocked(mctx, mem, mpctx->size);
 
1800
                        MCTXUNLOCK(mctx, &mctx->lock);
 
1801
                } else {
 
1802
                        mem_put(mctx, mem, mpctx->size);
 
1803
                        MCTXLOCK(mctx, &mctx->lock);
 
1804
                        mem_putstats(mctx, mem, mpctx->size);
 
1805
                        MCTXUNLOCK(mctx, &mctx->lock);
 
1806
                }
1631
1807
                if (mpctx->lock != NULL)
1632
1808
                        UNLOCK(mpctx->lock);
1633
1809
                return;
1775
1951
 
1776
1952
        return (fillcount);
1777
1953
}
 
1954
 
 
1955
void
 
1956
isc_mem_printactive(isc_mem_t *ctx, FILE *file) {
 
1957
 
 
1958
        REQUIRE(VALID_CONTEXT(ctx));
 
1959
        REQUIRE(file != NULL);
 
1960
 
 
1961
#if !ISC_MEM_TRACKLINES
 
1962
        UNUSED(ctx);
 
1963
        UNUSED(file);
 
1964
#else
 
1965
        print_active(ctx, file);
 
1966
#endif
 
1967
}
 
1968
 
 
1969
void
 
1970
isc_mem_printallactive(FILE *file) {
 
1971
#if !ISC_MEM_TRACKLINES
 
1972
        UNUSED(file);
 
1973
#else
 
1974
        isc_mem_t *ctx;
 
1975
 
 
1976
        RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
 
1977
 
 
1978
        LOCK(&lock);
 
1979
        for (ctx = ISC_LIST_HEAD(contexts);
 
1980
             ctx != NULL;
 
1981
             ctx = ISC_LIST_NEXT(ctx, link)) {
 
1982
                fprintf(file, "context: %p\n", ctx);
 
1983
                print_active(ctx, file);
 
1984
        }
 
1985
        UNLOCK(&lock);
 
1986
#endif
 
1987
}
 
1988
 
 
1989
void
 
1990
isc_mem_checkdestroyed(FILE *file) {
 
1991
 
 
1992
        RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
 
1993
 
 
1994
        LOCK(&lock);
 
1995
        if (!ISC_LIST_EMPTY(contexts))  {
 
1996
#if ISC_MEM_TRACKLINES
 
1997
                isc_mem_t *ctx;
 
1998
 
 
1999
                for (ctx = ISC_LIST_HEAD(contexts);
 
2000
                     ctx != NULL;
 
2001
                     ctx = ISC_LIST_NEXT(ctx, link)) {
 
2002
                        fprintf(file, "context: %p\n", ctx);
 
2003
                        print_active(ctx, file);
 
2004
                }
 
2005
                fflush(file);
 
2006
#endif
 
2007
                INSIST(0);
 
2008
        }
 
2009
        UNLOCK(&lock);
 
2010
}
 
2011
 
 
2012
#ifdef HAVE_LIBXML2
 
2013
 
 
2014
typedef struct summarystat {
 
2015
        isc_uint64_t    total;
 
2016
        isc_uint64_t    inuse;
 
2017
        isc_uint64_t    blocksize;
 
2018
        isc_uint64_t    contextsize;
 
2019
} summarystat_t;
 
2020
 
 
2021
static void
 
2022
renderctx(isc_mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) {
 
2023
        REQUIRE(VALID_CONTEXT(ctx));
 
2024
 
 
2025
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "context");
 
2026
 
 
2027
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "id");
 
2028
        xmlTextWriterWriteFormatString(writer, "%p", ctx);
 
2029
        xmlTextWriterEndElement(writer); /* id */
 
2030
 
 
2031
        if (ctx->name[0] != 0) {
 
2032
                xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
 
2033
                xmlTextWriterWriteFormatString(writer, "%s", ctx->name);
 
2034
                xmlTextWriterEndElement(writer); /* name */
 
2035
        }
 
2036
 
 
2037
        REQUIRE(VALID_CONTEXT(ctx));
 
2038
        MCTXLOCK(ctx, &ctx->lock);
 
2039
 
 
2040
        summary->contextsize += sizeof(*ctx) +
 
2041
                (ctx->max_size + 1) * sizeof(struct stats) +
 
2042
                ctx->max_size * sizeof(element *) +
 
2043
                ctx->basic_table_count * sizeof(char *);
 
2044
#if ISC_MEM_TRACKLINES
 
2045
        if (ctx->debuglist != NULL) {
 
2046
                summary->contextsize +=
 
2047
                        (ctx->max_size + 1) * sizeof(debuglist_t) +
 
2048
                        ctx->debuglistcnt * sizeof(debuglink_t);
 
2049
        }
 
2050
#endif
 
2051
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
 
2052
        xmlTextWriterWriteFormatString(writer, "%d", ctx->references);
 
2053
        xmlTextWriterEndElement(writer); /* references */
 
2054
 
 
2055
        summary->total += ctx->total;
 
2056
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "total");
 
2057
        xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
 
2058
                                       (isc_uint64_t)ctx->total);
 
2059
        xmlTextWriterEndElement(writer); /* total */
 
2060
 
 
2061
        summary->inuse += ctx->inuse;
 
2062
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "inuse");
 
2063
        xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
 
2064
                                       (isc_uint64_t)ctx->inuse);
 
2065
        xmlTextWriterEndElement(writer); /* inuse */
 
2066
 
 
2067
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "maxinuse");
 
2068
        xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
 
2069
                                       (isc_uint64_t)ctx->maxinuse);
 
2070
        xmlTextWriterEndElement(writer); /* maxinuse */
 
2071
 
 
2072
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "blocksize");
 
2073
        if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
 
2074
                summary->blocksize += ctx->basic_table_count *
 
2075
                        NUM_BASIC_BLOCKS * ctx->mem_target;
 
2076
                xmlTextWriterWriteFormatString(writer,
 
2077
                                               "%" ISC_PRINT_QUADFORMAT "u",
 
2078
                                               (isc_uint64_t)
 
2079
                                               ctx->basic_table_count *
 
2080
                                               NUM_BASIC_BLOCKS *
 
2081
                                               ctx->mem_target);
 
2082
        } else
 
2083
                xmlTextWriterWriteFormatString(writer, "%s", "-");
 
2084
        xmlTextWriterEndElement(writer); /* blocksize */
 
2085
 
 
2086
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "pools");
 
2087
        xmlTextWriterWriteFormatString(writer, "%u", ctx->poolcnt);
 
2088
        xmlTextWriterEndElement(writer); /* pools */
 
2089
        summary->contextsize += ctx->poolcnt * sizeof(isc_mempool_t);
 
2090
 
 
2091
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "hiwater");
 
2092
        xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
 
2093
                                       (isc_uint64_t)ctx->hi_water);
 
2094
        xmlTextWriterEndElement(writer); /* hiwater */
 
2095
 
 
2096
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "lowater");
 
2097
        xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
 
2098
                                       (isc_uint64_t)ctx->lo_water);
 
2099
        xmlTextWriterEndElement(writer); /* lowater */
 
2100
 
 
2101
        MCTXUNLOCK(ctx, &ctx->lock);
 
2102
 
 
2103
        xmlTextWriterEndElement(writer); /* context */
 
2104
}
 
2105
 
 
2106
void
 
2107
isc_mem_renderxml(xmlTextWriterPtr writer) {
 
2108
        isc_mem_t *ctx;
 
2109
        summarystat_t summary;
 
2110
        isc_uint64_t lost;
 
2111
 
 
2112
        memset(&summary, 0, sizeof(summary));
 
2113
 
 
2114
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "contexts");
 
2115
 
 
2116
        RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
 
2117
 
 
2118
        LOCK(&lock);
 
2119
        lost = totallost;
 
2120
        for (ctx = ISC_LIST_HEAD(contexts);
 
2121
             ctx != NULL;
 
2122
             ctx = ISC_LIST_NEXT(ctx, link)) {
 
2123
                renderctx(ctx, &summary, writer);
 
2124
        }
 
2125
        UNLOCK(&lock);
 
2126
 
 
2127
        xmlTextWriterEndElement(writer); /* contexts */
 
2128
 
 
2129
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "summary");
 
2130
 
 
2131
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "TotalUse");
 
2132
        xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
 
2133
                                       summary.total);
 
2134
        xmlTextWriterEndElement(writer); /* TotalUse */
 
2135
 
 
2136
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "InUse");
 
2137
        xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
 
2138
                                       summary.inuse);
 
2139
        xmlTextWriterEndElement(writer); /* InUse */
 
2140
 
 
2141
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "BlockSize");
 
2142
        xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
 
2143
                                       summary.blocksize);
 
2144
        xmlTextWriterEndElement(writer); /* BlockSize */
 
2145
 
 
2146
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "ContextSize");
 
2147
        xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
 
2148
                                       summary.contextsize);
 
2149
        xmlTextWriterEndElement(writer); /* ContextSize */
 
2150
 
 
2151
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "Lost");
 
2152
        xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
 
2153
                                       lost);
 
2154
        xmlTextWriterEndElement(writer); /* Lost */
 
2155
 
 
2156
        xmlTextWriterEndElement(writer); /* summary */
 
2157
}
 
2158
 
 
2159
#endif /* HAVE_LIBXML2 */