2 Samba Unix SMB/CIFS implementation.
4 Samba trivial allocation library - new interface
6 NOTE: Please read talloc_guide.txt for full documentation
8 Copyright (C) Andrew Tridgell 2004
9 Copyright (C) Stefan Metzmacher 2006
11 ** NOTE! The following LGPL license applies to the talloc
12 ** library. This does NOT imply that all of Samba is released
15 This library is free software; you can redistribute it and/or
16 modify it under the terms of the GNU Lesser General Public
17 License as published by the Free Software Foundation; either
18 version 3 of the License, or (at your option) any later version.
20 This library is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Lesser General Public License for more details.
25 You should have received a copy of the GNU Lesser General Public
26 License along with this library; if not, see <http://www.gnu.org/licenses/>.
30 inspired by http://swapped.cc/halloc/
36 #ifdef TALLOC_BUILD_VERSION_MAJOR
37 #if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR)
38 #error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR"
42 #ifdef TALLOC_BUILD_VERSION_MINOR
43 #if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR)
44 #error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR"
48 /* Special macros that are no-ops except when run under Valgrind on
49 * x86. They've moved a little bit from valgrind 1.0.4 to 1.9.4 */
50 #ifdef HAVE_VALGRIND_MEMCHECK_H
51 /* memcheck.h includes valgrind.h */
52 #include <valgrind/memcheck.h>
53 #elif defined(HAVE_VALGRIND_H)
57 /* use this to force every realloc to change the pointer, to stress test
58 code that might not cope */
59 #define ALWAYS_REALLOC 0
62 #define MAX_TALLOC_SIZE 0x10000000
63 #define TALLOC_MAGIC_BASE 0xe814ec70
64 #define TALLOC_MAGIC ( \
66 (TALLOC_VERSION_MAJOR << 12) + \
67 (TALLOC_VERSION_MINOR << 4) \
70 #define TALLOC_FLAG_FREE 0x01
71 #define TALLOC_FLAG_LOOP 0x02
72 #define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */
73 #define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */
75 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
77 /* by default we abort when given a bad pointer (such as when talloc_free() is called
78 on a pointer that came from malloc() */
80 #define TALLOC_ABORT(reason) abort()
83 #ifndef discard_const_p
84 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
85 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
87 # define discard_const_p(type, ptr) ((type *)(ptr))
91 /* these macros gain us a few percent of speed on gcc */
93 /* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
94 as its first argument */
96 #define likely(x) __builtin_expect(!!(x), 1)
99 #define unlikely(x) __builtin_expect(!!(x), 0)
103 #define likely(x) (x)
106 #define unlikely(x) (x)
110 /* this null_context is only used if talloc_enable_leak_report() or
111 talloc_enable_leak_report_full() is called, otherwise it remains
114 static void *null_context
;
115 static void *autofree_context
;
117 /* used to enable fill of memory on free, which can be useful for
118 * catching use after free errors when valgrind is too slow
126 #define TALLOC_FILL_ENV "TALLOC_FREE_FILL"
129 * do not wipe the header, to allow the
130 * double-free logic to still work
132 #define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \
133 if (unlikely(talloc_fill.enabled)) { \
134 size_t _flen = (_tc)->size; \
135 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
136 memset(_fptr, talloc_fill.fill_value, _flen); \
140 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
141 /* Mark the whole chunk as not accessable */
142 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \
143 size_t _flen = TC_HDR_SIZE + (_tc)->size; \
144 char *_fptr = (char *)(_tc); \
145 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
148 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0)
151 #define TC_INVALIDATE_FULL_CHUNK(_tc) do { \
152 TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \
153 TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \
156 #define TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
157 if (unlikely(talloc_fill.enabled)) { \
158 size_t _flen = (_tc)->size - (_new_size); \
159 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
160 _fptr += (_new_size); \
161 memset(_fptr, talloc_fill.fill_value, _flen); \
165 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
166 /* Mark the unused bytes not accessable */
167 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
168 size_t _flen = (_tc)->size - (_new_size); \
169 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
170 _fptr += (_new_size); \
171 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
174 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
177 #define TC_INVALIDATE_SHRINK_CHUNK(_tc, _new_size) do { \
178 TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size); \
179 TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
182 #define TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
183 if (unlikely(talloc_fill.enabled)) { \
184 size_t _flen = (_tc)->size - (_new_size); \
185 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
186 _fptr += (_new_size); \
187 memset(_fptr, talloc_fill.fill_value, _flen); \
191 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
192 /* Mark the unused bytes as undefined */
193 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
194 size_t _flen = (_tc)->size - (_new_size); \
195 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
196 _fptr += (_new_size); \
197 VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
200 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
203 #define TC_UNDEFINE_SHRINK_CHUNK(_tc, _new_size) do { \
204 TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size); \
205 TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
208 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
209 /* Mark the new bytes as undefined */
210 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { \
211 size_t _old_used = TC_HDR_SIZE + (_tc)->size; \
212 size_t _new_used = TC_HDR_SIZE + (_new_size); \
213 size_t _flen = _new_used - _old_used; \
214 char *_fptr = _old_used + (char *)(_tc); \
215 VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
218 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
221 #define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \
222 TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \
225 struct talloc_reference_handle
{
226 struct talloc_reference_handle
*next
, *prev
;
228 const char *location
;
231 struct talloc_memlimit
{
232 struct talloc_chunk
*parent
;
233 struct talloc_memlimit
*upper
;
238 static bool talloc_memlimit_check(struct talloc_memlimit
*limit
, size_t size
);
239 static void talloc_memlimit_grow(struct talloc_memlimit
*limit
,
241 static void talloc_memlimit_shrink(struct talloc_memlimit
*limit
,
243 static void talloc_memlimit_update_on_free(struct talloc_chunk
*tc
);
245 typedef int (*talloc_destructor_t
)(void *);
247 struct talloc_pool_hdr
;
249 struct talloc_chunk
{
250 struct talloc_chunk
*next
, *prev
;
251 struct talloc_chunk
*parent
, *child
;
252 struct talloc_reference_handle
*refs
;
253 talloc_destructor_t destructor
;
260 * if 'limit' is set it means all *new* children of the context will
261 * be limited to a total aggregate size ox max_size for memory
263 * cur_size is used to keep track of the current use
265 struct talloc_memlimit
*limit
;
268 * For members of a pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
269 * is a pointer to the struct talloc_chunk of the pool that it was
270 * allocated from. This way children can quickly find the pool to chew
273 struct talloc_pool_hdr
*pool
;
276 /* 16 byte alignment seems to keep everyone happy */
277 #define TC_ALIGN16(s) (((s)+15)&~15)
278 #define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
279 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
281 _PUBLIC_
int talloc_version_major(void)
283 return TALLOC_VERSION_MAJOR
;
286 _PUBLIC_
int talloc_version_minor(void)
288 return TALLOC_VERSION_MINOR
;
291 static void (*talloc_log_fn
)(const char *message
);
293 _PUBLIC_
void talloc_set_log_fn(void (*log_fn
)(const char *message
))
295 talloc_log_fn
= log_fn
;
298 static void talloc_log(const char *fmt
, ...) PRINTF_ATTRIBUTE(1,2);
299 static void talloc_log(const char *fmt
, ...)
304 if (!talloc_log_fn
) {
309 message
= talloc_vasprintf(NULL
, fmt
, ap
);
312 talloc_log_fn(message
);
313 talloc_free(message
);
316 static void talloc_log_stderr(const char *message
)
318 fprintf(stderr
, "%s", message
);
321 _PUBLIC_
void talloc_set_log_stderr(void)
323 talloc_set_log_fn(talloc_log_stderr
);
326 static void (*talloc_abort_fn
)(const char *reason
);
328 _PUBLIC_
void talloc_set_abort_fn(void (*abort_fn
)(const char *reason
))
330 talloc_abort_fn
= abort_fn
;
333 static void talloc_abort(const char *reason
)
335 talloc_log("%s\n", reason
);
337 if (!talloc_abort_fn
) {
338 TALLOC_ABORT(reason
);
341 talloc_abort_fn(reason
);
344 static void talloc_abort_magic(unsigned magic
)
346 unsigned striped
= magic
- TALLOC_MAGIC_BASE
;
347 unsigned major
= (striped
& 0xFFFFF000) >> 12;
348 unsigned minor
= (striped
& 0x00000FF0) >> 4;
349 talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
351 TALLOC_MAGIC
, TALLOC_VERSION_MAJOR
, TALLOC_VERSION_MINOR
);
352 talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
355 static void talloc_abort_access_after_free(void)
357 talloc_abort("Bad talloc magic value - access after free");
360 static void talloc_abort_unknown_value(void)
362 talloc_abort("Bad talloc magic value - unknown value");
365 /* panic if we get a bad magic value */
366 static inline struct talloc_chunk
*talloc_chunk_from_ptr(const void *ptr
)
368 const char *pp
= (const char *)ptr
;
369 struct talloc_chunk
*tc
= discard_const_p(struct talloc_chunk
, pp
- TC_HDR_SIZE
);
370 if (unlikely((tc
->flags
& (TALLOC_FLAG_FREE
| ~0xF)) != TALLOC_MAGIC
)) {
371 if ((tc
->flags
& (~0xFFF)) == TALLOC_MAGIC_BASE
) {
372 talloc_abort_magic(tc
->flags
& (~0xF));
376 if (tc
->flags
& TALLOC_FLAG_FREE
) {
377 talloc_log("talloc: access after free error - first free may be at %s\n", tc
->name
);
378 talloc_abort_access_after_free();
381 talloc_abort_unknown_value();
388 /* hook into the front of the list */
389 #define _TLIST_ADD(list, p) \
393 (p)->next = (p)->prev = NULL; \
395 (list)->prev = (p); \
396 (p)->next = (list); \
402 /* remove an element from a list - element doesn't have to be in list. */
403 #define _TLIST_REMOVE(list, p) \
405 if ((p) == (list)) { \
406 (list) = (p)->next; \
407 if (list) (list)->prev = NULL; \
409 if ((p)->prev) (p)->prev->next = (p)->next; \
410 if ((p)->next) (p)->next->prev = (p)->prev; \
412 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
417 return the parent chunk of a pointer
419 static inline struct talloc_chunk
*talloc_parent_chunk(const void *ptr
)
421 struct talloc_chunk
*tc
;
423 if (unlikely(ptr
== NULL
)) {
427 tc
= talloc_chunk_from_ptr(ptr
);
428 while (tc
->prev
) tc
=tc
->prev
;
433 _PUBLIC_
void *talloc_parent(const void *ptr
)
435 struct talloc_chunk
*tc
= talloc_parent_chunk(ptr
);
436 return tc
? TC_PTR_FROM_CHUNK(tc
) : NULL
;
442 _PUBLIC_
const char *talloc_parent_name(const void *ptr
)
444 struct talloc_chunk
*tc
= talloc_parent_chunk(ptr
);
445 return tc
? tc
->name
: NULL
;
449 A pool carries an in-pool object count count in the first 16 bytes.
450 bytes. This is done to support talloc_steal() to a parent outside of the
451 pool. The count includes the pool itself, so a talloc_free() on a pool will
452 only destroy the pool if the count has dropped to zero. A talloc_free() of a
453 pool member will reduce the count, and eventually also call free(3) on the
456 The object count is not put into "struct talloc_chunk" because it is only
457 relevant for talloc pools and the alignment to 16 bytes would increase the
458 memory footprint of each talloc chunk by those 16 bytes.
461 struct talloc_pool_hdr
{
463 unsigned int object_count
;
467 #define TP_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_pool_hdr))
469 static struct talloc_pool_hdr
*talloc_pool_from_chunk(struct talloc_chunk
*c
)
471 return (struct talloc_pool_hdr
*)((char *)c
- TP_HDR_SIZE
);
474 static struct talloc_chunk
*talloc_chunk_from_pool(struct talloc_pool_hdr
*h
)
476 return (struct talloc_chunk
*)((char *)h
+ TP_HDR_SIZE
);
479 static void *tc_pool_end(struct talloc_pool_hdr
*pool_hdr
)
481 struct talloc_chunk
*tc
= talloc_chunk_from_pool(pool_hdr
);
482 return (char *)tc
+ TC_HDR_SIZE
+ pool_hdr
->poolsize
;
485 static size_t tc_pool_space_left(struct talloc_pool_hdr
*pool_hdr
)
487 return (char *)tc_pool_end(pool_hdr
) - (char *)pool_hdr
->end
;
490 /* If tc is inside a pool, this gives the next neighbour. */
491 static void *tc_next_chunk(struct talloc_chunk
*tc
)
493 return (char *)tc
+ TC_ALIGN16(TC_HDR_SIZE
+ tc
->size
);
496 static void *tc_pool_first_chunk(struct talloc_pool_hdr
*pool_hdr
)
498 struct talloc_chunk
*tc
= talloc_chunk_from_pool(pool_hdr
);
499 return tc_next_chunk(tc
);
502 /* Mark the whole remaining pool as not accessable */
503 static void tc_invalidate_pool(struct talloc_pool_hdr
*pool_hdr
)
505 size_t flen
= tc_pool_space_left(pool_hdr
);
507 if (unlikely(talloc_fill
.enabled
)) {
508 memset(pool_hdr
->end
, talloc_fill
.fill_value
, flen
);
511 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
512 VALGRIND_MAKE_MEM_NOACCESS(pool_hdr
->end
, flen
);
520 static struct talloc_chunk
*talloc_alloc_pool(struct talloc_chunk
*parent
,
521 size_t size
, size_t prefix_len
)
523 struct talloc_pool_hdr
*pool_hdr
= NULL
;
525 struct talloc_chunk
*result
;
528 if (parent
== NULL
) {
532 if (parent
->flags
& TALLOC_FLAG_POOL
) {
533 pool_hdr
= talloc_pool_from_chunk(parent
);
535 else if (parent
->flags
& TALLOC_FLAG_POOLMEM
) {
536 pool_hdr
= parent
->pool
;
539 if (pool_hdr
== NULL
) {
543 space_left
= tc_pool_space_left(pool_hdr
);
546 * Align size to 16 bytes
548 chunk_size
= TC_ALIGN16(size
+ prefix_len
);
550 if (space_left
< chunk_size
) {
554 result
= (struct talloc_chunk
*)((char *)pool_hdr
->end
+ prefix_len
);
556 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
557 VALGRIND_MAKE_MEM_UNDEFINED(pool_hdr
->end
, chunk_size
);
560 pool_hdr
->end
= (void *)((char *)pool_hdr
->end
+ chunk_size
);
562 result
->flags
= TALLOC_MAGIC
| TALLOC_FLAG_POOLMEM
;
563 result
->pool
= pool_hdr
;
565 pool_hdr
->object_count
++;
571 Allocate a bit of memory as a child of an existing pointer
573 static inline void *__talloc_with_prefix(const void *context
, size_t size
,
576 struct talloc_chunk
*tc
= NULL
;
577 struct talloc_memlimit
*limit
= NULL
;
578 size_t total_len
= TC_HDR_SIZE
+ size
+ prefix_len
;
580 if (unlikely(context
== NULL
)) {
581 context
= null_context
;
584 if (unlikely(size
>= MAX_TALLOC_SIZE
)) {
588 if (unlikely(total_len
< TC_HDR_SIZE
)) {
592 if (context
!= NULL
) {
593 struct talloc_chunk
*ptc
= talloc_chunk_from_ptr(context
);
595 if (ptc
->limit
!= NULL
) {
599 tc
= talloc_alloc_pool(ptc
, TC_HDR_SIZE
+size
, prefix_len
);
606 * Only do the memlimit check/update on actual allocation.
608 if (!talloc_memlimit_check(limit
, total_len
)) {
613 ptr
= malloc(total_len
);
614 if (unlikely(ptr
== NULL
)) {
617 tc
= (struct talloc_chunk
*)(ptr
+ prefix_len
);
618 tc
->flags
= TALLOC_MAGIC
;
621 talloc_memlimit_grow(limit
, total_len
);
626 tc
->destructor
= NULL
;
631 if (likely(context
)) {
632 struct talloc_chunk
*parent
= talloc_chunk_from_ptr(context
);
635 parent
->child
->parent
= NULL
;
636 tc
->next
= parent
->child
;
645 tc
->next
= tc
->prev
= tc
->parent
= NULL
;
648 return TC_PTR_FROM_CHUNK(tc
);
651 static inline void *__talloc(const void *context
, size_t size
)
653 return __talloc_with_prefix(context
, size
, 0);
657 * Create a talloc pool
660 _PUBLIC_
void *talloc_pool(const void *context
, size_t size
)
662 struct talloc_chunk
*tc
;
663 struct talloc_pool_hdr
*pool_hdr
;
666 result
= __talloc_with_prefix(context
, size
, TP_HDR_SIZE
);
668 if (unlikely(result
== NULL
)) {
672 tc
= talloc_chunk_from_ptr(result
);
673 pool_hdr
= talloc_pool_from_chunk(tc
);
675 tc
->flags
|= TALLOC_FLAG_POOL
;
678 pool_hdr
->object_count
= 1;
679 pool_hdr
->end
= result
;
680 pool_hdr
->poolsize
= size
;
682 tc_invalidate_pool(pool_hdr
);
688 * Create a talloc pool correctly sized for a basic size plus
689 * a number of subobjects whose total size is given. Essentially
690 * a custom allocator for talloc to reduce fragmentation.
693 _PUBLIC_
void *_talloc_pooled_object(const void *ctx
,
695 const char *type_name
,
696 unsigned num_subobjects
,
697 size_t total_subobjects_size
)
699 size_t poolsize
, subobjects_slack
, tmp
;
700 struct talloc_chunk
*tc
;
701 struct talloc_pool_hdr
*pool_hdr
;
704 poolsize
= type_size
+ total_subobjects_size
;
706 if ((poolsize
< type_size
) || (poolsize
< total_subobjects_size
)) {
710 if (num_subobjects
== UINT_MAX
) {
713 num_subobjects
+= 1; /* the object body itself */
716 * Alignment can increase the pool size by at most 15 bytes per object
717 * plus alignment for the object itself
719 subobjects_slack
= (TC_HDR_SIZE
+ TP_HDR_SIZE
+ 15) * num_subobjects
;
720 if (subobjects_slack
< num_subobjects
) {
724 tmp
= poolsize
+ subobjects_slack
;
725 if ((tmp
< poolsize
) || (tmp
< subobjects_slack
)) {
730 ret
= talloc_pool(ctx
, poolsize
);
735 tc
= talloc_chunk_from_ptr(ret
);
736 tc
->size
= type_size
;
738 pool_hdr
= talloc_pool_from_chunk(tc
);
740 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
741 VALGRIND_MAKE_MEM_UNDEFINED(pool_hdr
->end
, type_size
);
744 pool_hdr
->end
= ((char *)pool_hdr
->end
+ TC_ALIGN16(type_size
));
746 talloc_set_name_const(ret
, type_name
);
754 setup a destructor to be called on free of a pointer
755 the destructor should return 0 on success, or -1 on failure.
756 if the destructor fails then the free is failed, and the memory can
757 be continued to be used
759 _PUBLIC_
void _talloc_set_destructor(const void *ptr
, int (*destructor
)(void *))
761 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
762 tc
->destructor
= destructor
;
766 increase the reference count on a piece of memory.
768 _PUBLIC_
int talloc_increase_ref_count(const void *ptr
)
770 if (unlikely(!talloc_reference(null_context
, ptr
))) {
777 helper for talloc_reference()
779 this is referenced by a function pointer and should not be inline
781 static int talloc_reference_destructor(struct talloc_reference_handle
*handle
)
783 struct talloc_chunk
*ptr_tc
= talloc_chunk_from_ptr(handle
->ptr
);
784 _TLIST_REMOVE(ptr_tc
->refs
, handle
);
789 more efficient way to add a name to a pointer - the name must point to a
792 static inline void _talloc_set_name_const(const void *ptr
, const char *name
)
794 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
799 internal talloc_named_const()
801 static inline void *_talloc_named_const(const void *context
, size_t size
, const char *name
)
805 ptr
= __talloc(context
, size
);
806 if (unlikely(ptr
== NULL
)) {
810 _talloc_set_name_const(ptr
, name
);
816 make a secondary reference to a pointer, hanging off the given context.
817 the pointer remains valid until both the original caller and this given
820 the major use for this is when two different structures need to reference the
821 same underlying data, and you want to be able to free the two instances separately,
824 _PUBLIC_
void *_talloc_reference_loc(const void *context
, const void *ptr
, const char *location
)
826 struct talloc_chunk
*tc
;
827 struct talloc_reference_handle
*handle
;
828 if (unlikely(ptr
== NULL
)) return NULL
;
830 tc
= talloc_chunk_from_ptr(ptr
);
831 handle
= (struct talloc_reference_handle
*)_talloc_named_const(context
,
832 sizeof(struct talloc_reference_handle
),
833 TALLOC_MAGIC_REFERENCE
);
834 if (unlikely(handle
== NULL
)) return NULL
;
836 /* note that we hang the destructor off the handle, not the
837 main context as that allows the caller to still setup their
838 own destructor on the context if they want to */
839 talloc_set_destructor(handle
, talloc_reference_destructor
);
840 handle
->ptr
= discard_const_p(void, ptr
);
841 handle
->location
= location
;
842 _TLIST_ADD(tc
->refs
, handle
);
846 static void *_talloc_steal_internal(const void *new_ctx
, const void *ptr
);
848 static inline void _talloc_free_poolmem(struct talloc_chunk
*tc
,
849 const char *location
)
851 struct talloc_pool_hdr
*pool
;
852 struct talloc_chunk
*pool_tc
;
856 pool_tc
= talloc_chunk_from_pool(pool
);
857 next_tc
= tc_next_chunk(tc
);
859 tc
->flags
|= TALLOC_FLAG_FREE
;
861 /* we mark the freed memory with where we called the free
862 * from. This means on a double free error we can report where
863 * the first free came from
867 TC_INVALIDATE_FULL_CHUNK(tc
);
869 if (unlikely(pool
->object_count
== 0)) {
870 talloc_abort("Pool object count zero!");
874 pool
->object_count
--;
876 if (unlikely(pool
->object_count
== 1
877 && !(pool_tc
->flags
& TALLOC_FLAG_FREE
))) {
879 * if there is just one object left in the pool
880 * and pool->flags does not have TALLOC_FLAG_FREE,
881 * it means this is the pool itself and
882 * the rest is available for new objects
885 pool
->end
= tc_pool_first_chunk(pool
);
886 tc_invalidate_pool(pool
);
890 if (unlikely(pool
->object_count
== 0)) {
892 * we mark the freed memory with where we called the free
893 * from. This means on a double free error we can report where
894 * the first free came from
896 pool_tc
->name
= location
;
898 if (pool_tc
->flags
& TALLOC_FLAG_POOLMEM
) {
899 _talloc_free_poolmem(pool_tc
, location
);
902 * The talloc_memlimit_update_on_free()
903 * call takes into account the
904 * prefix TP_HDR_SIZE allocated before
905 * the pool talloc_chunk.
907 talloc_memlimit_update_on_free(pool_tc
);
908 TC_INVALIDATE_FULL_CHUNK(pool_tc
);
914 if (pool
->end
== next_tc
) {
916 * if pool->pool still points to end of
917 * 'tc' (which is stored in the 'next_tc' variable),
918 * we can reclaim the memory of 'tc'.
925 * Do nothing. The memory is just "wasted", waiting for the pool
926 * itself to be freed.
930 static inline void _talloc_free_children_internal(struct talloc_chunk
*tc
,
932 const char *location
);
935 internal talloc_free call
937 static inline int _talloc_free_internal(void *ptr
, const char *location
)
939 struct talloc_chunk
*tc
;
942 if (unlikely(ptr
== NULL
)) {
946 /* possibly initialised the talloc fill value */
947 if (unlikely(!talloc_fill
.initialised
)) {
948 const char *fill
= getenv(TALLOC_FILL_ENV
);
950 talloc_fill
.enabled
= true;
951 talloc_fill
.fill_value
= strtoul(fill
, NULL
, 0);
953 talloc_fill
.initialised
= true;
956 tc
= talloc_chunk_from_ptr(ptr
);
958 if (unlikely(tc
->refs
)) {
960 /* check if this is a reference from a child or
961 * grandchild back to it's parent or grandparent
963 * in that case we need to remove the reference and
964 * call another instance of talloc_free() on the current
967 is_child
= talloc_is_parent(tc
->refs
, ptr
);
968 _talloc_free_internal(tc
->refs
, location
);
970 return _talloc_free_internal(ptr
, location
);
975 if (unlikely(tc
->flags
& TALLOC_FLAG_LOOP
)) {
976 /* we have a free loop - stop looping */
980 if (unlikely(tc
->destructor
)) {
981 talloc_destructor_t d
= tc
->destructor
;
982 if (d
== (talloc_destructor_t
)-1) {
985 tc
->destructor
= (talloc_destructor_t
)-1;
990 tc
->destructor
= NULL
;
994 _TLIST_REMOVE(tc
->parent
->child
, tc
);
995 if (tc
->parent
->child
) {
996 tc
->parent
->child
->parent
= tc
->parent
;
999 if (tc
->prev
) tc
->prev
->next
= tc
->next
;
1000 if (tc
->next
) tc
->next
->prev
= tc
->prev
;
1001 tc
->prev
= tc
->next
= NULL
;
1004 tc
->flags
|= TALLOC_FLAG_LOOP
;
1006 _talloc_free_children_internal(tc
, ptr
, location
);
1008 tc
->flags
|= TALLOC_FLAG_FREE
;
1010 /* we mark the freed memory with where we called the free
1011 * from. This means on a double free error we can report where
1012 * the first free came from
1014 tc
->name
= location
;
1016 if (tc
->flags
& TALLOC_FLAG_POOL
) {
1017 struct talloc_pool_hdr
*pool
;
1019 pool
= talloc_pool_from_chunk(tc
);
1021 if (unlikely(pool
->object_count
== 0)) {
1022 talloc_abort("Pool object count zero!");
1026 pool
->object_count
--;
1028 if (likely(pool
->object_count
!= 0)) {
1033 * With object_count==0, a pool becomes a normal piece of
1034 * memory to free. If it's allocated inside a pool, it needs
1035 * to be freed as poolmem, else it needs to be just freed.
1042 if (tc
->flags
& TALLOC_FLAG_POOLMEM
) {
1043 _talloc_free_poolmem(tc
, location
);
1047 talloc_memlimit_update_on_free(tc
);
1049 TC_INVALIDATE_FULL_CHUNK(tc
);
1054 static size_t _talloc_total_limit_size(const void *ptr
,
1055 struct talloc_memlimit
*old_limit
,
1056 struct talloc_memlimit
*new_limit
);
1059 move a lump of memory from one talloc context to another return the
1060 ptr on success, or NULL if it could not be transferred.
1061 passing NULL as ptr will always return NULL with no side effects.
1063 static void *_talloc_steal_internal(const void *new_ctx
, const void *ptr
)
1065 struct talloc_chunk
*tc
, *new_tc
;
1066 size_t ctx_size
= 0;
1068 if (unlikely(!ptr
)) {
1072 if (unlikely(new_ctx
== NULL
)) {
1073 new_ctx
= null_context
;
1076 tc
= talloc_chunk_from_ptr(ptr
);
1078 if (tc
->limit
!= NULL
) {
1080 ctx_size
= _talloc_total_limit_size(ptr
, NULL
, NULL
);
1082 /* Decrement the memory limit from the source .. */
1083 talloc_memlimit_shrink(tc
->limit
->upper
, ctx_size
);
1085 if (tc
->limit
->parent
== tc
) {
1086 tc
->limit
->upper
= NULL
;
1092 if (unlikely(new_ctx
== NULL
)) {
1094 _TLIST_REMOVE(tc
->parent
->child
, tc
);
1095 if (tc
->parent
->child
) {
1096 tc
->parent
->child
->parent
= tc
->parent
;
1099 if (tc
->prev
) tc
->prev
->next
= tc
->next
;
1100 if (tc
->next
) tc
->next
->prev
= tc
->prev
;
1103 tc
->parent
= tc
->next
= tc
->prev
= NULL
;
1104 return discard_const_p(void, ptr
);
1107 new_tc
= talloc_chunk_from_ptr(new_ctx
);
1109 if (unlikely(tc
== new_tc
|| tc
->parent
== new_tc
)) {
1110 return discard_const_p(void, ptr
);
1114 _TLIST_REMOVE(tc
->parent
->child
, tc
);
1115 if (tc
->parent
->child
) {
1116 tc
->parent
->child
->parent
= tc
->parent
;
1119 if (tc
->prev
) tc
->prev
->next
= tc
->next
;
1120 if (tc
->next
) tc
->next
->prev
= tc
->prev
;
1121 tc
->prev
= tc
->next
= NULL
;
1124 tc
->parent
= new_tc
;
1125 if (new_tc
->child
) new_tc
->child
->parent
= NULL
;
1126 _TLIST_ADD(new_tc
->child
, tc
);
1128 if (tc
->limit
|| new_tc
->limit
) {
1129 ctx_size
= _talloc_total_limit_size(ptr
, tc
->limit
,
1131 /* .. and increment it in the destination. */
1132 if (new_tc
->limit
) {
1133 talloc_memlimit_grow(new_tc
->limit
, ctx_size
);
1137 return discard_const_p(void, ptr
);
1141 move a lump of memory from one talloc context to another return the
1142 ptr on success, or NULL if it could not be transferred.
1143 passing NULL as ptr will always return NULL with no side effects.
1145 _PUBLIC_
void *_talloc_steal_loc(const void *new_ctx
, const void *ptr
, const char *location
)
1147 struct talloc_chunk
*tc
;
1149 if (unlikely(ptr
== NULL
)) {
1153 tc
= talloc_chunk_from_ptr(ptr
);
1155 if (unlikely(tc
->refs
!= NULL
) && talloc_parent(ptr
) != new_ctx
) {
1156 struct talloc_reference_handle
*h
;
1158 talloc_log("WARNING: talloc_steal with references at %s\n",
1161 for (h
=tc
->refs
; h
; h
=h
->next
) {
1162 talloc_log("\treference at %s\n",
1168 /* this test is probably too expensive to have on in the
1169 normal build, but it useful for debugging */
1170 if (talloc_is_parent(new_ctx
, ptr
)) {
1171 talloc_log("WARNING: stealing into talloc child at %s\n", location
);
1175 return _talloc_steal_internal(new_ctx
, ptr
);
1179 this is like a talloc_steal(), but you must supply the old
1180 parent. This resolves the ambiguity in a talloc_steal() which is
1181 called on a context that has more than one parent (via references)
1183 The old parent can be either a reference or a parent
1185 _PUBLIC_
void *talloc_reparent(const void *old_parent
, const void *new_parent
, const void *ptr
)
1187 struct talloc_chunk
*tc
;
1188 struct talloc_reference_handle
*h
;
1190 if (unlikely(ptr
== NULL
)) {
1194 if (old_parent
== talloc_parent(ptr
)) {
1195 return _talloc_steal_internal(new_parent
, ptr
);
1198 tc
= talloc_chunk_from_ptr(ptr
);
1199 for (h
=tc
->refs
;h
;h
=h
->next
) {
1200 if (talloc_parent(h
) == old_parent
) {
1201 if (_talloc_steal_internal(new_parent
, h
) != h
) {
1204 return discard_const_p(void, ptr
);
1208 /* it wasn't a parent */
1213 remove a secondary reference to a pointer. This undo's what
1214 talloc_reference() has done. The context and pointer arguments
1215 must match those given to a talloc_reference()
1217 static inline int talloc_unreference(const void *context
, const void *ptr
)
1219 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
1220 struct talloc_reference_handle
*h
;
1222 if (unlikely(context
== NULL
)) {
1223 context
= null_context
;
1226 for (h
=tc
->refs
;h
;h
=h
->next
) {
1227 struct talloc_chunk
*p
= talloc_parent_chunk(h
);
1229 if (context
== NULL
) break;
1230 } else if (TC_PTR_FROM_CHUNK(p
) == context
) {
1238 return _talloc_free_internal(h
, __location__
);
1242 remove a specific parent context from a pointer. This is a more
1243 controlled variant of talloc_free()
1245 _PUBLIC_
int talloc_unlink(const void *context
, void *ptr
)
1247 struct talloc_chunk
*tc_p
, *new_p
, *tc_c
;
1254 if (context
== NULL
) {
1255 context
= null_context
;
1258 if (talloc_unreference(context
, ptr
) == 0) {
1262 if (context
!= NULL
) {
1263 tc_c
= talloc_chunk_from_ptr(context
);
1267 if (tc_c
!= talloc_parent_chunk(ptr
)) {
1271 tc_p
= talloc_chunk_from_ptr(ptr
);
1273 if (tc_p
->refs
== NULL
) {
1274 return _talloc_free_internal(ptr
, __location__
);
1277 new_p
= talloc_parent_chunk(tc_p
->refs
);
1279 new_parent
= TC_PTR_FROM_CHUNK(new_p
);
1284 if (talloc_unreference(new_parent
, ptr
) != 0) {
1288 _talloc_steal_internal(new_parent
, ptr
);
1294 add a name to an existing pointer - va_list version
1296 static inline const char *talloc_set_name_v(const void *ptr
, const char *fmt
, va_list ap
) PRINTF_ATTRIBUTE(2,0);
1298 static inline const char *talloc_set_name_v(const void *ptr
, const char *fmt
, va_list ap
)
1300 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
1301 tc
->name
= talloc_vasprintf(ptr
, fmt
, ap
);
1302 if (likely(tc
->name
)) {
1303 _talloc_set_name_const(tc
->name
, ".name");
1309 add a name to an existing pointer
1311 _PUBLIC_
const char *talloc_set_name(const void *ptr
, const char *fmt
, ...)
1316 name
= talloc_set_name_v(ptr
, fmt
, ap
);
1323 create a named talloc pointer. Any talloc pointer can be named, and
1324 talloc_named() operates just like talloc() except that it allows you
1325 to name the pointer.
1327 _PUBLIC_
void *talloc_named(const void *context
, size_t size
, const char *fmt
, ...)
1333 ptr
= __talloc(context
, size
);
1334 if (unlikely(ptr
== NULL
)) return NULL
;
1337 name
= talloc_set_name_v(ptr
, fmt
, ap
);
1340 if (unlikely(name
== NULL
)) {
1341 _talloc_free_internal(ptr
, __location__
);
1349 return the name of a talloc ptr, or "UNNAMED"
1351 _PUBLIC_
const char *talloc_get_name(const void *ptr
)
1353 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
1354 if (unlikely(tc
->name
== TALLOC_MAGIC_REFERENCE
)) {
1355 return ".reference";
1357 if (likely(tc
->name
)) {
1365 check if a pointer has the given name. If it does, return the pointer,
1366 otherwise return NULL
1368 _PUBLIC_
void *talloc_check_name(const void *ptr
, const char *name
)
1371 if (unlikely(ptr
== NULL
)) return NULL
;
1372 pname
= talloc_get_name(ptr
);
1373 if (likely(pname
== name
|| strcmp(pname
, name
) == 0)) {
1374 return discard_const_p(void, ptr
);
1379 static void talloc_abort_type_mismatch(const char *location
,
1381 const char *expected
)
1385 reason
= talloc_asprintf(NULL
,
1386 "%s: Type mismatch: name[%s] expected[%s]",
1391 reason
= "Type mismatch";
1394 talloc_abort(reason
);
1397 _PUBLIC_
void *_talloc_get_type_abort(const void *ptr
, const char *name
, const char *location
)
1401 if (unlikely(ptr
== NULL
)) {
1402 talloc_abort_type_mismatch(location
, NULL
, name
);
1406 pname
= talloc_get_name(ptr
);
1407 if (likely(pname
== name
|| strcmp(pname
, name
) == 0)) {
1408 return discard_const_p(void, ptr
);
1411 talloc_abort_type_mismatch(location
, pname
, name
);
1416 this is for compatibility with older versions of talloc
1418 _PUBLIC_
void *talloc_init(const char *fmt
, ...)
1424 ptr
= __talloc(NULL
, 0);
1425 if (unlikely(ptr
== NULL
)) return NULL
;
1428 name
= talloc_set_name_v(ptr
, fmt
, ap
);
1431 if (unlikely(name
== NULL
)) {
1432 _talloc_free_internal(ptr
, __location__
);
1439 static inline void _talloc_free_children_internal(struct talloc_chunk
*tc
,
1441 const char *location
)
1444 /* we need to work out who will own an abandoned child
1445 if it cannot be freed. In priority order, the first
1446 choice is owner of any remaining reference to this
1447 pointer, the second choice is our parent, and the
1448 final choice is the null context. */
1449 void *child
= TC_PTR_FROM_CHUNK(tc
->child
);
1450 const void *new_parent
= null_context
;
1451 if (unlikely(tc
->child
->refs
)) {
1452 struct talloc_chunk
*p
= talloc_parent_chunk(tc
->child
->refs
);
1453 if (p
) new_parent
= TC_PTR_FROM_CHUNK(p
);
1455 if (unlikely(_talloc_free_internal(child
, location
) == -1)) {
1456 if (new_parent
== null_context
) {
1457 struct talloc_chunk
*p
= talloc_parent_chunk(ptr
);
1458 if (p
) new_parent
= TC_PTR_FROM_CHUNK(p
);
1460 _talloc_steal_internal(new_parent
, child
);
1466 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1467 should probably not be used in new code. It's in here to keep the talloc
1468 code consistent across Samba 3 and 4.
1470 _PUBLIC_
void talloc_free_children(void *ptr
)
1472 struct talloc_chunk
*tc_name
= NULL
;
1473 struct talloc_chunk
*tc
;
1475 if (unlikely(ptr
== NULL
)) {
1479 tc
= talloc_chunk_from_ptr(ptr
);
1481 /* we do not want to free the context name if it is a child .. */
1482 if (likely(tc
->child
)) {
1483 for (tc_name
= tc
->child
; tc_name
; tc_name
= tc_name
->next
) {
1484 if (tc
->name
== TC_PTR_FROM_CHUNK(tc_name
)) break;
1487 _TLIST_REMOVE(tc
->child
, tc_name
);
1489 tc
->child
->parent
= tc
;
1494 _talloc_free_children_internal(tc
, ptr
, __location__
);
1496 /* .. so we put it back after all other children have been freed */
1499 tc
->child
->parent
= NULL
;
1501 tc_name
->parent
= tc
;
1502 _TLIST_ADD(tc
->child
, tc_name
);
1507 Allocate a bit of memory as a child of an existing pointer
1509 _PUBLIC_
void *_talloc(const void *context
, size_t size
)
1511 return __talloc(context
, size
);
1515 externally callable talloc_set_name_const()
1517 _PUBLIC_
void talloc_set_name_const(const void *ptr
, const char *name
)
1519 _talloc_set_name_const(ptr
, name
);
1523 create a named talloc pointer. Any talloc pointer can be named, and
1524 talloc_named() operates just like talloc() except that it allows you
1525 to name the pointer.
1527 _PUBLIC_
void *talloc_named_const(const void *context
, size_t size
, const char *name
)
1529 return _talloc_named_const(context
, size
, name
);
1533 free a talloc pointer. This also frees all child pointers of this
1536 return 0 if the memory is actually freed, otherwise -1. The memory
1537 will not be freed if the ref_count is > 1 or the destructor (if
1538 any) returns non-zero
1540 _PUBLIC_
int _talloc_free(void *ptr
, const char *location
)
1542 struct talloc_chunk
*tc
;
1544 if (unlikely(ptr
== NULL
)) {
1548 tc
= talloc_chunk_from_ptr(ptr
);
1550 if (unlikely(tc
->refs
!= NULL
)) {
1551 struct talloc_reference_handle
*h
;
1553 if (talloc_parent(ptr
) == null_context
&& tc
->refs
->next
== NULL
) {
1554 /* in this case we do know which parent should
1555 get this pointer, as there is really only
1557 return talloc_unlink(null_context
, ptr
);
1560 talloc_log("ERROR: talloc_free with references at %s\n",
1563 for (h
=tc
->refs
; h
; h
=h
->next
) {
1564 talloc_log("\treference at %s\n",
1570 return _talloc_free_internal(ptr
, location
);
1576 A talloc version of realloc. The context argument is only used if
1579 _PUBLIC_
void *_talloc_realloc(const void *context
, void *ptr
, size_t size
, const char *name
)
1581 struct talloc_chunk
*tc
;
1583 bool malloced
= false;
1584 struct talloc_pool_hdr
*pool_hdr
= NULL
;
1585 size_t old_size
= 0;
1586 size_t new_size
= 0;
1588 /* size zero is equivalent to free() */
1589 if (unlikely(size
== 0)) {
1590 talloc_unlink(context
, ptr
);
1594 if (unlikely(size
>= MAX_TALLOC_SIZE
)) {
1598 /* realloc(NULL) is equivalent to malloc() */
1600 return _talloc_named_const(context
, size
, name
);
1603 tc
= talloc_chunk_from_ptr(ptr
);
1605 /* don't allow realloc on referenced pointers */
1606 if (unlikely(tc
->refs
)) {
1610 /* don't let anybody try to realloc a talloc_pool */
1611 if (unlikely(tc
->flags
& TALLOC_FLAG_POOL
)) {
1615 if (tc
->limit
&& (size
> tc
->size
)) {
1616 if (!talloc_memlimit_check(tc
->limit
, (size
- tc
->size
))) {
1622 /* handle realloc inside a talloc_pool */
1623 if (unlikely(tc
->flags
& TALLOC_FLAG_POOLMEM
)) {
1624 pool_hdr
= tc
->pool
;
1627 #if (ALWAYS_REALLOC == 0)
1628 /* don't shrink if we have less than 1k to gain */
1629 if (size
< tc
->size
&& tc
->limit
== NULL
) {
1631 void *next_tc
= tc_next_chunk(tc
);
1632 TC_INVALIDATE_SHRINK_CHUNK(tc
, size
);
1634 if (next_tc
== pool_hdr
->end
) {
1635 /* note: tc->size has changed, so this works */
1636 pool_hdr
->end
= tc_next_chunk(tc
);
1639 } else if ((tc
->size
- size
) < 1024) {
1641 * if we call TC_INVALIDATE_SHRINK_CHUNK() here
1642 * we would need to call TC_UNDEFINE_GROW_CHUNK()
1643 * after each realloc call, which slows down
1644 * testing a lot :-(.
1646 * That is why we only mark memory as undefined here.
1648 TC_UNDEFINE_SHRINK_CHUNK(tc
, size
);
1650 /* do not shrink if we have less than 1k to gain */
1654 } else if (tc
->size
== size
) {
1656 * do not change the pointer if it is exactly
1663 /* by resetting magic we catch users of the old memory */
1664 tc
->flags
|= TALLOC_FLAG_FREE
;
1668 new_ptr
= talloc_alloc_pool(tc
, size
+ TC_HDR_SIZE
, 0);
1669 pool_hdr
->object_count
--;
1671 if (new_ptr
== NULL
) {
1672 new_ptr
= malloc(TC_HDR_SIZE
+size
);
1678 memcpy(new_ptr
, tc
, MIN(tc
->size
,size
) + TC_HDR_SIZE
);
1679 TC_INVALIDATE_FULL_CHUNK(tc
);
1682 /* We're doing malloc then free here, so record the difference. */
1683 old_size
= tc
->size
;
1685 new_ptr
= malloc(size
+ TC_HDR_SIZE
);
1687 memcpy(new_ptr
, tc
, MIN(tc
->size
, size
) + TC_HDR_SIZE
);
1693 struct talloc_chunk
*pool_tc
;
1694 void *next_tc
= tc_next_chunk(tc
);
1695 size_t old_chunk_size
= TC_ALIGN16(TC_HDR_SIZE
+ tc
->size
);
1696 size_t new_chunk_size
= TC_ALIGN16(TC_HDR_SIZE
+ size
);
1697 size_t space_needed
;
1699 unsigned int chunk_count
= pool_hdr
->object_count
;
1701 pool_tc
= talloc_chunk_from_pool(pool_hdr
);
1702 if (!(pool_tc
->flags
& TALLOC_FLAG_FREE
)) {
1706 if (chunk_count
== 1) {
1708 * optimize for the case where 'tc' is the only
1709 * chunk in the pool.
1711 char *start
= tc_pool_first_chunk(pool_hdr
);
1712 space_needed
= new_chunk_size
;
1713 space_left
= (char *)tc_pool_end(pool_hdr
) - start
;
1715 if (space_left
>= space_needed
) {
1716 size_t old_used
= TC_HDR_SIZE
+ tc
->size
;
1717 size_t new_used
= TC_HDR_SIZE
+ size
;
1720 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
1724 * start -> tc may have
1725 * been freed and thus been marked as
1726 * VALGRIND_MEM_NOACCESS. Set it to
1727 * VALGRIND_MEM_UNDEFINED so we can
1728 * copy into it without valgrind errors.
1729 * We can't just mark
1730 * new_ptr -> new_ptr + old_used
1731 * as this may overlap on top of tc,
1732 * (which is why we use memmove, not
1733 * memcpy below) hence the MIN.
1735 size_t undef_len
= MIN((((char *)tc
) - ((char *)new_ptr
)),old_used
);
1736 VALGRIND_MAKE_MEM_UNDEFINED(new_ptr
, undef_len
);
1740 memmove(new_ptr
, tc
, old_used
);
1742 tc
= (struct talloc_chunk
*)new_ptr
;
1743 TC_UNDEFINE_GROW_CHUNK(tc
, size
);
1746 * first we do not align the pool pointer
1747 * because we want to invalidate the padding
1750 pool_hdr
->end
= new_used
+ (char *)new_ptr
;
1751 tc_invalidate_pool(pool_hdr
);
1753 /* now the aligned pointer */
1754 pool_hdr
->end
= new_chunk_size
+ (char *)new_ptr
;
1761 if (new_chunk_size
== old_chunk_size
) {
1762 TC_UNDEFINE_GROW_CHUNK(tc
, size
);
1763 tc
->flags
&= ~TALLOC_FLAG_FREE
;
1768 if (next_tc
== pool_hdr
->end
) {
1770 * optimize for the case where 'tc' is the last
1771 * chunk in the pool.
1773 space_needed
= new_chunk_size
- old_chunk_size
;
1774 space_left
= tc_pool_space_left(pool_hdr
);
1776 if (space_left
>= space_needed
) {
1777 TC_UNDEFINE_GROW_CHUNK(tc
, size
);
1778 tc
->flags
&= ~TALLOC_FLAG_FREE
;
1780 pool_hdr
->end
= tc_next_chunk(tc
);
1785 new_ptr
= talloc_alloc_pool(tc
, size
+ TC_HDR_SIZE
, 0);
1787 if (new_ptr
== NULL
) {
1788 new_ptr
= malloc(TC_HDR_SIZE
+size
);
1794 memcpy(new_ptr
, tc
, MIN(tc
->size
,size
) + TC_HDR_SIZE
);
1796 _talloc_free_poolmem(tc
, __location__
"_talloc_realloc");
1800 /* We're doing realloc here, so record the difference. */
1801 old_size
= tc
->size
;
1803 new_ptr
= realloc(tc
, size
+ TC_HDR_SIZE
);
1807 if (unlikely(!new_ptr
)) {
1808 tc
->flags
&= ~TALLOC_FLAG_FREE
;
1812 tc
= (struct talloc_chunk
*)new_ptr
;
1813 tc
->flags
&= ~TALLOC_FLAG_FREE
;
1815 tc
->flags
&= ~TALLOC_FLAG_POOLMEM
;
1818 tc
->parent
->child
= tc
;
1821 tc
->child
->parent
= tc
;
1825 tc
->prev
->next
= tc
;
1828 tc
->next
->prev
= tc
;
1831 if (new_size
> old_size
) {
1832 talloc_memlimit_grow(tc
->limit
, new_size
- old_size
);
1833 } else if (new_size
< old_size
) {
1834 talloc_memlimit_shrink(tc
->limit
, old_size
- new_size
);
1838 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc
), name
);
1840 return TC_PTR_FROM_CHUNK(tc
);
1844 a wrapper around talloc_steal() for situations where you are moving a pointer
1845 between two structures, and want the old pointer to be set to NULL
1847 _PUBLIC_
void *_talloc_move(const void *new_ctx
, const void *_pptr
)
1849 const void **pptr
= discard_const_p(const void *,_pptr
);
1850 void *ret
= talloc_steal(new_ctx
, discard_const_p(void, *pptr
));
1855 enum talloc_mem_count_type
{
1861 static size_t _talloc_total_mem_internal(const void *ptr
,
1862 enum talloc_mem_count_type type
,
1863 struct talloc_memlimit
*old_limit
,
1864 struct talloc_memlimit
*new_limit
)
1867 struct talloc_chunk
*c
, *tc
;
1876 tc
= talloc_chunk_from_ptr(ptr
);
1878 if (old_limit
|| new_limit
) {
1879 if (tc
->limit
&& tc
->limit
->upper
== old_limit
) {
1880 tc
->limit
->upper
= new_limit
;
1884 /* optimize in the memlimits case */
1885 if (type
== TOTAL_MEM_LIMIT
&&
1886 tc
->limit
!= NULL
&&
1887 tc
->limit
!= old_limit
&&
1888 tc
->limit
->parent
== tc
) {
1889 return tc
->limit
->cur_size
;
1892 if (tc
->flags
& TALLOC_FLAG_LOOP
) {
1896 tc
->flags
|= TALLOC_FLAG_LOOP
;
1898 if (old_limit
|| new_limit
) {
1899 if (old_limit
== tc
->limit
) {
1900 tc
->limit
= new_limit
;
1905 case TOTAL_MEM_SIZE
:
1906 if (likely(tc
->name
!= TALLOC_MAGIC_REFERENCE
)) {
1910 case TOTAL_MEM_BLOCKS
:
1913 case TOTAL_MEM_LIMIT
:
1914 if (likely(tc
->name
!= TALLOC_MAGIC_REFERENCE
)) {
1916 * Don't count memory allocated from a pool
1917 * when calculating limits. Only count the
1920 if (!(tc
->flags
& TALLOC_FLAG_POOLMEM
)) {
1921 if (tc
->flags
& TALLOC_FLAG_POOL
) {
1923 * If this is a pool, the allocated
1924 * size is in the pool header, and
1925 * remember to add in the prefix
1928 struct talloc_pool_hdr
*pool_hdr
1929 = talloc_pool_from_chunk(tc
);
1930 total
= pool_hdr
->poolsize
+
1934 total
= tc
->size
+ TC_HDR_SIZE
;
1940 for (c
= tc
->child
; c
; c
= c
->next
) {
1941 total
+= _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c
), type
,
1942 old_limit
, new_limit
);
1945 tc
->flags
&= ~TALLOC_FLAG_LOOP
;
1951 return the total size of a talloc pool (subtree)
1953 _PUBLIC_
size_t talloc_total_size(const void *ptr
)
1955 return _talloc_total_mem_internal(ptr
, TOTAL_MEM_SIZE
, NULL
, NULL
);
1959 return the total number of blocks in a talloc pool (subtree)
1961 _PUBLIC_
size_t talloc_total_blocks(const void *ptr
)
1963 return _talloc_total_mem_internal(ptr
, TOTAL_MEM_BLOCKS
, NULL
, NULL
);
1967 return the number of external references to a pointer
1969 _PUBLIC_
size_t talloc_reference_count(const void *ptr
)
1971 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
1972 struct talloc_reference_handle
*h
;
1975 for (h
=tc
->refs
;h
;h
=h
->next
) {
1982 report on memory usage by all children of a pointer, giving a full tree view
1984 _PUBLIC_
void talloc_report_depth_cb(const void *ptr
, int depth
, int max_depth
,
1985 void (*callback
)(const void *ptr
,
1986 int depth
, int max_depth
,
1988 void *private_data
),
1991 struct talloc_chunk
*c
, *tc
;
1996 if (ptr
== NULL
) return;
1998 tc
= talloc_chunk_from_ptr(ptr
);
2000 if (tc
->flags
& TALLOC_FLAG_LOOP
) {
2004 callback(ptr
, depth
, max_depth
, 0, private_data
);
2006 if (max_depth
>= 0 && depth
>= max_depth
) {
2010 tc
->flags
|= TALLOC_FLAG_LOOP
;
2011 for (c
=tc
->child
;c
;c
=c
->next
) {
2012 if (c
->name
== TALLOC_MAGIC_REFERENCE
) {
2013 struct talloc_reference_handle
*h
= (struct talloc_reference_handle
*)TC_PTR_FROM_CHUNK(c
);
2014 callback(h
->ptr
, depth
+ 1, max_depth
, 1, private_data
);
2016 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c
), depth
+ 1, max_depth
, callback
, private_data
);
2019 tc
->flags
&= ~TALLOC_FLAG_LOOP
;
2022 static void talloc_report_depth_FILE_helper(const void *ptr
, int depth
, int max_depth
, int is_ref
, void *_f
)
2024 const char *name
= talloc_get_name(ptr
);
2025 struct talloc_chunk
*tc
;
2026 FILE *f
= (FILE *)_f
;
2029 fprintf(f
, "%*sreference to: %s\n", depth
*4, "", name
);
2033 tc
= talloc_chunk_from_ptr(ptr
);
2034 if (tc
->limit
&& tc
->limit
->parent
== tc
) {
2035 fprintf(f
, "%*s%-30s is a memlimit context"
2036 " (max_size = %lu bytes, cur_size = %lu bytes)\n",
2039 (unsigned long)tc
->limit
->max_size
,
2040 (unsigned long)tc
->limit
->cur_size
);
2044 fprintf(f
,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
2045 (max_depth
< 0 ? "full " :""), name
,
2046 (unsigned long)talloc_total_size(ptr
),
2047 (unsigned long)talloc_total_blocks(ptr
));
2051 fprintf(f
, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
2054 (unsigned long)talloc_total_size(ptr
),
2055 (unsigned long)talloc_total_blocks(ptr
),
2056 (int)talloc_reference_count(ptr
), ptr
);
2059 fprintf(f
, "content: ");
2060 if (talloc_total_size(ptr
)) {
2061 int tot
= talloc_total_size(ptr
);
2064 for (i
= 0; i
< tot
; i
++) {
2065 if ((((char *)ptr
)[i
] > 31) && (((char *)ptr
)[i
] < 126)) {
2066 fprintf(f
, "%c", ((char *)ptr
)[i
]);
2068 fprintf(f
, "~%02x", ((char *)ptr
)[i
]);
2077 report on memory usage by all children of a pointer, giving a full tree view
2079 _PUBLIC_
void talloc_report_depth_file(const void *ptr
, int depth
, int max_depth
, FILE *f
)
2082 talloc_report_depth_cb(ptr
, depth
, max_depth
, talloc_report_depth_FILE_helper
, f
);
2088 report on memory usage by all children of a pointer, giving a full tree view
2090 _PUBLIC_
void talloc_report_full(const void *ptr
, FILE *f
)
2092 talloc_report_depth_file(ptr
, 0, -1, f
);
2096 report on memory usage by all children of a pointer
2098 _PUBLIC_
void talloc_report(const void *ptr
, FILE *f
)
2100 talloc_report_depth_file(ptr
, 0, 1, f
);
2104 report on any memory hanging off the null context
2106 static void talloc_report_null(void)
2108 if (talloc_total_size(null_context
) != 0) {
2109 talloc_report(null_context
, stderr
);
2114 report on any memory hanging off the null context
2116 static void talloc_report_null_full(void)
2118 if (talloc_total_size(null_context
) != 0) {
2119 talloc_report_full(null_context
, stderr
);
2124 enable tracking of the NULL context
2126 _PUBLIC_
void talloc_enable_null_tracking(void)
2128 if (null_context
== NULL
) {
2129 null_context
= _talloc_named_const(NULL
, 0, "null_context");
2130 if (autofree_context
!= NULL
) {
2131 talloc_reparent(NULL
, null_context
, autofree_context
);
2137 enable tracking of the NULL context, not moving the autofree context
2138 into the NULL context. This is needed for the talloc testsuite
2140 _PUBLIC_
void talloc_enable_null_tracking_no_autofree(void)
2142 if (null_context
== NULL
) {
2143 null_context
= _talloc_named_const(NULL
, 0, "null_context");
2148 disable tracking of the NULL context
2150 _PUBLIC_
void talloc_disable_null_tracking(void)
2152 if (null_context
!= NULL
) {
2153 /* we have to move any children onto the real NULL
2155 struct talloc_chunk
*tc
, *tc2
;
2156 tc
= talloc_chunk_from_ptr(null_context
);
2157 for (tc2
= tc
->child
; tc2
; tc2
=tc2
->next
) {
2158 if (tc2
->parent
== tc
) tc2
->parent
= NULL
;
2159 if (tc2
->prev
== tc
) tc2
->prev
= NULL
;
2161 for (tc2
= tc
->next
; tc2
; tc2
=tc2
->next
) {
2162 if (tc2
->parent
== tc
) tc2
->parent
= NULL
;
2163 if (tc2
->prev
== tc
) tc2
->prev
= NULL
;
2168 talloc_free(null_context
);
2169 null_context
= NULL
;
2173 enable leak reporting on exit
2175 _PUBLIC_
void talloc_enable_leak_report(void)
2177 talloc_enable_null_tracking();
2178 atexit(talloc_report_null
);
2182 enable full leak reporting on exit
2184 _PUBLIC_
void talloc_enable_leak_report_full(void)
2186 talloc_enable_null_tracking();
2187 atexit(talloc_report_null_full
);
2191 talloc and zero memory.
2193 _PUBLIC_
void *_talloc_zero(const void *ctx
, size_t size
, const char *name
)
2195 void *p
= _talloc_named_const(ctx
, size
, name
);
2198 memset(p
, '\0', size
);
2205 memdup with a talloc.
2207 _PUBLIC_
void *_talloc_memdup(const void *t
, const void *p
, size_t size
, const char *name
)
2209 void *newp
= _talloc_named_const(t
, size
, name
);
2212 memcpy(newp
, p
, size
);
2218 static inline char *__talloc_strlendup(const void *t
, const char *p
, size_t len
)
2222 ret
= (char *)__talloc(t
, len
+ 1);
2223 if (unlikely(!ret
)) return NULL
;
2225 memcpy(ret
, p
, len
);
2228 _talloc_set_name_const(ret
, ret
);
2233 strdup with a talloc
2235 _PUBLIC_
char *talloc_strdup(const void *t
, const char *p
)
2237 if (unlikely(!p
)) return NULL
;
2238 return __talloc_strlendup(t
, p
, strlen(p
));
2242 strndup with a talloc
2244 _PUBLIC_
char *talloc_strndup(const void *t
, const char *p
, size_t n
)
2246 if (unlikely(!p
)) return NULL
;
2247 return __talloc_strlendup(t
, p
, strnlen(p
, n
));
2250 static inline char *__talloc_strlendup_append(char *s
, size_t slen
,
2251 const char *a
, size_t alen
)
2255 ret
= talloc_realloc(NULL
, s
, char, slen
+ alen
+ 1);
2256 if (unlikely(!ret
)) return NULL
;
2258 /* append the string and the trailing \0 */
2259 memcpy(&ret
[slen
], a
, alen
);
2262 _talloc_set_name_const(ret
, ret
);
2267 * Appends at the end of the string.
2269 _PUBLIC_
char *talloc_strdup_append(char *s
, const char *a
)
2272 return talloc_strdup(NULL
, a
);
2279 return __talloc_strlendup_append(s
, strlen(s
), a
, strlen(a
));
2283 * Appends at the end of the talloc'ed buffer,
2284 * not the end of the string.
2286 _PUBLIC_
char *talloc_strdup_append_buffer(char *s
, const char *a
)
2291 return talloc_strdup(NULL
, a
);
2298 slen
= talloc_get_size(s
);
2299 if (likely(slen
> 0)) {
2303 return __talloc_strlendup_append(s
, slen
, a
, strlen(a
));
2307 * Appends at the end of the string.
2309 _PUBLIC_
char *talloc_strndup_append(char *s
, const char *a
, size_t n
)
2312 return talloc_strndup(NULL
, a
, n
);
2319 return __talloc_strlendup_append(s
, strlen(s
), a
, strnlen(a
, n
));
2323 * Appends at the end of the talloc'ed buffer,
2324 * not the end of the string.
2326 _PUBLIC_
char *talloc_strndup_append_buffer(char *s
, const char *a
, size_t n
)
2331 return talloc_strndup(NULL
, a
, n
);
2338 slen
= talloc_get_size(s
);
2339 if (likely(slen
> 0)) {
2343 return __talloc_strlendup_append(s
, slen
, a
, strnlen(a
, n
));
2346 #ifndef HAVE_VA_COPY
2347 #ifdef HAVE___VA_COPY
2348 #define va_copy(dest, src) __va_copy(dest, src)
2350 #define va_copy(dest, src) (dest) = (src)
2354 _PUBLIC_
char *talloc_vasprintf(const void *t
, const char *fmt
, va_list ap
)
2361 /* this call looks strange, but it makes it work on older solaris boxes */
2363 len
= vsnprintf(&c
, 1, fmt
, ap2
);
2365 if (unlikely(len
< 0)) {
2369 ret
= (char *)__talloc(t
, len
+1);
2370 if (unlikely(!ret
)) return NULL
;
2373 vsnprintf(ret
, len
+1, fmt
, ap2
);
2376 _talloc_set_name_const(ret
, ret
);
2382 Perform string formatting, and return a pointer to newly allocated
2383 memory holding the result, inside a memory pool.
2385 _PUBLIC_
char *talloc_asprintf(const void *t
, const char *fmt
, ...)
2391 ret
= talloc_vasprintf(t
, fmt
, ap
);
2396 static inline char *__talloc_vaslenprintf_append(char *s
, size_t slen
,
2397 const char *fmt
, va_list ap
)
2398 PRINTF_ATTRIBUTE(3,0);
2400 static inline char *__talloc_vaslenprintf_append(char *s
, size_t slen
,
2401 const char *fmt
, va_list ap
)
2408 alen
= vsnprintf(&c
, 1, fmt
, ap2
);
2412 /* Either the vsnprintf failed or the format resulted in
2413 * no characters being formatted. In the former case, we
2414 * ought to return NULL, in the latter we ought to return
2415 * the original string. Most current callers of this
2416 * function expect it to never return NULL.
2421 s
= talloc_realloc(NULL
, s
, char, slen
+ alen
+ 1);
2422 if (!s
) return NULL
;
2425 vsnprintf(s
+ slen
, alen
+ 1, fmt
, ap2
);
2428 _talloc_set_name_const(s
, s
);
2433 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2434 * and return @p s, which may have moved. Good for gradually
2435 * accumulating output into a string buffer. Appends at the end
2438 _PUBLIC_
char *talloc_vasprintf_append(char *s
, const char *fmt
, va_list ap
)
2441 return talloc_vasprintf(NULL
, fmt
, ap
);
2444 return __talloc_vaslenprintf_append(s
, strlen(s
), fmt
, ap
);
2448 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2449 * and return @p s, which may have moved. Always appends at the
2450 * end of the talloc'ed buffer, not the end of the string.
2452 _PUBLIC_
char *talloc_vasprintf_append_buffer(char *s
, const char *fmt
, va_list ap
)
2457 return talloc_vasprintf(NULL
, fmt
, ap
);
2460 slen
= talloc_get_size(s
);
2461 if (likely(slen
> 0)) {
2465 return __talloc_vaslenprintf_append(s
, slen
, fmt
, ap
);
2469 Realloc @p s to append the formatted result of @p fmt and return @p
2470 s, which may have moved. Good for gradually accumulating output
2471 into a string buffer.
2473 _PUBLIC_
char *talloc_asprintf_append(char *s
, const char *fmt
, ...)
2478 s
= talloc_vasprintf_append(s
, fmt
, ap
);
2484 Realloc @p s to append the formatted result of @p fmt and return @p
2485 s, which may have moved. Good for gradually accumulating output
2488 _PUBLIC_
char *talloc_asprintf_append_buffer(char *s
, const char *fmt
, ...)
2493 s
= talloc_vasprintf_append_buffer(s
, fmt
, ap
);
2499 alloc an array, checking for integer overflow in the array size
2501 _PUBLIC_
void *_talloc_array(const void *ctx
, size_t el_size
, unsigned count
, const char *name
)
2503 if (count
>= MAX_TALLOC_SIZE
/el_size
) {
2506 return _talloc_named_const(ctx
, el_size
* count
, name
);
2510 alloc an zero array, checking for integer overflow in the array size
2512 _PUBLIC_
void *_talloc_zero_array(const void *ctx
, size_t el_size
, unsigned count
, const char *name
)
2514 if (count
>= MAX_TALLOC_SIZE
/el_size
) {
2517 return _talloc_zero(ctx
, el_size
* count
, name
);
2521 realloc an array, checking for integer overflow in the array size
2523 _PUBLIC_
void *_talloc_realloc_array(const void *ctx
, void *ptr
, size_t el_size
, unsigned count
, const char *name
)
2525 if (count
>= MAX_TALLOC_SIZE
/el_size
) {
2528 return _talloc_realloc(ctx
, ptr
, el_size
* count
, name
);
2532 a function version of talloc_realloc(), so it can be passed as a function pointer
2533 to libraries that want a realloc function (a realloc function encapsulates
2534 all the basic capabilities of an allocation library, which is why this is useful)
2536 _PUBLIC_
void *talloc_realloc_fn(const void *context
, void *ptr
, size_t size
)
2538 return _talloc_realloc(context
, ptr
, size
, NULL
);
2542 static int talloc_autofree_destructor(void *ptr
)
2544 autofree_context
= NULL
;
2548 static void talloc_autofree(void)
2550 talloc_free(autofree_context
);
2554 return a context which will be auto-freed on exit
2555 this is useful for reducing the noise in leak reports
2557 _PUBLIC_
void *talloc_autofree_context(void)
2559 if (autofree_context
== NULL
) {
2560 autofree_context
= _talloc_named_const(NULL
, 0, "autofree_context");
2561 talloc_set_destructor(autofree_context
, talloc_autofree_destructor
);
2562 atexit(talloc_autofree
);
2564 return autofree_context
;
2567 _PUBLIC_
size_t talloc_get_size(const void *context
)
2569 struct talloc_chunk
*tc
;
2571 if (context
== NULL
) {
2572 context
= null_context
;
2574 if (context
== NULL
) {
2578 tc
= talloc_chunk_from_ptr(context
);
2584 find a parent of this context that has the given name, if any
2586 _PUBLIC_
void *talloc_find_parent_byname(const void *context
, const char *name
)
2588 struct talloc_chunk
*tc
;
2590 if (context
== NULL
) {
2594 tc
= talloc_chunk_from_ptr(context
);
2596 if (tc
->name
&& strcmp(tc
->name
, name
) == 0) {
2597 return TC_PTR_FROM_CHUNK(tc
);
2599 while (tc
&& tc
->prev
) tc
= tc
->prev
;
2608 show the parentage of a context
2610 _PUBLIC_
void talloc_show_parents(const void *context
, FILE *file
)
2612 struct talloc_chunk
*tc
;
2614 if (context
== NULL
) {
2615 fprintf(file
, "talloc no parents for NULL\n");
2619 tc
= talloc_chunk_from_ptr(context
);
2620 fprintf(file
, "talloc parents of '%s'\n", talloc_get_name(context
));
2622 fprintf(file
, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc
)));
2623 while (tc
&& tc
->prev
) tc
= tc
->prev
;
2632 return 1 if ptr is a parent of context
2634 static int _talloc_is_parent(const void *context
, const void *ptr
, int depth
)
2636 struct talloc_chunk
*tc
;
2638 if (context
== NULL
) {
2642 tc
= talloc_chunk_from_ptr(context
);
2643 while (tc
&& depth
> 0) {
2644 if (TC_PTR_FROM_CHUNK(tc
) == ptr
) return 1;
2645 while (tc
&& tc
->prev
) tc
= tc
->prev
;
2655 return 1 if ptr is a parent of context
2657 _PUBLIC_
int talloc_is_parent(const void *context
, const void *ptr
)
2659 return _talloc_is_parent(context
, ptr
, TALLOC_MAX_DEPTH
);
2663 return the total size of memory used by this context and all children
2665 static size_t _talloc_total_limit_size(const void *ptr
,
2666 struct talloc_memlimit
*old_limit
,
2667 struct talloc_memlimit
*new_limit
)
2669 return _talloc_total_mem_internal(ptr
, TOTAL_MEM_LIMIT
,
2670 old_limit
, new_limit
);
2673 static bool talloc_memlimit_check(struct talloc_memlimit
*limit
, size_t size
)
2675 struct talloc_memlimit
*l
;
2677 for (l
= limit
; l
!= NULL
; l
= l
->upper
) {
2678 if (l
->max_size
!= 0 &&
2679 ((l
->max_size
<= l
->cur_size
) ||
2680 (l
->max_size
- l
->cur_size
< size
))) {
2689 Update memory limits when freeing a talloc_chunk.
2691 static void talloc_memlimit_update_on_free(struct talloc_chunk
*tc
)
2693 size_t limit_shrink_size
;
2700 * Pool entries don't count. Only the pools
2701 * themselves are counted as part of the memory
2702 * limits. Note that this also takes care of
2703 * nested pools which have both flags
2704 * TALLOC_FLAG_POOLMEM|TALLOC_FLAG_POOL set.
2706 if (tc
->flags
& TALLOC_FLAG_POOLMEM
) {
2711 * If we are part of a memory limited context hierarchy
2712 * we need to subtract the memory used from the counters
2715 limit_shrink_size
= tc
->size
+TC_HDR_SIZE
;
2718 * If we're deallocating a pool, take into
2719 * account the prefix size added for the pool.
2722 if (tc
->flags
& TALLOC_FLAG_POOL
) {
2723 limit_shrink_size
+= TP_HDR_SIZE
;
2726 talloc_memlimit_shrink(tc
->limit
, limit_shrink_size
);
2728 if (tc
->limit
->parent
== tc
) {
2736 Increase memory limit accounting after a malloc/realloc.
2738 static void talloc_memlimit_grow(struct talloc_memlimit
*limit
,
2741 struct talloc_memlimit
*l
;
2743 for (l
= limit
; l
!= NULL
; l
= l
->upper
) {
2744 size_t new_cur_size
= l
->cur_size
+ size
;
2745 if (new_cur_size
< l
->cur_size
) {
2746 talloc_abort("logic error in talloc_memlimit_grow\n");
2749 l
->cur_size
= new_cur_size
;
2754 Decrease memory limit accounting after a free/realloc.
2756 static void talloc_memlimit_shrink(struct talloc_memlimit
*limit
,
2759 struct talloc_memlimit
*l
;
2761 for (l
= limit
; l
!= NULL
; l
= l
->upper
) {
2762 if (l
->cur_size
< size
) {
2763 talloc_abort("logic error in talloc_memlimit_shrink\n");
2766 l
->cur_size
= l
->cur_size
- size
;
2770 _PUBLIC_
int talloc_set_memlimit(const void *ctx
, size_t max_size
)
2772 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ctx
);
2773 struct talloc_memlimit
*orig_limit
;
2774 struct talloc_memlimit
*limit
= NULL
;
2776 if (tc
->limit
&& tc
->limit
->parent
== tc
) {
2777 tc
->limit
->max_size
= max_size
;
2780 orig_limit
= tc
->limit
;
2782 limit
= malloc(sizeof(struct talloc_memlimit
));
2783 if (limit
== NULL
) {
2787 limit
->max_size
= max_size
;
2788 limit
->cur_size
= _talloc_total_limit_size(ctx
, tc
->limit
, limit
);
2791 limit
->upper
= orig_limit
;
2793 limit
->upper
= NULL
;