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
;
466 #define TP_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_pool_hdr))
468 static struct talloc_pool_hdr
*talloc_pool_from_chunk(struct talloc_chunk
*c
)
470 return (struct talloc_pool_hdr
*)((char *)c
- TP_HDR_SIZE
);
473 static struct talloc_chunk
*talloc_chunk_from_pool(struct talloc_pool_hdr
*h
)
475 return (struct talloc_chunk
*)((char *)h
+ TP_HDR_SIZE
);
478 static void *tc_pool_end(struct talloc_pool_hdr
*pool_hdr
)
480 struct talloc_chunk
*tc
= talloc_chunk_from_pool(pool_hdr
);
481 return (char *)tc
+ TC_HDR_SIZE
+ tc
->size
;
484 static size_t tc_pool_space_left(struct talloc_pool_hdr
*pool_hdr
)
486 return (char *)tc_pool_end(pool_hdr
) - (char *)pool_hdr
->end
;
489 static void *tc_pool_first_chunk(struct talloc_pool_hdr
*pool_hdr
)
491 return TC_PTR_FROM_CHUNK(talloc_chunk_from_pool(pool_hdr
));
494 /* If tc is inside a pool, this gives the next neighbour. */
495 static void *tc_next_chunk(struct talloc_chunk
*tc
)
497 return (char *)tc
+ TC_ALIGN16(TC_HDR_SIZE
+ tc
->size
);
500 /* Mark the whole remaining pool as not accessable */
501 static void tc_invalidate_pool(struct talloc_pool_hdr
*pool_hdr
)
503 size_t flen
= tc_pool_space_left(pool_hdr
);
505 if (unlikely(talloc_fill
.enabled
)) {
506 memset(pool_hdr
->end
, talloc_fill
.fill_value
, flen
);
509 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
510 VALGRIND_MAKE_MEM_NOACCESS(pool_hdr
->end
, flen
);
518 static struct talloc_chunk
*talloc_alloc_pool(struct talloc_chunk
*parent
,
519 size_t size
, size_t prefix_len
)
521 struct talloc_pool_hdr
*pool_hdr
= NULL
;
523 struct talloc_chunk
*result
;
526 if (parent
== NULL
) {
530 if (parent
->flags
& TALLOC_FLAG_POOL
) {
531 pool_hdr
= talloc_pool_from_chunk(parent
);
533 else if (parent
->flags
& TALLOC_FLAG_POOLMEM
) {
534 pool_hdr
= parent
->pool
;
537 if (pool_hdr
== NULL
) {
541 space_left
= tc_pool_space_left(pool_hdr
);
544 * Align size to 16 bytes
546 chunk_size
= TC_ALIGN16(size
+ prefix_len
);
548 if (space_left
< chunk_size
) {
552 result
= (struct talloc_chunk
*)((char *)pool_hdr
->end
+ prefix_len
);
554 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
555 VALGRIND_MAKE_MEM_UNDEFINED(pool_hdr
->end
, chunk_size
);
558 pool_hdr
->end
= (void *)((char *)pool_hdr
->end
+ chunk_size
);
560 result
->flags
= TALLOC_MAGIC
| TALLOC_FLAG_POOLMEM
;
561 result
->pool
= pool_hdr
;
563 pool_hdr
->object_count
++;
569 Allocate a bit of memory as a child of an existing pointer
571 static inline void *__talloc_with_prefix(const void *context
, size_t size
,
574 struct talloc_chunk
*tc
= NULL
;
575 struct talloc_memlimit
*limit
= NULL
;
576 size_t total_len
= TC_HDR_SIZE
+ size
+ prefix_len
;
578 if (unlikely(context
== NULL
)) {
579 context
= null_context
;
582 if (unlikely(size
>= MAX_TALLOC_SIZE
)) {
586 if (unlikely(total_len
< TC_HDR_SIZE
)) {
590 if (context
!= NULL
) {
591 struct talloc_chunk
*ptc
= talloc_chunk_from_ptr(context
);
593 if (ptc
->limit
!= NULL
) {
597 tc
= talloc_alloc_pool(ptc
, TC_HDR_SIZE
+size
, prefix_len
);
604 * Only do the memlimit check/update on actual allocation.
606 if (!talloc_memlimit_check(limit
, total_len
)) {
611 ptr
= malloc(total_len
);
612 if (unlikely(ptr
== NULL
)) {
615 tc
= (struct talloc_chunk
*)(ptr
+ prefix_len
);
616 tc
->flags
= TALLOC_MAGIC
;
619 talloc_memlimit_grow(limit
, total_len
);
624 tc
->destructor
= NULL
;
629 if (likely(context
)) {
630 struct talloc_chunk
*parent
= talloc_chunk_from_ptr(context
);
633 parent
->child
->parent
= NULL
;
634 tc
->next
= parent
->child
;
643 tc
->next
= tc
->prev
= tc
->parent
= NULL
;
646 return TC_PTR_FROM_CHUNK(tc
);
649 static inline void *__talloc(const void *context
, size_t size
)
651 return __talloc_with_prefix(context
, size
, 0);
655 * Create a talloc pool
658 _PUBLIC_
void *talloc_pool(const void *context
, size_t size
)
660 struct talloc_chunk
*tc
;
661 struct talloc_pool_hdr
*pool_hdr
;
664 result
= __talloc_with_prefix(context
, size
, TP_HDR_SIZE
);
666 if (unlikely(result
== NULL
)) {
670 tc
= talloc_chunk_from_ptr(result
);
671 pool_hdr
= talloc_pool_from_chunk(tc
);
673 if (unlikely(tc
->flags
& TALLOC_FLAG_POOLMEM
)) {
674 /* We don't handle this correctly, so fail. */
675 talloc_log("talloc: cannot allocate pool off another pool %s\n",
676 talloc_get_name(context
));
680 tc
->flags
|= TALLOC_FLAG_POOL
;
682 pool_hdr
->object_count
= 1;
683 pool_hdr
->end
= result
;
685 tc_invalidate_pool(pool_hdr
);
691 setup a destructor to be called on free of a pointer
692 the destructor should return 0 on success, or -1 on failure.
693 if the destructor fails then the free is failed, and the memory can
694 be continued to be used
696 _PUBLIC_
void _talloc_set_destructor(const void *ptr
, int (*destructor
)(void *))
698 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
699 tc
->destructor
= destructor
;
703 increase the reference count on a piece of memory.
705 _PUBLIC_
int talloc_increase_ref_count(const void *ptr
)
707 if (unlikely(!talloc_reference(null_context
, ptr
))) {
714 helper for talloc_reference()
716 this is referenced by a function pointer and should not be inline
718 static int talloc_reference_destructor(struct talloc_reference_handle
*handle
)
720 struct talloc_chunk
*ptr_tc
= talloc_chunk_from_ptr(handle
->ptr
);
721 _TLIST_REMOVE(ptr_tc
->refs
, handle
);
726 more efficient way to add a name to a pointer - the name must point to a
729 static inline void _talloc_set_name_const(const void *ptr
, const char *name
)
731 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
736 internal talloc_named_const()
738 static inline void *_talloc_named_const(const void *context
, size_t size
, const char *name
)
742 ptr
= __talloc(context
, size
);
743 if (unlikely(ptr
== NULL
)) {
747 _talloc_set_name_const(ptr
, name
);
753 make a secondary reference to a pointer, hanging off the given context.
754 the pointer remains valid until both the original caller and this given
757 the major use for this is when two different structures need to reference the
758 same underlying data, and you want to be able to free the two instances separately,
761 _PUBLIC_
void *_talloc_reference_loc(const void *context
, const void *ptr
, const char *location
)
763 struct talloc_chunk
*tc
;
764 struct talloc_reference_handle
*handle
;
765 if (unlikely(ptr
== NULL
)) return NULL
;
767 tc
= talloc_chunk_from_ptr(ptr
);
768 handle
= (struct talloc_reference_handle
*)_talloc_named_const(context
,
769 sizeof(struct talloc_reference_handle
),
770 TALLOC_MAGIC_REFERENCE
);
771 if (unlikely(handle
== NULL
)) return NULL
;
773 /* note that we hang the destructor off the handle, not the
774 main context as that allows the caller to still setup their
775 own destructor on the context if they want to */
776 talloc_set_destructor(handle
, talloc_reference_destructor
);
777 handle
->ptr
= discard_const_p(void, ptr
);
778 handle
->location
= location
;
779 _TLIST_ADD(tc
->refs
, handle
);
783 static void *_talloc_steal_internal(const void *new_ctx
, const void *ptr
);
785 static inline void _talloc_free_poolmem(struct talloc_chunk
*tc
,
786 const char *location
)
788 struct talloc_pool_hdr
*pool
;
789 struct talloc_chunk
*pool_tc
;
793 pool_tc
= talloc_chunk_from_pool(pool
);
794 next_tc
= tc_next_chunk(tc
);
796 tc
->flags
|= TALLOC_FLAG_FREE
;
798 /* we mark the freed memory with where we called the free
799 * from. This means on a double free error we can report where
800 * the first free came from
804 TC_INVALIDATE_FULL_CHUNK(tc
);
806 if (unlikely(pool
->object_count
== 0)) {
807 talloc_abort("Pool object count zero!");
811 pool
->object_count
--;
813 if (unlikely(pool
->object_count
== 1
814 && !(pool_tc
->flags
& TALLOC_FLAG_FREE
))) {
816 * if there is just one object left in the pool
817 * and pool->flags does not have TALLOC_FLAG_FREE,
818 * it means this is the pool itself and
819 * the rest is available for new objects
822 pool
->end
= tc_pool_first_chunk(pool
);
823 tc_invalidate_pool(pool
);
827 if (unlikely(pool
->object_count
== 0)) {
829 * we mark the freed memory with where we called the free
830 * from. This means on a double free error we can report where
831 * the first free came from
833 pool_tc
->name
= location
;
835 talloc_memlimit_update_on_free(pool_tc
);
837 TC_INVALIDATE_FULL_CHUNK(pool_tc
);
842 if (pool
->end
== next_tc
) {
844 * if pool->pool still points to end of
845 * 'tc' (which is stored in the 'next_tc' variable),
846 * we can reclaim the memory of 'tc'.
853 * Do nothing. The memory is just "wasted", waiting for the pool
854 * itself to be freed.
858 static inline void _talloc_free_children_internal(struct talloc_chunk
*tc
,
860 const char *location
);
863 internal talloc_free call
865 static inline int _talloc_free_internal(void *ptr
, const char *location
)
867 struct talloc_chunk
*tc
;
869 if (unlikely(ptr
== NULL
)) {
873 /* possibly initialised the talloc fill value */
874 if (unlikely(!talloc_fill
.initialised
)) {
875 const char *fill
= getenv(TALLOC_FILL_ENV
);
877 talloc_fill
.enabled
= true;
878 talloc_fill
.fill_value
= strtoul(fill
, NULL
, 0);
880 talloc_fill
.initialised
= true;
883 tc
= talloc_chunk_from_ptr(ptr
);
885 if (unlikely(tc
->refs
)) {
887 /* check if this is a reference from a child or
888 * grandchild back to it's parent or grandparent
890 * in that case we need to remove the reference and
891 * call another instance of talloc_free() on the current
894 is_child
= talloc_is_parent(tc
->refs
, ptr
);
895 _talloc_free_internal(tc
->refs
, location
);
897 return _talloc_free_internal(ptr
, location
);
902 if (unlikely(tc
->flags
& TALLOC_FLAG_LOOP
)) {
903 /* we have a free loop - stop looping */
907 if (unlikely(tc
->destructor
)) {
908 talloc_destructor_t d
= tc
->destructor
;
909 if (d
== (talloc_destructor_t
)-1) {
912 tc
->destructor
= (talloc_destructor_t
)-1;
917 tc
->destructor
= NULL
;
921 _TLIST_REMOVE(tc
->parent
->child
, tc
);
922 if (tc
->parent
->child
) {
923 tc
->parent
->child
->parent
= tc
->parent
;
926 if (tc
->prev
) tc
->prev
->next
= tc
->next
;
927 if (tc
->next
) tc
->next
->prev
= tc
->prev
;
928 tc
->prev
= tc
->next
= NULL
;
931 tc
->flags
|= TALLOC_FLAG_LOOP
;
933 _talloc_free_children_internal(tc
, ptr
, location
);
935 tc
->flags
|= TALLOC_FLAG_FREE
;
937 /* we mark the freed memory with where we called the free
938 * from. This means on a double free error we can report where
939 * the first free came from
943 if (tc
->flags
& TALLOC_FLAG_POOL
) {
944 struct talloc_pool_hdr
*pool
;
946 pool
= talloc_pool_from_chunk(tc
);
948 if (unlikely(pool
->object_count
== 0)) {
949 talloc_abort("Pool object count zero!");
953 pool
->object_count
--;
955 if (likely(pool
->object_count
!= 0)) {
960 * This call takes into account the
961 * prefix TP_HDR_SIZE allocated before
962 * the pool talloc_chunk.
964 talloc_memlimit_update_on_free(tc
);
966 TC_INVALIDATE_FULL_CHUNK(tc
);
971 if (tc
->flags
& TALLOC_FLAG_POOLMEM
) {
972 _talloc_free_poolmem(tc
, location
);
976 talloc_memlimit_update_on_free(tc
);
978 TC_INVALIDATE_FULL_CHUNK(tc
);
983 static size_t _talloc_total_limit_size(const void *ptr
,
984 struct talloc_memlimit
*old_limit
,
985 struct talloc_memlimit
*new_limit
);
988 move a lump of memory from one talloc context to another return the
989 ptr on success, or NULL if it could not be transferred.
990 passing NULL as ptr will always return NULL with no side effects.
992 static void *_talloc_steal_internal(const void *new_ctx
, const void *ptr
)
994 struct talloc_chunk
*tc
, *new_tc
;
997 if (unlikely(!ptr
)) {
1001 if (unlikely(new_ctx
== NULL
)) {
1002 new_ctx
= null_context
;
1005 tc
= talloc_chunk_from_ptr(ptr
);
1007 if (tc
->limit
!= NULL
) {
1009 ctx_size
= _talloc_total_limit_size(ptr
, NULL
, NULL
);
1011 /* Decrement the memory limit from the source .. */
1012 talloc_memlimit_shrink(tc
->limit
->upper
, ctx_size
);
1014 if (tc
->limit
->parent
== tc
) {
1015 tc
->limit
->upper
= NULL
;
1021 if (unlikely(new_ctx
== NULL
)) {
1023 _TLIST_REMOVE(tc
->parent
->child
, tc
);
1024 if (tc
->parent
->child
) {
1025 tc
->parent
->child
->parent
= tc
->parent
;
1028 if (tc
->prev
) tc
->prev
->next
= tc
->next
;
1029 if (tc
->next
) tc
->next
->prev
= tc
->prev
;
1032 tc
->parent
= tc
->next
= tc
->prev
= NULL
;
1033 return discard_const_p(void, ptr
);
1036 new_tc
= talloc_chunk_from_ptr(new_ctx
);
1038 if (unlikely(tc
== new_tc
|| tc
->parent
== new_tc
)) {
1039 return discard_const_p(void, ptr
);
1043 _TLIST_REMOVE(tc
->parent
->child
, tc
);
1044 if (tc
->parent
->child
) {
1045 tc
->parent
->child
->parent
= tc
->parent
;
1048 if (tc
->prev
) tc
->prev
->next
= tc
->next
;
1049 if (tc
->next
) tc
->next
->prev
= tc
->prev
;
1050 tc
->prev
= tc
->next
= NULL
;
1053 tc
->parent
= new_tc
;
1054 if (new_tc
->child
) new_tc
->child
->parent
= NULL
;
1055 _TLIST_ADD(new_tc
->child
, tc
);
1057 if (tc
->limit
|| new_tc
->limit
) {
1058 ctx_size
= _talloc_total_limit_size(ptr
, tc
->limit
,
1060 /* .. and increment it in the destination. */
1061 if (new_tc
->limit
) {
1062 talloc_memlimit_grow(new_tc
->limit
, ctx_size
);
1066 return discard_const_p(void, ptr
);
1070 move a lump of memory from one talloc context to another return the
1071 ptr on success, or NULL if it could not be transferred.
1072 passing NULL as ptr will always return NULL with no side effects.
1074 _PUBLIC_
void *_talloc_steal_loc(const void *new_ctx
, const void *ptr
, const char *location
)
1076 struct talloc_chunk
*tc
;
1078 if (unlikely(ptr
== NULL
)) {
1082 tc
= talloc_chunk_from_ptr(ptr
);
1084 if (unlikely(tc
->refs
!= NULL
) && talloc_parent(ptr
) != new_ctx
) {
1085 struct talloc_reference_handle
*h
;
1087 talloc_log("WARNING: talloc_steal with references at %s\n",
1090 for (h
=tc
->refs
; h
; h
=h
->next
) {
1091 talloc_log("\treference at %s\n",
1097 /* this test is probably too expensive to have on in the
1098 normal build, but it useful for debugging */
1099 if (talloc_is_parent(new_ctx
, ptr
)) {
1100 talloc_log("WARNING: stealing into talloc child at %s\n", location
);
1104 return _talloc_steal_internal(new_ctx
, ptr
);
1108 this is like a talloc_steal(), but you must supply the old
1109 parent. This resolves the ambiguity in a talloc_steal() which is
1110 called on a context that has more than one parent (via references)
1112 The old parent can be either a reference or a parent
1114 _PUBLIC_
void *talloc_reparent(const void *old_parent
, const void *new_parent
, const void *ptr
)
1116 struct talloc_chunk
*tc
;
1117 struct talloc_reference_handle
*h
;
1119 if (unlikely(ptr
== NULL
)) {
1123 if (old_parent
== talloc_parent(ptr
)) {
1124 return _talloc_steal_internal(new_parent
, ptr
);
1127 tc
= talloc_chunk_from_ptr(ptr
);
1128 for (h
=tc
->refs
;h
;h
=h
->next
) {
1129 if (talloc_parent(h
) == old_parent
) {
1130 if (_talloc_steal_internal(new_parent
, h
) != h
) {
1133 return discard_const_p(void, ptr
);
1137 /* it wasn't a parent */
1142 remove a secondary reference to a pointer. This undo's what
1143 talloc_reference() has done. The context and pointer arguments
1144 must match those given to a talloc_reference()
1146 static inline int talloc_unreference(const void *context
, const void *ptr
)
1148 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
1149 struct talloc_reference_handle
*h
;
1151 if (unlikely(context
== NULL
)) {
1152 context
= null_context
;
1155 for (h
=tc
->refs
;h
;h
=h
->next
) {
1156 struct talloc_chunk
*p
= talloc_parent_chunk(h
);
1158 if (context
== NULL
) break;
1159 } else if (TC_PTR_FROM_CHUNK(p
) == context
) {
1167 return _talloc_free_internal(h
, __location__
);
1171 remove a specific parent context from a pointer. This is a more
1172 controlled variant of talloc_free()
1174 _PUBLIC_
int talloc_unlink(const void *context
, void *ptr
)
1176 struct talloc_chunk
*tc_p
, *new_p
, *tc_c
;
1183 if (context
== NULL
) {
1184 context
= null_context
;
1187 if (talloc_unreference(context
, ptr
) == 0) {
1191 if (context
!= NULL
) {
1192 tc_c
= talloc_chunk_from_ptr(context
);
1196 if (tc_c
!= talloc_parent_chunk(ptr
)) {
1200 tc_p
= talloc_chunk_from_ptr(ptr
);
1202 if (tc_p
->refs
== NULL
) {
1203 return _talloc_free_internal(ptr
, __location__
);
1206 new_p
= talloc_parent_chunk(tc_p
->refs
);
1208 new_parent
= TC_PTR_FROM_CHUNK(new_p
);
1213 if (talloc_unreference(new_parent
, ptr
) != 0) {
1217 _talloc_steal_internal(new_parent
, ptr
);
1223 add a name to an existing pointer - va_list version
1225 static inline const char *talloc_set_name_v(const void *ptr
, const char *fmt
, va_list ap
) PRINTF_ATTRIBUTE(2,0);
1227 static inline const char *talloc_set_name_v(const void *ptr
, const char *fmt
, va_list ap
)
1229 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
1230 tc
->name
= talloc_vasprintf(ptr
, fmt
, ap
);
1231 if (likely(tc
->name
)) {
1232 _talloc_set_name_const(tc
->name
, ".name");
1238 add a name to an existing pointer
1240 _PUBLIC_
const char *talloc_set_name(const void *ptr
, const char *fmt
, ...)
1245 name
= talloc_set_name_v(ptr
, fmt
, ap
);
1252 create a named talloc pointer. Any talloc pointer can be named, and
1253 talloc_named() operates just like talloc() except that it allows you
1254 to name the pointer.
1256 _PUBLIC_
void *talloc_named(const void *context
, size_t size
, const char *fmt
, ...)
1262 ptr
= __talloc(context
, size
);
1263 if (unlikely(ptr
== NULL
)) return NULL
;
1266 name
= talloc_set_name_v(ptr
, fmt
, ap
);
1269 if (unlikely(name
== NULL
)) {
1270 _talloc_free_internal(ptr
, __location__
);
1278 return the name of a talloc ptr, or "UNNAMED"
1280 _PUBLIC_
const char *talloc_get_name(const void *ptr
)
1282 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
1283 if (unlikely(tc
->name
== TALLOC_MAGIC_REFERENCE
)) {
1284 return ".reference";
1286 if (likely(tc
->name
)) {
1294 check if a pointer has the given name. If it does, return the pointer,
1295 otherwise return NULL
1297 _PUBLIC_
void *talloc_check_name(const void *ptr
, const char *name
)
1300 if (unlikely(ptr
== NULL
)) return NULL
;
1301 pname
= talloc_get_name(ptr
);
1302 if (likely(pname
== name
|| strcmp(pname
, name
) == 0)) {
1303 return discard_const_p(void, ptr
);
1308 static void talloc_abort_type_mismatch(const char *location
,
1310 const char *expected
)
1314 reason
= talloc_asprintf(NULL
,
1315 "%s: Type mismatch: name[%s] expected[%s]",
1320 reason
= "Type mismatch";
1323 talloc_abort(reason
);
1326 _PUBLIC_
void *_talloc_get_type_abort(const void *ptr
, const char *name
, const char *location
)
1330 if (unlikely(ptr
== NULL
)) {
1331 talloc_abort_type_mismatch(location
, NULL
, name
);
1335 pname
= talloc_get_name(ptr
);
1336 if (likely(pname
== name
|| strcmp(pname
, name
) == 0)) {
1337 return discard_const_p(void, ptr
);
1340 talloc_abort_type_mismatch(location
, pname
, name
);
1345 this is for compatibility with older versions of talloc
1347 _PUBLIC_
void *talloc_init(const char *fmt
, ...)
1353 ptr
= __talloc(NULL
, 0);
1354 if (unlikely(ptr
== NULL
)) return NULL
;
1357 name
= talloc_set_name_v(ptr
, fmt
, ap
);
1360 if (unlikely(name
== NULL
)) {
1361 _talloc_free_internal(ptr
, __location__
);
1368 static inline void _talloc_free_children_internal(struct talloc_chunk
*tc
,
1370 const char *location
)
1373 /* we need to work out who will own an abandoned child
1374 if it cannot be freed. In priority order, the first
1375 choice is owner of any remaining reference to this
1376 pointer, the second choice is our parent, and the
1377 final choice is the null context. */
1378 void *child
= TC_PTR_FROM_CHUNK(tc
->child
);
1379 const void *new_parent
= null_context
;
1380 if (unlikely(tc
->child
->refs
)) {
1381 struct talloc_chunk
*p
= talloc_parent_chunk(tc
->child
->refs
);
1382 if (p
) new_parent
= TC_PTR_FROM_CHUNK(p
);
1384 if (unlikely(_talloc_free_internal(child
, location
) == -1)) {
1385 if (new_parent
== null_context
) {
1386 struct talloc_chunk
*p
= talloc_parent_chunk(ptr
);
1387 if (p
) new_parent
= TC_PTR_FROM_CHUNK(p
);
1389 _talloc_steal_internal(new_parent
, child
);
1395 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1396 should probably not be used in new code. It's in here to keep the talloc
1397 code consistent across Samba 3 and 4.
1399 _PUBLIC_
void talloc_free_children(void *ptr
)
1401 struct talloc_chunk
*tc_name
= NULL
;
1402 struct talloc_chunk
*tc
;
1404 if (unlikely(ptr
== NULL
)) {
1408 tc
= talloc_chunk_from_ptr(ptr
);
1410 /* we do not want to free the context name if it is a child .. */
1411 if (likely(tc
->child
)) {
1412 for (tc_name
= tc
->child
; tc_name
; tc_name
= tc_name
->next
) {
1413 if (tc
->name
== TC_PTR_FROM_CHUNK(tc_name
)) break;
1416 _TLIST_REMOVE(tc
->child
, tc_name
);
1418 tc
->child
->parent
= tc
;
1423 _talloc_free_children_internal(tc
, ptr
, __location__
);
1425 /* .. so we put it back after all other children have been freed */
1428 tc
->child
->parent
= NULL
;
1430 tc_name
->parent
= tc
;
1431 _TLIST_ADD(tc
->child
, tc_name
);
1436 Allocate a bit of memory as a child of an existing pointer
1438 _PUBLIC_
void *_talloc(const void *context
, size_t size
)
1440 return __talloc(context
, size
);
1444 externally callable talloc_set_name_const()
1446 _PUBLIC_
void talloc_set_name_const(const void *ptr
, const char *name
)
1448 _talloc_set_name_const(ptr
, name
);
1452 create a named talloc pointer. Any talloc pointer can be named, and
1453 talloc_named() operates just like talloc() except that it allows you
1454 to name the pointer.
1456 _PUBLIC_
void *talloc_named_const(const void *context
, size_t size
, const char *name
)
1458 return _talloc_named_const(context
, size
, name
);
1462 free a talloc pointer. This also frees all child pointers of this
1465 return 0 if the memory is actually freed, otherwise -1. The memory
1466 will not be freed if the ref_count is > 1 or the destructor (if
1467 any) returns non-zero
1469 _PUBLIC_
int _talloc_free(void *ptr
, const char *location
)
1471 struct talloc_chunk
*tc
;
1473 if (unlikely(ptr
== NULL
)) {
1477 tc
= talloc_chunk_from_ptr(ptr
);
1479 if (unlikely(tc
->refs
!= NULL
)) {
1480 struct talloc_reference_handle
*h
;
1482 if (talloc_parent(ptr
) == null_context
&& tc
->refs
->next
== NULL
) {
1483 /* in this case we do know which parent should
1484 get this pointer, as there is really only
1486 return talloc_unlink(null_context
, ptr
);
1489 talloc_log("ERROR: talloc_free with references at %s\n",
1492 for (h
=tc
->refs
; h
; h
=h
->next
) {
1493 talloc_log("\treference at %s\n",
1499 return _talloc_free_internal(ptr
, location
);
1505 A talloc version of realloc. The context argument is only used if
1508 _PUBLIC_
void *_talloc_realloc(const void *context
, void *ptr
, size_t size
, const char *name
)
1510 struct talloc_chunk
*tc
;
1512 bool malloced
= false;
1513 struct talloc_pool_hdr
*pool_hdr
= NULL
;
1514 size_t old_size
= 0;
1515 size_t new_size
= 0;
1517 /* size zero is equivalent to free() */
1518 if (unlikely(size
== 0)) {
1519 talloc_unlink(context
, ptr
);
1523 if (unlikely(size
>= MAX_TALLOC_SIZE
)) {
1527 /* realloc(NULL) is equivalent to malloc() */
1529 return _talloc_named_const(context
, size
, name
);
1532 tc
= talloc_chunk_from_ptr(ptr
);
1534 /* don't allow realloc on referenced pointers */
1535 if (unlikely(tc
->refs
)) {
1539 /* don't let anybody try to realloc a talloc_pool */
1540 if (unlikely(tc
->flags
& TALLOC_FLAG_POOL
)) {
1544 if (tc
->limit
&& (size
> tc
->size
)) {
1545 if (!talloc_memlimit_check(tc
->limit
, (size
- tc
->size
))) {
1551 /* handle realloc inside a talloc_pool */
1552 if (unlikely(tc
->flags
& TALLOC_FLAG_POOLMEM
)) {
1553 pool_hdr
= tc
->pool
;
1556 #if (ALWAYS_REALLOC == 0)
1557 /* don't shrink if we have less than 1k to gain */
1558 if (size
< tc
->size
&& tc
->limit
== NULL
) {
1560 void *next_tc
= tc_next_chunk(tc
);
1561 TC_INVALIDATE_SHRINK_CHUNK(tc
, size
);
1563 if (next_tc
== pool_hdr
->end
) {
1564 /* note: tc->size has changed, so this works */
1565 pool_hdr
->end
= tc_next_chunk(tc
);
1568 } else if ((tc
->size
- size
) < 1024) {
1570 * if we call TC_INVALIDATE_SHRINK_CHUNK() here
1571 * we would need to call TC_UNDEFINE_GROW_CHUNK()
1572 * after each realloc call, which slows down
1573 * testing a lot :-(.
1575 * That is why we only mark memory as undefined here.
1577 TC_UNDEFINE_SHRINK_CHUNK(tc
, size
);
1579 /* do not shrink if we have less than 1k to gain */
1583 } else if (tc
->size
== size
) {
1585 * do not change the pointer if it is exactly
1592 /* by resetting magic we catch users of the old memory */
1593 tc
->flags
|= TALLOC_FLAG_FREE
;
1597 new_ptr
= talloc_alloc_pool(tc
, size
+ TC_HDR_SIZE
, 0);
1598 pool_hdr
->object_count
--;
1600 if (new_ptr
== NULL
) {
1601 new_ptr
= malloc(TC_HDR_SIZE
+size
);
1607 memcpy(new_ptr
, tc
, MIN(tc
->size
,size
) + TC_HDR_SIZE
);
1608 TC_INVALIDATE_FULL_CHUNK(tc
);
1611 /* We're doing malloc then free here, so record the difference. */
1612 old_size
= tc
->size
;
1614 new_ptr
= malloc(size
+ TC_HDR_SIZE
);
1616 memcpy(new_ptr
, tc
, MIN(tc
->size
, size
) + TC_HDR_SIZE
);
1622 struct talloc_chunk
*pool_tc
;
1623 void *next_tc
= tc_next_chunk(tc
);
1624 size_t old_chunk_size
= TC_ALIGN16(TC_HDR_SIZE
+ tc
->size
);
1625 size_t new_chunk_size
= TC_ALIGN16(TC_HDR_SIZE
+ size
);
1626 size_t space_needed
;
1628 unsigned int chunk_count
= pool_hdr
->object_count
;
1630 pool_tc
= talloc_chunk_from_pool(pool_hdr
);
1631 if (!(pool_tc
->flags
& TALLOC_FLAG_FREE
)) {
1635 if (chunk_count
== 1) {
1637 * optimize for the case where 'tc' is the only
1638 * chunk in the pool.
1640 char *start
= tc_pool_first_chunk(pool_hdr
);
1641 space_needed
= new_chunk_size
;
1642 space_left
= (char *)tc_pool_end(pool_hdr
) - start
;
1644 if (space_left
>= space_needed
) {
1645 size_t old_used
= TC_HDR_SIZE
+ tc
->size
;
1646 size_t new_used
= TC_HDR_SIZE
+ size
;
1649 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
1653 * start -> tc may have
1654 * been freed and thus been marked as
1655 * VALGRIND_MEM_NOACCESS. Set it to
1656 * VALGRIND_MEM_UNDEFINED so we can
1657 * copy into it without valgrind errors.
1658 * We can't just mark
1659 * new_ptr -> new_ptr + old_used
1660 * as this may overlap on top of tc,
1661 * (which is why we use memmove, not
1662 * memcpy below) hence the MIN.
1664 size_t undef_len
= MIN((((char *)tc
) - ((char *)new_ptr
)),old_used
);
1665 VALGRIND_MAKE_MEM_UNDEFINED(new_ptr
, undef_len
);
1669 memmove(new_ptr
, tc
, old_used
);
1671 tc
= (struct talloc_chunk
*)new_ptr
;
1672 TC_UNDEFINE_GROW_CHUNK(tc
, size
);
1675 * first we do not align the pool pointer
1676 * because we want to invalidate the padding
1679 pool_hdr
->end
= new_used
+ (char *)new_ptr
;
1680 tc_invalidate_pool(pool_hdr
);
1682 /* now the aligned pointer */
1683 pool_hdr
->end
= new_chunk_size
+ (char *)new_ptr
;
1690 if (new_chunk_size
== old_chunk_size
) {
1691 TC_UNDEFINE_GROW_CHUNK(tc
, size
);
1692 tc
->flags
&= ~TALLOC_FLAG_FREE
;
1697 if (next_tc
== pool_hdr
->end
) {
1699 * optimize for the case where 'tc' is the last
1700 * chunk in the pool.
1702 space_needed
= new_chunk_size
- old_chunk_size
;
1703 space_left
= tc_pool_space_left(pool_hdr
);
1705 if (space_left
>= space_needed
) {
1706 TC_UNDEFINE_GROW_CHUNK(tc
, size
);
1707 tc
->flags
&= ~TALLOC_FLAG_FREE
;
1709 pool_hdr
->end
= tc_next_chunk(tc
);
1714 new_ptr
= talloc_alloc_pool(tc
, size
+ TC_HDR_SIZE
, 0);
1716 if (new_ptr
== NULL
) {
1717 new_ptr
= malloc(TC_HDR_SIZE
+size
);
1723 memcpy(new_ptr
, tc
, MIN(tc
->size
,size
) + TC_HDR_SIZE
);
1725 _talloc_free_poolmem(tc
, __location__
"_talloc_realloc");
1729 /* We're doing realloc here, so record the difference. */
1730 old_size
= tc
->size
;
1732 new_ptr
= realloc(tc
, size
+ TC_HDR_SIZE
);
1736 if (unlikely(!new_ptr
)) {
1737 tc
->flags
&= ~TALLOC_FLAG_FREE
;
1741 tc
= (struct talloc_chunk
*)new_ptr
;
1742 tc
->flags
&= ~TALLOC_FLAG_FREE
;
1744 tc
->flags
&= ~TALLOC_FLAG_POOLMEM
;
1747 tc
->parent
->child
= tc
;
1750 tc
->child
->parent
= tc
;
1754 tc
->prev
->next
= tc
;
1757 tc
->next
->prev
= tc
;
1760 if (new_size
> old_size
) {
1761 talloc_memlimit_grow(tc
->limit
, new_size
- old_size
);
1762 } else if (new_size
< old_size
) {
1763 talloc_memlimit_shrink(tc
->limit
, old_size
- new_size
);
1767 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc
), name
);
1769 return TC_PTR_FROM_CHUNK(tc
);
1773 a wrapper around talloc_steal() for situations where you are moving a pointer
1774 between two structures, and want the old pointer to be set to NULL
1776 _PUBLIC_
void *_talloc_move(const void *new_ctx
, const void *_pptr
)
1778 const void **pptr
= discard_const_p(const void *,_pptr
);
1779 void *ret
= talloc_steal(new_ctx
, discard_const_p(void, *pptr
));
1784 enum talloc_mem_count_type
{
1790 static size_t _talloc_total_mem_internal(const void *ptr
,
1791 enum talloc_mem_count_type type
,
1792 struct talloc_memlimit
*old_limit
,
1793 struct talloc_memlimit
*new_limit
)
1796 struct talloc_chunk
*c
, *tc
;
1805 tc
= talloc_chunk_from_ptr(ptr
);
1807 if (old_limit
|| new_limit
) {
1808 if (tc
->limit
&& tc
->limit
->upper
== old_limit
) {
1809 tc
->limit
->upper
= new_limit
;
1813 /* optimize in the memlimits case */
1814 if (type
== TOTAL_MEM_LIMIT
&&
1815 tc
->limit
!= NULL
&&
1816 tc
->limit
!= old_limit
&&
1817 tc
->limit
->parent
== tc
) {
1818 return tc
->limit
->cur_size
;
1821 if (tc
->flags
& TALLOC_FLAG_LOOP
) {
1825 tc
->flags
|= TALLOC_FLAG_LOOP
;
1827 if (old_limit
|| new_limit
) {
1828 if (old_limit
== tc
->limit
) {
1829 tc
->limit
= new_limit
;
1834 case TOTAL_MEM_SIZE
:
1835 if (likely(tc
->name
!= TALLOC_MAGIC_REFERENCE
)) {
1839 case TOTAL_MEM_BLOCKS
:
1842 case TOTAL_MEM_LIMIT
:
1843 if (likely(tc
->name
!= TALLOC_MAGIC_REFERENCE
)) {
1845 * Don't count memory allocated from a pool
1846 * when calculating limits. Only count the
1849 if (!(tc
->flags
& TALLOC_FLAG_POOLMEM
)) {
1850 total
= tc
->size
+ TC_HDR_SIZE
;
1852 * If this is a pool, remember to
1853 * add the prefix length.
1855 if (tc
->flags
& TALLOC_FLAG_POOL
) {
1856 total
+= TP_HDR_SIZE
;
1862 for (c
= tc
->child
; c
; c
= c
->next
) {
1863 total
+= _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c
), type
,
1864 old_limit
, new_limit
);
1867 tc
->flags
&= ~TALLOC_FLAG_LOOP
;
1873 return the total size of a talloc pool (subtree)
1875 _PUBLIC_
size_t talloc_total_size(const void *ptr
)
1877 return _talloc_total_mem_internal(ptr
, TOTAL_MEM_SIZE
, NULL
, NULL
);
1881 return the total number of blocks in a talloc pool (subtree)
1883 _PUBLIC_
size_t talloc_total_blocks(const void *ptr
)
1885 return _talloc_total_mem_internal(ptr
, TOTAL_MEM_BLOCKS
, NULL
, NULL
);
1889 return the number of external references to a pointer
1891 _PUBLIC_
size_t talloc_reference_count(const void *ptr
)
1893 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ptr
);
1894 struct talloc_reference_handle
*h
;
1897 for (h
=tc
->refs
;h
;h
=h
->next
) {
1904 report on memory usage by all children of a pointer, giving a full tree view
1906 _PUBLIC_
void talloc_report_depth_cb(const void *ptr
, int depth
, int max_depth
,
1907 void (*callback
)(const void *ptr
,
1908 int depth
, int max_depth
,
1910 void *private_data
),
1913 struct talloc_chunk
*c
, *tc
;
1918 if (ptr
== NULL
) return;
1920 tc
= talloc_chunk_from_ptr(ptr
);
1922 if (tc
->flags
& TALLOC_FLAG_LOOP
) {
1926 callback(ptr
, depth
, max_depth
, 0, private_data
);
1928 if (max_depth
>= 0 && depth
>= max_depth
) {
1932 tc
->flags
|= TALLOC_FLAG_LOOP
;
1933 for (c
=tc
->child
;c
;c
=c
->next
) {
1934 if (c
->name
== TALLOC_MAGIC_REFERENCE
) {
1935 struct talloc_reference_handle
*h
= (struct talloc_reference_handle
*)TC_PTR_FROM_CHUNK(c
);
1936 callback(h
->ptr
, depth
+ 1, max_depth
, 1, private_data
);
1938 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c
), depth
+ 1, max_depth
, callback
, private_data
);
1941 tc
->flags
&= ~TALLOC_FLAG_LOOP
;
1944 static void talloc_report_depth_FILE_helper(const void *ptr
, int depth
, int max_depth
, int is_ref
, void *_f
)
1946 const char *name
= talloc_get_name(ptr
);
1947 struct talloc_chunk
*tc
;
1948 FILE *f
= (FILE *)_f
;
1951 fprintf(f
, "%*sreference to: %s\n", depth
*4, "", name
);
1955 tc
= talloc_chunk_from_ptr(ptr
);
1956 if (tc
->limit
&& tc
->limit
->parent
== tc
) {
1957 fprintf(f
, "%*s%-30s is a memlimit context"
1958 " (max_size = %lu bytes, cur_size = %lu bytes)\n",
1961 (unsigned long)tc
->limit
->max_size
,
1962 (unsigned long)tc
->limit
->cur_size
);
1966 fprintf(f
,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1967 (max_depth
< 0 ? "full " :""), name
,
1968 (unsigned long)talloc_total_size(ptr
),
1969 (unsigned long)talloc_total_blocks(ptr
));
1973 fprintf(f
, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1976 (unsigned long)talloc_total_size(ptr
),
1977 (unsigned long)talloc_total_blocks(ptr
),
1978 (int)talloc_reference_count(ptr
), ptr
);
1981 fprintf(f
, "content: ");
1982 if (talloc_total_size(ptr
)) {
1983 int tot
= talloc_total_size(ptr
);
1986 for (i
= 0; i
< tot
; i
++) {
1987 if ((((char *)ptr
)[i
] > 31) && (((char *)ptr
)[i
] < 126)) {
1988 fprintf(f
, "%c", ((char *)ptr
)[i
]);
1990 fprintf(f
, "~%02x", ((char *)ptr
)[i
]);
1999 report on memory usage by all children of a pointer, giving a full tree view
2001 _PUBLIC_
void talloc_report_depth_file(const void *ptr
, int depth
, int max_depth
, FILE *f
)
2004 talloc_report_depth_cb(ptr
, depth
, max_depth
, talloc_report_depth_FILE_helper
, f
);
2010 report on memory usage by all children of a pointer, giving a full tree view
2012 _PUBLIC_
void talloc_report_full(const void *ptr
, FILE *f
)
2014 talloc_report_depth_file(ptr
, 0, -1, f
);
2018 report on memory usage by all children of a pointer
2020 _PUBLIC_
void talloc_report(const void *ptr
, FILE *f
)
2022 talloc_report_depth_file(ptr
, 0, 1, f
);
2026 report on any memory hanging off the null context
2028 static void talloc_report_null(void)
2030 if (talloc_total_size(null_context
) != 0) {
2031 talloc_report(null_context
, stderr
);
2036 report on any memory hanging off the null context
2038 static void talloc_report_null_full(void)
2040 if (talloc_total_size(null_context
) != 0) {
2041 talloc_report_full(null_context
, stderr
);
2046 enable tracking of the NULL context
2048 _PUBLIC_
void talloc_enable_null_tracking(void)
2050 if (null_context
== NULL
) {
2051 null_context
= _talloc_named_const(NULL
, 0, "null_context");
2052 if (autofree_context
!= NULL
) {
2053 talloc_reparent(NULL
, null_context
, autofree_context
);
2059 enable tracking of the NULL context, not moving the autofree context
2060 into the NULL context. This is needed for the talloc testsuite
2062 _PUBLIC_
void talloc_enable_null_tracking_no_autofree(void)
2064 if (null_context
== NULL
) {
2065 null_context
= _talloc_named_const(NULL
, 0, "null_context");
2070 disable tracking of the NULL context
2072 _PUBLIC_
void talloc_disable_null_tracking(void)
2074 if (null_context
!= NULL
) {
2075 /* we have to move any children onto the real NULL
2077 struct talloc_chunk
*tc
, *tc2
;
2078 tc
= talloc_chunk_from_ptr(null_context
);
2079 for (tc2
= tc
->child
; tc2
; tc2
=tc2
->next
) {
2080 if (tc2
->parent
== tc
) tc2
->parent
= NULL
;
2081 if (tc2
->prev
== tc
) tc2
->prev
= NULL
;
2083 for (tc2
= tc
->next
; tc2
; tc2
=tc2
->next
) {
2084 if (tc2
->parent
== tc
) tc2
->parent
= NULL
;
2085 if (tc2
->prev
== tc
) tc2
->prev
= NULL
;
2090 talloc_free(null_context
);
2091 null_context
= NULL
;
2095 enable leak reporting on exit
2097 _PUBLIC_
void talloc_enable_leak_report(void)
2099 talloc_enable_null_tracking();
2100 atexit(talloc_report_null
);
2104 enable full leak reporting on exit
2106 _PUBLIC_
void talloc_enable_leak_report_full(void)
2108 talloc_enable_null_tracking();
2109 atexit(talloc_report_null_full
);
2113 talloc and zero memory.
2115 _PUBLIC_
void *_talloc_zero(const void *ctx
, size_t size
, const char *name
)
2117 void *p
= _talloc_named_const(ctx
, size
, name
);
2120 memset(p
, '\0', size
);
2127 memdup with a talloc.
2129 _PUBLIC_
void *_talloc_memdup(const void *t
, const void *p
, size_t size
, const char *name
)
2131 void *newp
= _talloc_named_const(t
, size
, name
);
2134 memcpy(newp
, p
, size
);
2140 static inline char *__talloc_strlendup(const void *t
, const char *p
, size_t len
)
2144 ret
= (char *)__talloc(t
, len
+ 1);
2145 if (unlikely(!ret
)) return NULL
;
2147 memcpy(ret
, p
, len
);
2150 _talloc_set_name_const(ret
, ret
);
2155 strdup with a talloc
2157 _PUBLIC_
char *talloc_strdup(const void *t
, const char *p
)
2159 if (unlikely(!p
)) return NULL
;
2160 return __talloc_strlendup(t
, p
, strlen(p
));
2164 strndup with a talloc
2166 _PUBLIC_
char *talloc_strndup(const void *t
, const char *p
, size_t n
)
2168 if (unlikely(!p
)) return NULL
;
2169 return __talloc_strlendup(t
, p
, strnlen(p
, n
));
2172 static inline char *__talloc_strlendup_append(char *s
, size_t slen
,
2173 const char *a
, size_t alen
)
2177 ret
= talloc_realloc(NULL
, s
, char, slen
+ alen
+ 1);
2178 if (unlikely(!ret
)) return NULL
;
2180 /* append the string and the trailing \0 */
2181 memcpy(&ret
[slen
], a
, alen
);
2184 _talloc_set_name_const(ret
, ret
);
2189 * Appends at the end of the string.
2191 _PUBLIC_
char *talloc_strdup_append(char *s
, const char *a
)
2194 return talloc_strdup(NULL
, a
);
2201 return __talloc_strlendup_append(s
, strlen(s
), a
, strlen(a
));
2205 * Appends at the end of the talloc'ed buffer,
2206 * not the end of the string.
2208 _PUBLIC_
char *talloc_strdup_append_buffer(char *s
, const char *a
)
2213 return talloc_strdup(NULL
, a
);
2220 slen
= talloc_get_size(s
);
2221 if (likely(slen
> 0)) {
2225 return __talloc_strlendup_append(s
, slen
, a
, strlen(a
));
2229 * Appends at the end of the string.
2231 _PUBLIC_
char *talloc_strndup_append(char *s
, const char *a
, size_t n
)
2234 return talloc_strndup(NULL
, a
, n
);
2241 return __talloc_strlendup_append(s
, strlen(s
), a
, strnlen(a
, n
));
2245 * Appends at the end of the talloc'ed buffer,
2246 * not the end of the string.
2248 _PUBLIC_
char *talloc_strndup_append_buffer(char *s
, const char *a
, size_t n
)
2253 return talloc_strndup(NULL
, a
, n
);
2260 slen
= talloc_get_size(s
);
2261 if (likely(slen
> 0)) {
2265 return __talloc_strlendup_append(s
, slen
, a
, strnlen(a
, n
));
2268 #ifndef HAVE_VA_COPY
2269 #ifdef HAVE___VA_COPY
2270 #define va_copy(dest, src) __va_copy(dest, src)
2272 #define va_copy(dest, src) (dest) = (src)
2276 _PUBLIC_
char *talloc_vasprintf(const void *t
, const char *fmt
, va_list ap
)
2283 /* this call looks strange, but it makes it work on older solaris boxes */
2285 len
= vsnprintf(&c
, 1, fmt
, ap2
);
2287 if (unlikely(len
< 0)) {
2291 ret
= (char *)__talloc(t
, len
+1);
2292 if (unlikely(!ret
)) return NULL
;
2295 vsnprintf(ret
, len
+1, fmt
, ap2
);
2298 _talloc_set_name_const(ret
, ret
);
2304 Perform string formatting, and return a pointer to newly allocated
2305 memory holding the result, inside a memory pool.
2307 _PUBLIC_
char *talloc_asprintf(const void *t
, const char *fmt
, ...)
2313 ret
= talloc_vasprintf(t
, fmt
, ap
);
2318 static inline char *__talloc_vaslenprintf_append(char *s
, size_t slen
,
2319 const char *fmt
, va_list ap
)
2320 PRINTF_ATTRIBUTE(3,0);
2322 static inline char *__talloc_vaslenprintf_append(char *s
, size_t slen
,
2323 const char *fmt
, va_list ap
)
2330 alen
= vsnprintf(&c
, 1, fmt
, ap2
);
2334 /* Either the vsnprintf failed or the format resulted in
2335 * no characters being formatted. In the former case, we
2336 * ought to return NULL, in the latter we ought to return
2337 * the original string. Most current callers of this
2338 * function expect it to never return NULL.
2343 s
= talloc_realloc(NULL
, s
, char, slen
+ alen
+ 1);
2344 if (!s
) return NULL
;
2347 vsnprintf(s
+ slen
, alen
+ 1, fmt
, ap2
);
2350 _talloc_set_name_const(s
, s
);
2355 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2356 * and return @p s, which may have moved. Good for gradually
2357 * accumulating output into a string buffer. Appends at the end
2360 _PUBLIC_
char *talloc_vasprintf_append(char *s
, const char *fmt
, va_list ap
)
2363 return talloc_vasprintf(NULL
, fmt
, ap
);
2366 return __talloc_vaslenprintf_append(s
, strlen(s
), fmt
, ap
);
2370 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2371 * and return @p s, which may have moved. Always appends at the
2372 * end of the talloc'ed buffer, not the end of the string.
2374 _PUBLIC_
char *talloc_vasprintf_append_buffer(char *s
, const char *fmt
, va_list ap
)
2379 return talloc_vasprintf(NULL
, fmt
, ap
);
2382 slen
= talloc_get_size(s
);
2383 if (likely(slen
> 0)) {
2387 return __talloc_vaslenprintf_append(s
, slen
, fmt
, ap
);
2391 Realloc @p s to append the formatted result of @p fmt and return @p
2392 s, which may have moved. Good for gradually accumulating output
2393 into a string buffer.
2395 _PUBLIC_
char *talloc_asprintf_append(char *s
, const char *fmt
, ...)
2400 s
= talloc_vasprintf_append(s
, fmt
, ap
);
2406 Realloc @p s to append the formatted result of @p fmt and return @p
2407 s, which may have moved. Good for gradually accumulating output
2410 _PUBLIC_
char *talloc_asprintf_append_buffer(char *s
, const char *fmt
, ...)
2415 s
= talloc_vasprintf_append_buffer(s
, fmt
, ap
);
2421 alloc an array, checking for integer overflow in the array size
2423 _PUBLIC_
void *_talloc_array(const void *ctx
, size_t el_size
, unsigned count
, const char *name
)
2425 if (count
>= MAX_TALLOC_SIZE
/el_size
) {
2428 return _talloc_named_const(ctx
, el_size
* count
, name
);
2432 alloc an zero array, checking for integer overflow in the array size
2434 _PUBLIC_
void *_talloc_zero_array(const void *ctx
, size_t el_size
, unsigned count
, const char *name
)
2436 if (count
>= MAX_TALLOC_SIZE
/el_size
) {
2439 return _talloc_zero(ctx
, el_size
* count
, name
);
2443 realloc an array, checking for integer overflow in the array size
2445 _PUBLIC_
void *_talloc_realloc_array(const void *ctx
, void *ptr
, size_t el_size
, unsigned count
, const char *name
)
2447 if (count
>= MAX_TALLOC_SIZE
/el_size
) {
2450 return _talloc_realloc(ctx
, ptr
, el_size
* count
, name
);
2454 a function version of talloc_realloc(), so it can be passed as a function pointer
2455 to libraries that want a realloc function (a realloc function encapsulates
2456 all the basic capabilities of an allocation library, which is why this is useful)
2458 _PUBLIC_
void *talloc_realloc_fn(const void *context
, void *ptr
, size_t size
)
2460 return _talloc_realloc(context
, ptr
, size
, NULL
);
2464 static int talloc_autofree_destructor(void *ptr
)
2466 autofree_context
= NULL
;
2470 static void talloc_autofree(void)
2472 talloc_free(autofree_context
);
2476 return a context which will be auto-freed on exit
2477 this is useful for reducing the noise in leak reports
2479 _PUBLIC_
void *talloc_autofree_context(void)
2481 if (autofree_context
== NULL
) {
2482 autofree_context
= _talloc_named_const(NULL
, 0, "autofree_context");
2483 talloc_set_destructor(autofree_context
, talloc_autofree_destructor
);
2484 atexit(talloc_autofree
);
2486 return autofree_context
;
2489 _PUBLIC_
size_t talloc_get_size(const void *context
)
2491 struct talloc_chunk
*tc
;
2493 if (context
== NULL
) {
2494 context
= null_context
;
2496 if (context
== NULL
) {
2500 tc
= talloc_chunk_from_ptr(context
);
2506 find a parent of this context that has the given name, if any
2508 _PUBLIC_
void *talloc_find_parent_byname(const void *context
, const char *name
)
2510 struct talloc_chunk
*tc
;
2512 if (context
== NULL
) {
2516 tc
= talloc_chunk_from_ptr(context
);
2518 if (tc
->name
&& strcmp(tc
->name
, name
) == 0) {
2519 return TC_PTR_FROM_CHUNK(tc
);
2521 while (tc
&& tc
->prev
) tc
= tc
->prev
;
2530 show the parentage of a context
2532 _PUBLIC_
void talloc_show_parents(const void *context
, FILE *file
)
2534 struct talloc_chunk
*tc
;
2536 if (context
== NULL
) {
2537 fprintf(file
, "talloc no parents for NULL\n");
2541 tc
= talloc_chunk_from_ptr(context
);
2542 fprintf(file
, "talloc parents of '%s'\n", talloc_get_name(context
));
2544 fprintf(file
, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc
)));
2545 while (tc
&& tc
->prev
) tc
= tc
->prev
;
2554 return 1 if ptr is a parent of context
2556 static int _talloc_is_parent(const void *context
, const void *ptr
, int depth
)
2558 struct talloc_chunk
*tc
;
2560 if (context
== NULL
) {
2564 tc
= talloc_chunk_from_ptr(context
);
2565 while (tc
&& depth
> 0) {
2566 if (TC_PTR_FROM_CHUNK(tc
) == ptr
) return 1;
2567 while (tc
&& tc
->prev
) tc
= tc
->prev
;
2577 return 1 if ptr is a parent of context
2579 _PUBLIC_
int talloc_is_parent(const void *context
, const void *ptr
)
2581 return _talloc_is_parent(context
, ptr
, TALLOC_MAX_DEPTH
);
2585 return the total size of memory used by this context and all children
2587 static size_t _talloc_total_limit_size(const void *ptr
,
2588 struct talloc_memlimit
*old_limit
,
2589 struct talloc_memlimit
*new_limit
)
2591 return _talloc_total_mem_internal(ptr
, TOTAL_MEM_LIMIT
,
2592 old_limit
, new_limit
);
2595 static bool talloc_memlimit_check(struct talloc_memlimit
*limit
, size_t size
)
2597 struct talloc_memlimit
*l
;
2599 for (l
= limit
; l
!= NULL
; l
= l
->upper
) {
2600 if (l
->max_size
!= 0 &&
2601 ((l
->max_size
<= l
->cur_size
) ||
2602 (l
->max_size
- l
->cur_size
< size
))) {
2611 Update memory limits when freeing a talloc_chunk.
2613 static void talloc_memlimit_update_on_free(struct talloc_chunk
*tc
)
2615 size_t limit_shrink_size
;
2622 * Pool entries don't count. Only the pools
2623 * themselves are counted as part of the memory
2626 if (tc
->flags
& TALLOC_FLAG_POOLMEM
) {
2631 * If we are part of a memory limited context hierarchy
2632 * we need to subtract the memory used from the counters
2635 limit_shrink_size
= tc
->size
+TC_HDR_SIZE
;
2638 * If we're deallocating a pool, take into
2639 * account the prefix size added for the pool.
2642 if (tc
->flags
& TALLOC_FLAG_POOL
) {
2643 limit_shrink_size
+= TP_HDR_SIZE
;
2646 talloc_memlimit_shrink(tc
->limit
, limit_shrink_size
);
2648 if (tc
->limit
->parent
== tc
) {
2656 Increase memory limit accounting after a malloc/realloc.
2658 static void talloc_memlimit_grow(struct talloc_memlimit
*limit
,
2661 struct talloc_memlimit
*l
;
2663 for (l
= limit
; l
!= NULL
; l
= l
->upper
) {
2664 size_t new_cur_size
= l
->cur_size
+ size
;
2665 if (new_cur_size
< l
->cur_size
) {
2666 talloc_abort("logic error in talloc_memlimit_grow\n");
2669 l
->cur_size
= new_cur_size
;
2674 Decrease memory limit accounting after a free/realloc.
2676 static void talloc_memlimit_shrink(struct talloc_memlimit
*limit
,
2679 struct talloc_memlimit
*l
;
2681 for (l
= limit
; l
!= NULL
; l
= l
->upper
) {
2682 if (l
->cur_size
< size
) {
2683 talloc_abort("logic error in talloc_memlimit_shrink\n");
2686 l
->cur_size
= l
->cur_size
- size
;
2690 _PUBLIC_
int talloc_set_memlimit(const void *ctx
, size_t max_size
)
2692 struct talloc_chunk
*tc
= talloc_chunk_from_ptr(ctx
);
2693 struct talloc_memlimit
*orig_limit
;
2694 struct talloc_memlimit
*limit
= NULL
;
2696 if (tc
->limit
&& tc
->limit
->parent
== tc
) {
2697 tc
->limit
->max_size
= max_size
;
2700 orig_limit
= tc
->limit
;
2702 limit
= malloc(sizeof(struct talloc_memlimit
));
2703 if (limit
== NULL
) {
2707 limit
->max_size
= max_size
;
2708 limit
->cur_size
= _talloc_total_limit_size(ctx
, tc
->limit
, limit
);
2711 limit
->upper
= orig_limit
;
2713 limit
->upper
= NULL
;