Don't call talloc_memlimit_update() inside _talloc_realloc() when we're just manipula...
[Samba.git] / lib / talloc / talloc.c
blobaabd2fb762750337e3049688917d68bfa033a7ad
1 /*
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
13 ** under the LGPL
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/
33 #include "replace.h"
34 #include "talloc.h"
36 #ifdef TALLOC_BUILD_VERSION_MAJOR
37 #if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR)
38 #error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR"
39 #endif
40 #endif
42 #ifdef TALLOC_BUILD_VERSION_MINOR
43 #if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR)
44 #error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR"
45 #endif
46 #endif
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)
54 #include <valgrind.h>
55 #endif
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 ( \
65 TALLOC_MAGIC_BASE + \
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() */
79 #ifndef TALLOC_ABORT
80 #define TALLOC_ABORT(reason) abort()
81 #endif
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)))
86 #else
87 # define discard_const_p(type, ptr) ((type *)(ptr))
88 #endif
89 #endif
91 /* these macros gain us a few percent of speed on gcc */
92 #if (__GNUC__ >= 3)
93 /* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
94 as its first argument */
95 #ifndef likely
96 #define likely(x) __builtin_expect(!!(x), 1)
97 #endif
98 #ifndef unlikely
99 #define unlikely(x) __builtin_expect(!!(x), 0)
100 #endif
101 #else
102 #ifndef likely
103 #define likely(x) (x)
104 #endif
105 #ifndef unlikely
106 #define unlikely(x) (x)
107 #endif
108 #endif
110 /* this null_context is only used if talloc_enable_leak_report() or
111 talloc_enable_leak_report_full() is called, otherwise it remains
112 NULL
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
120 static struct {
121 bool initialised;
122 bool enabled;
123 uint8_t fill_value;
124 } talloc_fill;
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); \
138 } while (0)
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); \
146 } while(0)
147 #else
148 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0)
149 #endif
151 #define TC_INVALIDATE_FULL_CHUNK(_tc) do { \
152 TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \
153 TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \
154 } while (0)
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); \
163 } while (0)
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); \
172 } while (0)
173 #else
174 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
175 #endif
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); \
180 } while (0)
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); \
189 } while (0)
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); \
198 } while (0)
199 #else
200 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
201 #endif
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); \
206 } while (0)
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); \
216 } while (0)
217 #else
218 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
219 #endif
221 #define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \
222 TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \
223 } while (0)
225 struct talloc_reference_handle {
226 struct talloc_reference_handle *next, *prev;
227 void *ptr;
228 const char *location;
231 struct talloc_memlimit {
232 struct talloc_chunk *parent;
233 struct talloc_memlimit *upper;
234 size_t max_size;
235 size_t cur_size;
238 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size);
239 static bool talloc_memlimit_update(struct talloc_memlimit *limit,
240 size_t old_size, size_t new_size);
241 static void talloc_memlimit_grow(struct talloc_memlimit *limit,
242 size_t size);
243 static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
244 size_t size);
245 static void talloc_memlimit_update_on_free(struct talloc_chunk *tc);
247 typedef int (*talloc_destructor_t)(void *);
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;
254 const char *name;
255 size_t size;
256 unsigned flags;
259 * limit semantics:
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
262 * allocations.
263 * cur_size is used to keep track of the current use
265 struct talloc_memlimit *limit;
268 * "pool" has dual use:
270 * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
271 * marks the end of the currently allocated area.
273 * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
274 * is a pointer to the struct talloc_chunk of the pool that it was
275 * allocated from. This way children can quickly find the pool to chew
276 * from.
278 void *pool;
281 /* 16 byte alignment seems to keep everyone happy */
282 #define TC_ALIGN16(s) (((s)+15)&~15)
283 #define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
284 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
286 _PUBLIC_ int talloc_version_major(void)
288 return TALLOC_VERSION_MAJOR;
291 _PUBLIC_ int talloc_version_minor(void)
293 return TALLOC_VERSION_MINOR;
296 static void (*talloc_log_fn)(const char *message);
298 _PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
300 talloc_log_fn = log_fn;
303 static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
304 static void talloc_log(const char *fmt, ...)
306 va_list ap;
307 char *message;
309 if (!talloc_log_fn) {
310 return;
313 va_start(ap, fmt);
314 message = talloc_vasprintf(NULL, fmt, ap);
315 va_end(ap);
317 talloc_log_fn(message);
318 talloc_free(message);
321 static void talloc_log_stderr(const char *message)
323 fprintf(stderr, "%s", message);
326 _PUBLIC_ void talloc_set_log_stderr(void)
328 talloc_set_log_fn(talloc_log_stderr);
331 static void (*talloc_abort_fn)(const char *reason);
333 _PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
335 talloc_abort_fn = abort_fn;
338 static void talloc_abort(const char *reason)
340 talloc_log("%s\n", reason);
342 if (!talloc_abort_fn) {
343 TALLOC_ABORT(reason);
346 talloc_abort_fn(reason);
349 static void talloc_abort_magic(unsigned magic)
351 unsigned striped = magic - TALLOC_MAGIC_BASE;
352 unsigned major = (striped & 0xFFFFF000) >> 12;
353 unsigned minor = (striped & 0x00000FF0) >> 4;
354 talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
355 magic, major, minor,
356 TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR);
357 talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
360 static void talloc_abort_access_after_free(void)
362 talloc_abort("Bad talloc magic value - access after free");
365 static void talloc_abort_unknown_value(void)
367 talloc_abort("Bad talloc magic value - unknown value");
370 /* panic if we get a bad magic value */
371 static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
373 const char *pp = (const char *)ptr;
374 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
375 if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
376 if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) {
377 talloc_abort_magic(tc->flags & (~0xF));
378 return NULL;
381 if (tc->flags & TALLOC_FLAG_FREE) {
382 talloc_log("talloc: access after free error - first free may be at %s\n", tc->name);
383 talloc_abort_access_after_free();
384 return NULL;
385 } else {
386 talloc_abort_unknown_value();
387 return NULL;
390 return tc;
393 /* hook into the front of the list */
394 #define _TLIST_ADD(list, p) \
395 do { \
396 if (!(list)) { \
397 (list) = (p); \
398 (p)->next = (p)->prev = NULL; \
399 } else { \
400 (list)->prev = (p); \
401 (p)->next = (list); \
402 (p)->prev = NULL; \
403 (list) = (p); \
405 } while (0)
407 /* remove an element from a list - element doesn't have to be in list. */
408 #define _TLIST_REMOVE(list, p) \
409 do { \
410 if ((p) == (list)) { \
411 (list) = (p)->next; \
412 if (list) (list)->prev = NULL; \
413 } else { \
414 if ((p)->prev) (p)->prev->next = (p)->next; \
415 if ((p)->next) (p)->next->prev = (p)->prev; \
417 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
418 } while (0)
422 return the parent chunk of a pointer
424 static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
426 struct talloc_chunk *tc;
428 if (unlikely(ptr == NULL)) {
429 return NULL;
432 tc = talloc_chunk_from_ptr(ptr);
433 while (tc->prev) tc=tc->prev;
435 return tc->parent;
438 _PUBLIC_ void *talloc_parent(const void *ptr)
440 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
441 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
445 find parents name
447 _PUBLIC_ const char *talloc_parent_name(const void *ptr)
449 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
450 return tc? tc->name : NULL;
454 A pool carries an in-pool object count count in the first 16 bytes.
455 bytes. This is done to support talloc_steal() to a parent outside of the
456 pool. The count includes the pool itself, so a talloc_free() on a pool will
457 only destroy the pool if the count has dropped to zero. A talloc_free() of a
458 pool member will reduce the count, and eventually also call free(3) on the
459 pool memory.
461 The object count is not put into "struct talloc_chunk" because it is only
462 relevant for talloc pools and the alignment to 16 bytes would increase the
463 memory footprint of each talloc chunk by those 16 bytes.
466 union talloc_pool_chunk {
467 /* This lets object_count nestle into 16-byte padding of talloc_chunk,
468 * on 32-bit platforms. */
469 struct tc_pool_hdr {
470 struct talloc_chunk c;
471 unsigned int object_count;
472 } hdr;
473 /* This makes it always 16 byte aligned. */
474 char pad[TC_ALIGN16(sizeof(struct tc_pool_hdr))];
477 static void *tc_pool_end(union talloc_pool_chunk *pool_tc)
479 return (char *)pool_tc + TC_HDR_SIZE + pool_tc->hdr.c.size;
482 static size_t tc_pool_space_left(union talloc_pool_chunk *pool_tc)
484 return (char *)tc_pool_end(pool_tc) - (char *)pool_tc->hdr.c.pool;
487 static void *tc_pool_first_chunk(union talloc_pool_chunk *pool_tc)
489 return pool_tc + 1;
492 /* If tc is inside a pool, this gives the next neighbour. */
493 static void *tc_next_chunk(struct talloc_chunk *tc)
495 return (char *)tc + TC_ALIGN16(TC_HDR_SIZE + tc->size);
498 /* Mark the whole remaining pool as not accessable */
499 static void tc_invalidate_pool(union talloc_pool_chunk *pool_tc)
501 size_t flen = tc_pool_space_left(pool_tc);
503 if (unlikely(talloc_fill.enabled)) {
504 memset(pool_tc->hdr.c.pool, talloc_fill.fill_value, flen);
507 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
508 VALGRIND_MAKE_MEM_NOACCESS(pool_tc->hdr.c.pool, flen);
509 #endif
513 Allocate from a pool
516 static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
517 size_t size)
519 union talloc_pool_chunk *pool_ctx = NULL;
520 size_t space_left;
521 struct talloc_chunk *result;
522 size_t chunk_size;
524 if (parent == NULL) {
525 return NULL;
528 if (parent->flags & TALLOC_FLAG_POOL) {
529 pool_ctx = (union talloc_pool_chunk *)parent;
531 else if (parent->flags & TALLOC_FLAG_POOLMEM) {
532 pool_ctx = (union talloc_pool_chunk *)parent->pool;
535 if (pool_ctx == NULL) {
536 return NULL;
539 space_left = tc_pool_space_left(pool_ctx);
542 * Align size to 16 bytes
544 chunk_size = TC_ALIGN16(size);
546 if (space_left < chunk_size) {
547 return NULL;
550 result = (struct talloc_chunk *)pool_ctx->hdr.c.pool;
552 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
553 VALGRIND_MAKE_MEM_UNDEFINED(result, size);
554 #endif
556 pool_ctx->hdr.c.pool = (void *)((char *)result + chunk_size);
558 result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
559 result->pool = pool_ctx;
561 pool_ctx->hdr.object_count++;
563 return result;
567 Allocate a bit of memory as a child of an existing pointer
569 static inline void *__talloc(const void *context, size_t size)
571 struct talloc_chunk *tc = NULL;
572 struct talloc_memlimit *limit = NULL;
574 if (unlikely(context == NULL)) {
575 context = null_context;
578 if (unlikely(size >= MAX_TALLOC_SIZE)) {
579 return NULL;
582 if (context != NULL) {
583 struct talloc_chunk *ptc = talloc_chunk_from_ptr(context);
585 if (ptc->limit != NULL) {
586 limit = ptc->limit;
589 tc = talloc_alloc_pool(ptc, TC_HDR_SIZE+size);
592 if (tc == NULL) {
594 * Only do the memlimit check/update on actual allocation.
596 if (!talloc_memlimit_check(limit, TC_HDR_SIZE + size)) {
597 errno = ENOMEM;
598 return NULL;
601 tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
602 if (unlikely(tc == NULL)) return NULL;
603 tc->flags = TALLOC_MAGIC;
604 tc->pool = NULL;
606 talloc_memlimit_grow(limit, TC_HDR_SIZE + size);
609 tc->limit = limit;
610 tc->size = size;
611 tc->destructor = NULL;
612 tc->child = NULL;
613 tc->name = NULL;
614 tc->refs = NULL;
616 if (likely(context)) {
617 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
619 if (parent->child) {
620 parent->child->parent = NULL;
621 tc->next = parent->child;
622 tc->next->prev = tc;
623 } else {
624 tc->next = NULL;
626 tc->parent = parent;
627 tc->prev = NULL;
628 parent->child = tc;
629 } else {
630 tc->next = tc->prev = tc->parent = NULL;
633 return TC_PTR_FROM_CHUNK(tc);
637 * Create a talloc pool
640 _PUBLIC_ void *talloc_pool(const void *context, size_t size)
642 union talloc_pool_chunk *pool_tc;
643 void *result = __talloc(context, sizeof(*pool_tc) - TC_HDR_SIZE + size);
645 if (unlikely(result == NULL)) {
646 return NULL;
649 pool_tc = (union talloc_pool_chunk *)talloc_chunk_from_ptr(result);
650 if (unlikely(pool_tc->hdr.c.flags & TALLOC_FLAG_POOLMEM)) {
651 /* We don't handle this correctly, so fail. */
652 talloc_log("talloc: cannot allocate pool off another pool %s\n",
653 talloc_get_name(context));
654 talloc_free(result);
655 return NULL;
657 pool_tc->hdr.c.flags |= TALLOC_FLAG_POOL;
658 pool_tc->hdr.c.pool = tc_pool_first_chunk(pool_tc);
660 pool_tc->hdr.object_count = 1;
662 tc_invalidate_pool(pool_tc);
664 return result;
668 setup a destructor to be called on free of a pointer
669 the destructor should return 0 on success, or -1 on failure.
670 if the destructor fails then the free is failed, and the memory can
671 be continued to be used
673 _PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
675 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
676 tc->destructor = destructor;
680 increase the reference count on a piece of memory.
682 _PUBLIC_ int talloc_increase_ref_count(const void *ptr)
684 if (unlikely(!talloc_reference(null_context, ptr))) {
685 return -1;
687 return 0;
691 helper for talloc_reference()
693 this is referenced by a function pointer and should not be inline
695 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
697 struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
698 _TLIST_REMOVE(ptr_tc->refs, handle);
699 return 0;
703 more efficient way to add a name to a pointer - the name must point to a
704 true string constant
706 static inline void _talloc_set_name_const(const void *ptr, const char *name)
708 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
709 tc->name = name;
713 internal talloc_named_const()
715 static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
717 void *ptr;
719 ptr = __talloc(context, size);
720 if (unlikely(ptr == NULL)) {
721 return NULL;
724 _talloc_set_name_const(ptr, name);
726 return ptr;
730 make a secondary reference to a pointer, hanging off the given context.
731 the pointer remains valid until both the original caller and this given
732 context are freed.
734 the major use for this is when two different structures need to reference the
735 same underlying data, and you want to be able to free the two instances separately,
736 and in either order
738 _PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
740 struct talloc_chunk *tc;
741 struct talloc_reference_handle *handle;
742 if (unlikely(ptr == NULL)) return NULL;
744 tc = talloc_chunk_from_ptr(ptr);
745 handle = (struct talloc_reference_handle *)_talloc_named_const(context,
746 sizeof(struct talloc_reference_handle),
747 TALLOC_MAGIC_REFERENCE);
748 if (unlikely(handle == NULL)) return NULL;
750 /* note that we hang the destructor off the handle, not the
751 main context as that allows the caller to still setup their
752 own destructor on the context if they want to */
753 talloc_set_destructor(handle, talloc_reference_destructor);
754 handle->ptr = discard_const_p(void, ptr);
755 handle->location = location;
756 _TLIST_ADD(tc->refs, handle);
757 return handle->ptr;
760 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
762 static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
763 const char *location)
765 union talloc_pool_chunk *pool;
766 void *next_tc;
768 pool = (union talloc_pool_chunk *)tc->pool;
769 next_tc = tc_next_chunk(tc);
771 tc->flags |= TALLOC_FLAG_FREE;
773 /* we mark the freed memory with where we called the free
774 * from. This means on a double free error we can report where
775 * the first free came from
777 tc->name = location;
779 TC_INVALIDATE_FULL_CHUNK(tc);
781 if (unlikely(pool->hdr.object_count == 0)) {
782 talloc_abort("Pool object count zero!");
783 return;
786 pool->hdr.object_count--;
788 if (unlikely(pool->hdr.object_count == 1
789 && !(pool->hdr.c.flags & TALLOC_FLAG_FREE))) {
791 * if there is just one object left in the pool
792 * and pool->flags does not have TALLOC_FLAG_FREE,
793 * it means this is the pool itself and
794 * the rest is available for new objects
795 * again.
797 pool->hdr.c.pool = tc_pool_first_chunk(pool);
798 tc_invalidate_pool(pool);
799 return;
802 if (unlikely(pool->hdr.object_count == 0)) {
804 * we mark the freed memory with where we called the free
805 * from. This means on a double free error we can report where
806 * the first free came from
808 pool->hdr.c.name = location;
810 talloc_memlimit_update_on_free(&pool->hdr.c);
812 TC_INVALIDATE_FULL_CHUNK(&pool->hdr.c);
813 free(pool);
814 return;
817 if (pool->hdr.c.pool == next_tc) {
819 * if pool->pool still points to end of
820 * 'tc' (which is stored in the 'next_tc' variable),
821 * we can reclaim the memory of 'tc'.
823 pool->hdr.c.pool = tc;
824 return;
828 * Do nothing. The memory is just "wasted", waiting for the pool
829 * itself to be freed.
833 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
834 void *ptr,
835 const char *location);
838 internal talloc_free call
840 static inline int _talloc_free_internal(void *ptr, const char *location)
842 struct talloc_chunk *tc;
844 if (unlikely(ptr == NULL)) {
845 return -1;
848 /* possibly initialised the talloc fill value */
849 if (unlikely(!talloc_fill.initialised)) {
850 const char *fill = getenv(TALLOC_FILL_ENV);
851 if (fill != NULL) {
852 talloc_fill.enabled = true;
853 talloc_fill.fill_value = strtoul(fill, NULL, 0);
855 talloc_fill.initialised = true;
858 tc = talloc_chunk_from_ptr(ptr);
860 if (unlikely(tc->refs)) {
861 int is_child;
862 /* check if this is a reference from a child or
863 * grandchild back to it's parent or grandparent
865 * in that case we need to remove the reference and
866 * call another instance of talloc_free() on the current
867 * pointer.
869 is_child = talloc_is_parent(tc->refs, ptr);
870 _talloc_free_internal(tc->refs, location);
871 if (is_child) {
872 return _talloc_free_internal(ptr, location);
874 return -1;
877 if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
878 /* we have a free loop - stop looping */
879 return 0;
882 if (unlikely(tc->destructor)) {
883 talloc_destructor_t d = tc->destructor;
884 if (d == (talloc_destructor_t)-1) {
885 return -1;
887 tc->destructor = (talloc_destructor_t)-1;
888 if (d(ptr) == -1) {
889 tc->destructor = d;
890 return -1;
892 tc->destructor = NULL;
895 if (tc->parent) {
896 _TLIST_REMOVE(tc->parent->child, tc);
897 if (tc->parent->child) {
898 tc->parent->child->parent = tc->parent;
900 } else {
901 if (tc->prev) tc->prev->next = tc->next;
902 if (tc->next) tc->next->prev = tc->prev;
903 tc->prev = tc->next = NULL;
906 tc->flags |= TALLOC_FLAG_LOOP;
908 _talloc_free_children_internal(tc, ptr, location);
910 tc->flags |= TALLOC_FLAG_FREE;
912 /* we mark the freed memory with where we called the free
913 * from. This means on a double free error we can report where
914 * the first free came from
916 tc->name = location;
918 if (tc->flags & TALLOC_FLAG_POOL) {
919 union talloc_pool_chunk *pool = (union talloc_pool_chunk *)tc;
921 if (unlikely(pool->hdr.object_count == 0)) {
922 talloc_abort("Pool object count zero!");
923 return 0;
926 pool->hdr.object_count--;
928 if (likely(pool->hdr.object_count != 0)) {
929 return 0;
932 talloc_memlimit_update_on_free(tc);
934 TC_INVALIDATE_FULL_CHUNK(tc);
935 free(tc);
936 return 0;
939 if (tc->flags & TALLOC_FLAG_POOLMEM) {
940 _talloc_free_poolmem(tc, location);
941 return 0;
944 talloc_memlimit_update_on_free(tc);
946 TC_INVALIDATE_FULL_CHUNK(tc);
947 free(tc);
948 return 0;
951 static size_t _talloc_total_limit_size(const void *ptr,
952 struct talloc_memlimit *old_limit,
953 struct talloc_memlimit *new_limit);
956 move a lump of memory from one talloc context to another return the
957 ptr on success, or NULL if it could not be transferred.
958 passing NULL as ptr will always return NULL with no side effects.
960 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr)
962 struct talloc_chunk *tc, *new_tc;
963 size_t ctx_size = 0;
965 if (unlikely(!ptr)) {
966 return NULL;
969 if (unlikely(new_ctx == NULL)) {
970 new_ctx = null_context;
973 tc = talloc_chunk_from_ptr(ptr);
975 if (tc->limit != NULL) {
977 ctx_size = _talloc_total_limit_size(ptr, NULL, NULL);
979 /* Decrement the memory limit from the source .. */
980 talloc_memlimit_shrink(tc->limit->upper, ctx_size);
982 if (tc->limit->parent == tc) {
983 tc->limit->upper = NULL;
984 } else {
985 tc->limit = NULL;
989 if (unlikely(new_ctx == NULL)) {
990 if (tc->parent) {
991 _TLIST_REMOVE(tc->parent->child, tc);
992 if (tc->parent->child) {
993 tc->parent->child->parent = tc->parent;
995 } else {
996 if (tc->prev) tc->prev->next = tc->next;
997 if (tc->next) tc->next->prev = tc->prev;
1000 tc->parent = tc->next = tc->prev = NULL;
1001 return discard_const_p(void, ptr);
1004 new_tc = talloc_chunk_from_ptr(new_ctx);
1006 if (unlikely(tc == new_tc || tc->parent == new_tc)) {
1007 return discard_const_p(void, ptr);
1010 if (tc->parent) {
1011 _TLIST_REMOVE(tc->parent->child, tc);
1012 if (tc->parent->child) {
1013 tc->parent->child->parent = tc->parent;
1015 } else {
1016 if (tc->prev) tc->prev->next = tc->next;
1017 if (tc->next) tc->next->prev = tc->prev;
1018 tc->prev = tc->next = NULL;
1021 tc->parent = new_tc;
1022 if (new_tc->child) new_tc->child->parent = NULL;
1023 _TLIST_ADD(new_tc->child, tc);
1025 if (tc->limit || new_tc->limit) {
1026 ctx_size = _talloc_total_limit_size(ptr, tc->limit,
1027 new_tc->limit);
1028 /* .. and increment it in the destination. */
1029 if (new_tc->limit) {
1030 talloc_memlimit_grow(new_tc->limit, ctx_size);
1034 return discard_const_p(void, ptr);
1038 move a lump of memory from one talloc context to another return the
1039 ptr on success, or NULL if it could not be transferred.
1040 passing NULL as ptr will always return NULL with no side effects.
1042 _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
1044 struct talloc_chunk *tc;
1046 if (unlikely(ptr == NULL)) {
1047 return NULL;
1050 tc = talloc_chunk_from_ptr(ptr);
1052 if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
1053 struct talloc_reference_handle *h;
1055 talloc_log("WARNING: talloc_steal with references at %s\n",
1056 location);
1058 for (h=tc->refs; h; h=h->next) {
1059 talloc_log("\treference at %s\n",
1060 h->location);
1064 #if 0
1065 /* this test is probably too expensive to have on in the
1066 normal build, but it useful for debugging */
1067 if (talloc_is_parent(new_ctx, ptr)) {
1068 talloc_log("WARNING: stealing into talloc child at %s\n", location);
1070 #endif
1072 return _talloc_steal_internal(new_ctx, ptr);
1076 this is like a talloc_steal(), but you must supply the old
1077 parent. This resolves the ambiguity in a talloc_steal() which is
1078 called on a context that has more than one parent (via references)
1080 The old parent can be either a reference or a parent
1082 _PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
1084 struct talloc_chunk *tc;
1085 struct talloc_reference_handle *h;
1087 if (unlikely(ptr == NULL)) {
1088 return NULL;
1091 if (old_parent == talloc_parent(ptr)) {
1092 return _talloc_steal_internal(new_parent, ptr);
1095 tc = talloc_chunk_from_ptr(ptr);
1096 for (h=tc->refs;h;h=h->next) {
1097 if (talloc_parent(h) == old_parent) {
1098 if (_talloc_steal_internal(new_parent, h) != h) {
1099 return NULL;
1101 return discard_const_p(void, ptr);
1105 /* it wasn't a parent */
1106 return NULL;
1110 remove a secondary reference to a pointer. This undo's what
1111 talloc_reference() has done. The context and pointer arguments
1112 must match those given to a talloc_reference()
1114 static inline int talloc_unreference(const void *context, const void *ptr)
1116 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1117 struct talloc_reference_handle *h;
1119 if (unlikely(context == NULL)) {
1120 context = null_context;
1123 for (h=tc->refs;h;h=h->next) {
1124 struct talloc_chunk *p = talloc_parent_chunk(h);
1125 if (p == NULL) {
1126 if (context == NULL) break;
1127 } else if (TC_PTR_FROM_CHUNK(p) == context) {
1128 break;
1131 if (h == NULL) {
1132 return -1;
1135 return _talloc_free_internal(h, __location__);
1139 remove a specific parent context from a pointer. This is a more
1140 controlled variant of talloc_free()
1142 _PUBLIC_ int talloc_unlink(const void *context, void *ptr)
1144 struct talloc_chunk *tc_p, *new_p, *tc_c;
1145 void *new_parent;
1147 if (ptr == NULL) {
1148 return -1;
1151 if (context == NULL) {
1152 context = null_context;
1155 if (talloc_unreference(context, ptr) == 0) {
1156 return 0;
1159 if (context != NULL) {
1160 tc_c = talloc_chunk_from_ptr(context);
1161 } else {
1162 tc_c = NULL;
1164 if (tc_c != talloc_parent_chunk(ptr)) {
1165 return -1;
1168 tc_p = talloc_chunk_from_ptr(ptr);
1170 if (tc_p->refs == NULL) {
1171 return _talloc_free_internal(ptr, __location__);
1174 new_p = talloc_parent_chunk(tc_p->refs);
1175 if (new_p) {
1176 new_parent = TC_PTR_FROM_CHUNK(new_p);
1177 } else {
1178 new_parent = NULL;
1181 if (talloc_unreference(new_parent, ptr) != 0) {
1182 return -1;
1185 _talloc_steal_internal(new_parent, ptr);
1187 return 0;
1191 add a name to an existing pointer - va_list version
1193 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1195 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
1197 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1198 tc->name = talloc_vasprintf(ptr, fmt, ap);
1199 if (likely(tc->name)) {
1200 _talloc_set_name_const(tc->name, ".name");
1202 return tc->name;
1206 add a name to an existing pointer
1208 _PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
1210 const char *name;
1211 va_list ap;
1212 va_start(ap, fmt);
1213 name = talloc_set_name_v(ptr, fmt, ap);
1214 va_end(ap);
1215 return name;
1220 create a named talloc pointer. Any talloc pointer can be named, and
1221 talloc_named() operates just like talloc() except that it allows you
1222 to name the pointer.
1224 _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
1226 va_list ap;
1227 void *ptr;
1228 const char *name;
1230 ptr = __talloc(context, size);
1231 if (unlikely(ptr == NULL)) return NULL;
1233 va_start(ap, fmt);
1234 name = talloc_set_name_v(ptr, fmt, ap);
1235 va_end(ap);
1237 if (unlikely(name == NULL)) {
1238 _talloc_free_internal(ptr, __location__);
1239 return NULL;
1242 return ptr;
1246 return the name of a talloc ptr, or "UNNAMED"
1248 _PUBLIC_ const char *talloc_get_name(const void *ptr)
1250 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1251 if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
1252 return ".reference";
1254 if (likely(tc->name)) {
1255 return tc->name;
1257 return "UNNAMED";
1262 check if a pointer has the given name. If it does, return the pointer,
1263 otherwise return NULL
1265 _PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
1267 const char *pname;
1268 if (unlikely(ptr == NULL)) return NULL;
1269 pname = talloc_get_name(ptr);
1270 if (likely(pname == name || strcmp(pname, name) == 0)) {
1271 return discard_const_p(void, ptr);
1273 return NULL;
1276 static void talloc_abort_type_mismatch(const char *location,
1277 const char *name,
1278 const char *expected)
1280 const char *reason;
1282 reason = talloc_asprintf(NULL,
1283 "%s: Type mismatch: name[%s] expected[%s]",
1284 location,
1285 name?name:"NULL",
1286 expected);
1287 if (!reason) {
1288 reason = "Type mismatch";
1291 talloc_abort(reason);
1294 _PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
1296 const char *pname;
1298 if (unlikely(ptr == NULL)) {
1299 talloc_abort_type_mismatch(location, NULL, name);
1300 return NULL;
1303 pname = talloc_get_name(ptr);
1304 if (likely(pname == name || strcmp(pname, name) == 0)) {
1305 return discard_const_p(void, ptr);
1308 talloc_abort_type_mismatch(location, pname, name);
1309 return NULL;
1313 this is for compatibility with older versions of talloc
1315 _PUBLIC_ void *talloc_init(const char *fmt, ...)
1317 va_list ap;
1318 void *ptr;
1319 const char *name;
1321 ptr = __talloc(NULL, 0);
1322 if (unlikely(ptr == NULL)) return NULL;
1324 va_start(ap, fmt);
1325 name = talloc_set_name_v(ptr, fmt, ap);
1326 va_end(ap);
1328 if (unlikely(name == NULL)) {
1329 _talloc_free_internal(ptr, __location__);
1330 return NULL;
1333 return ptr;
1336 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
1337 void *ptr,
1338 const char *location)
1340 while (tc->child) {
1341 /* we need to work out who will own an abandoned child
1342 if it cannot be freed. In priority order, the first
1343 choice is owner of any remaining reference to this
1344 pointer, the second choice is our parent, and the
1345 final choice is the null context. */
1346 void *child = TC_PTR_FROM_CHUNK(tc->child);
1347 const void *new_parent = null_context;
1348 if (unlikely(tc->child->refs)) {
1349 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1350 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1352 if (unlikely(_talloc_free_internal(child, location) == -1)) {
1353 if (new_parent == null_context) {
1354 struct talloc_chunk *p = talloc_parent_chunk(ptr);
1355 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1357 _talloc_steal_internal(new_parent, child);
1363 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1364 should probably not be used in new code. It's in here to keep the talloc
1365 code consistent across Samba 3 and 4.
1367 _PUBLIC_ void talloc_free_children(void *ptr)
1369 struct talloc_chunk *tc_name = NULL;
1370 struct talloc_chunk *tc;
1372 if (unlikely(ptr == NULL)) {
1373 return;
1376 tc = talloc_chunk_from_ptr(ptr);
1378 /* we do not want to free the context name if it is a child .. */
1379 if (likely(tc->child)) {
1380 for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
1381 if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
1383 if (tc_name) {
1384 _TLIST_REMOVE(tc->child, tc_name);
1385 if (tc->child) {
1386 tc->child->parent = tc;
1391 _talloc_free_children_internal(tc, ptr, __location__);
1393 /* .. so we put it back after all other children have been freed */
1394 if (tc_name) {
1395 if (tc->child) {
1396 tc->child->parent = NULL;
1398 tc_name->parent = tc;
1399 _TLIST_ADD(tc->child, tc_name);
1404 Allocate a bit of memory as a child of an existing pointer
1406 _PUBLIC_ void *_talloc(const void *context, size_t size)
1408 return __talloc(context, size);
1412 externally callable talloc_set_name_const()
1414 _PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
1416 _talloc_set_name_const(ptr, name);
1420 create a named talloc pointer. Any talloc pointer can be named, and
1421 talloc_named() operates just like talloc() except that it allows you
1422 to name the pointer.
1424 _PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
1426 return _talloc_named_const(context, size, name);
1430 free a talloc pointer. This also frees all child pointers of this
1431 pointer recursively
1433 return 0 if the memory is actually freed, otherwise -1. The memory
1434 will not be freed if the ref_count is > 1 or the destructor (if
1435 any) returns non-zero
1437 _PUBLIC_ int _talloc_free(void *ptr, const char *location)
1439 struct talloc_chunk *tc;
1441 if (unlikely(ptr == NULL)) {
1442 return -1;
1445 tc = talloc_chunk_from_ptr(ptr);
1447 if (unlikely(tc->refs != NULL)) {
1448 struct talloc_reference_handle *h;
1450 if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
1451 /* in this case we do know which parent should
1452 get this pointer, as there is really only
1453 one parent */
1454 return talloc_unlink(null_context, ptr);
1457 talloc_log("ERROR: talloc_free with references at %s\n",
1458 location);
1460 for (h=tc->refs; h; h=h->next) {
1461 talloc_log("\treference at %s\n",
1462 h->location);
1464 return -1;
1467 return _talloc_free_internal(ptr, location);
1473 A talloc version of realloc. The context argument is only used if
1474 ptr is NULL
1476 _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
1478 struct talloc_chunk *tc;
1479 void *new_ptr;
1480 bool malloced = false;
1481 union talloc_pool_chunk *pool_tc = NULL;
1483 /* size zero is equivalent to free() */
1484 if (unlikely(size == 0)) {
1485 talloc_unlink(context, ptr);
1486 return NULL;
1489 if (unlikely(size >= MAX_TALLOC_SIZE)) {
1490 return NULL;
1493 /* realloc(NULL) is equivalent to malloc() */
1494 if (ptr == NULL) {
1495 return _talloc_named_const(context, size, name);
1498 tc = talloc_chunk_from_ptr(ptr);
1500 /* don't allow realloc on referenced pointers */
1501 if (unlikely(tc->refs)) {
1502 return NULL;
1505 /* don't let anybody try to realloc a talloc_pool */
1506 if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
1507 return NULL;
1510 if (tc->limit && (size > tc->size)) {
1511 if (!talloc_memlimit_check(tc->limit, (size - tc->size))) {
1512 errno = ENOMEM;
1513 return NULL;
1517 /* handle realloc inside a talloc_pool */
1518 if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
1519 pool_tc = (union talloc_pool_chunk *)tc->pool;
1522 #if (ALWAYS_REALLOC == 0)
1523 /* don't shrink if we have less than 1k to gain */
1524 if (size < tc->size && tc->limit == NULL) {
1525 if (pool_tc) {
1526 void *next_tc = tc_next_chunk(tc);
1527 TC_INVALIDATE_SHRINK_CHUNK(tc, size);
1528 tc->size = size;
1529 if (next_tc == pool_tc->hdr.c.pool) {
1530 /* note: tc->size has changed, so this works */
1531 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1533 return ptr;
1534 } else if ((tc->size - size) < 1024) {
1536 * if we call TC_INVALIDATE_SHRINK_CHUNK() here
1537 * we would need to call TC_UNDEFINE_GROW_CHUNK()
1538 * after each realloc call, which slows down
1539 * testing a lot :-(.
1541 * That is why we only mark memory as undefined here.
1543 TC_UNDEFINE_SHRINK_CHUNK(tc, size);
1545 /* do not shrink if we have less than 1k to gain */
1546 tc->size = size;
1547 return ptr;
1549 } else if (tc->size == size) {
1551 * do not change the pointer if it is exactly
1552 * the same size.
1554 return ptr;
1556 #endif
1558 /* by resetting magic we catch users of the old memory */
1559 tc->flags |= TALLOC_FLAG_FREE;
1561 #if ALWAYS_REALLOC
1562 if (pool_tc) {
1563 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1564 pool_tc->hdr.object_count--;
1566 if (new_ptr == NULL) {
1567 new_ptr = malloc(TC_HDR_SIZE+size);
1568 malloced = true;
1571 if (new_ptr) {
1572 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1573 TC_INVALIDATE_FULL_CHUNK(tc);
1575 } else {
1576 new_ptr = malloc(size + TC_HDR_SIZE);
1577 if (new_ptr) {
1578 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1579 free(tc);
1582 #else
1583 if (pool_tc) {
1584 void *next_tc = tc_next_chunk(tc);
1585 size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size);
1586 size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
1587 size_t space_needed;
1588 size_t space_left;
1589 unsigned int chunk_count = pool_tc->hdr.object_count;
1591 if (!(pool_tc->hdr.c.flags & TALLOC_FLAG_FREE)) {
1592 chunk_count -= 1;
1595 if (chunk_count == 1) {
1597 * optimize for the case where 'tc' is the only
1598 * chunk in the pool.
1600 char *start = tc_pool_first_chunk(pool_tc);
1601 space_needed = new_chunk_size;
1602 space_left = (char *)tc_pool_end(pool_tc) - start;
1604 if (space_left >= space_needed) {
1605 size_t old_used = TC_HDR_SIZE + tc->size;
1606 size_t new_used = TC_HDR_SIZE + size;
1607 new_ptr = start;
1608 memmove(new_ptr, tc, old_used);
1610 tc = (struct talloc_chunk *)new_ptr;
1611 TC_UNDEFINE_GROW_CHUNK(tc, size);
1614 * first we do not align the pool pointer
1615 * because we want to invalidate the padding
1616 * too.
1618 pool_tc->hdr.c.pool = new_used + (char *)new_ptr;
1619 tc_invalidate_pool(pool_tc);
1621 /* now the aligned pointer */
1622 pool_tc->hdr.c.pool = new_chunk_size + (char *)new_ptr;
1623 goto got_new_ptr;
1626 next_tc = NULL;
1629 if (new_chunk_size == old_chunk_size) {
1630 TC_UNDEFINE_GROW_CHUNK(tc, size);
1631 tc->flags &= ~TALLOC_FLAG_FREE;
1632 tc->size = size;
1633 return ptr;
1636 if (next_tc == pool_tc->hdr.c.pool) {
1638 * optimize for the case where 'tc' is the last
1639 * chunk in the pool.
1641 space_needed = new_chunk_size - old_chunk_size;
1642 space_left = tc_pool_space_left(pool_tc);
1644 if (space_left >= space_needed) {
1645 TC_UNDEFINE_GROW_CHUNK(tc, size);
1646 tc->flags &= ~TALLOC_FLAG_FREE;
1647 tc->size = size;
1648 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1649 return ptr;
1653 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1655 if (new_ptr == NULL) {
1656 new_ptr = malloc(TC_HDR_SIZE+size);
1657 malloced = true;
1660 if (new_ptr) {
1661 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1663 _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
1666 else {
1667 new_ptr = realloc(tc, size + TC_HDR_SIZE);
1669 got_new_ptr:
1670 #endif
1671 if (unlikely(!new_ptr)) {
1672 tc->flags &= ~TALLOC_FLAG_FREE;
1673 return NULL;
1676 tc = (struct talloc_chunk *)new_ptr;
1677 tc->flags &= ~TALLOC_FLAG_FREE;
1678 if (malloced) {
1679 tc->flags &= ~TALLOC_FLAG_POOLMEM;
1681 if (tc->parent) {
1682 tc->parent->child = tc;
1684 if (tc->child) {
1685 tc->child->parent = tc;
1688 if (tc->prev) {
1689 tc->prev->next = tc;
1691 if (tc->next) {
1692 tc->next->prev = tc;
1695 if (!talloc_memlimit_update(tc->limit, tc->size, size)) {
1696 talloc_abort("cur_size memlimit counter not correct!");
1697 errno = EINVAL;
1698 return NULL;
1700 tc->size = size;
1701 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
1703 return TC_PTR_FROM_CHUNK(tc);
1707 a wrapper around talloc_steal() for situations where you are moving a pointer
1708 between two structures, and want the old pointer to be set to NULL
1710 _PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
1712 const void **pptr = discard_const_p(const void *,_pptr);
1713 void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
1714 (*pptr) = NULL;
1715 return ret;
1718 enum talloc_mem_count_type {
1719 TOTAL_MEM_SIZE,
1720 TOTAL_MEM_BLOCKS,
1721 TOTAL_MEM_LIMIT,
1724 static size_t _talloc_total_mem_internal(const void *ptr,
1725 enum talloc_mem_count_type type,
1726 struct talloc_memlimit *old_limit,
1727 struct talloc_memlimit *new_limit)
1729 size_t total = 0;
1730 struct talloc_chunk *c, *tc;
1732 if (ptr == NULL) {
1733 ptr = null_context;
1735 if (ptr == NULL) {
1736 return 0;
1739 tc = talloc_chunk_from_ptr(ptr);
1741 if (old_limit || new_limit) {
1742 if (tc->limit && tc->limit->upper == old_limit) {
1743 tc->limit->upper = new_limit;
1747 /* optimize in the memlimits case */
1748 if (type == TOTAL_MEM_LIMIT &&
1749 tc->limit != NULL &&
1750 tc->limit != old_limit &&
1751 tc->limit->parent == tc) {
1752 return tc->limit->cur_size;
1755 if (tc->flags & TALLOC_FLAG_LOOP) {
1756 return 0;
1759 tc->flags |= TALLOC_FLAG_LOOP;
1761 if (old_limit || new_limit) {
1762 if (old_limit == tc->limit) {
1763 tc->limit = new_limit;
1767 switch (type) {
1768 case TOTAL_MEM_SIZE:
1769 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1770 total = tc->size;
1772 break;
1773 case TOTAL_MEM_BLOCKS:
1774 total++;
1775 break;
1776 case TOTAL_MEM_LIMIT:
1777 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1779 * Don't count memory allocated from a pool
1780 * when calculating limits. Only count the
1781 * pool itself.
1783 if (!(tc->flags & TALLOC_FLAG_POOLMEM)) {
1784 total = tc->size + TC_HDR_SIZE;
1787 break;
1789 for (c = tc->child; c; c = c->next) {
1790 total += _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c), type,
1791 old_limit, new_limit);
1794 tc->flags &= ~TALLOC_FLAG_LOOP;
1796 return total;
1800 return the total size of a talloc pool (subtree)
1802 _PUBLIC_ size_t talloc_total_size(const void *ptr)
1804 return _talloc_total_mem_internal(ptr, TOTAL_MEM_SIZE, NULL, NULL);
1808 return the total number of blocks in a talloc pool (subtree)
1810 _PUBLIC_ size_t talloc_total_blocks(const void *ptr)
1812 return _talloc_total_mem_internal(ptr, TOTAL_MEM_BLOCKS, NULL, NULL);
1816 return the number of external references to a pointer
1818 _PUBLIC_ size_t talloc_reference_count(const void *ptr)
1820 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1821 struct talloc_reference_handle *h;
1822 size_t ret = 0;
1824 for (h=tc->refs;h;h=h->next) {
1825 ret++;
1827 return ret;
1831 report on memory usage by all children of a pointer, giving a full tree view
1833 _PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1834 void (*callback)(const void *ptr,
1835 int depth, int max_depth,
1836 int is_ref,
1837 void *private_data),
1838 void *private_data)
1840 struct talloc_chunk *c, *tc;
1842 if (ptr == NULL) {
1843 ptr = null_context;
1845 if (ptr == NULL) return;
1847 tc = talloc_chunk_from_ptr(ptr);
1849 if (tc->flags & TALLOC_FLAG_LOOP) {
1850 return;
1853 callback(ptr, depth, max_depth, 0, private_data);
1855 if (max_depth >= 0 && depth >= max_depth) {
1856 return;
1859 tc->flags |= TALLOC_FLAG_LOOP;
1860 for (c=tc->child;c;c=c->next) {
1861 if (c->name == TALLOC_MAGIC_REFERENCE) {
1862 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1863 callback(h->ptr, depth + 1, max_depth, 1, private_data);
1864 } else {
1865 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1868 tc->flags &= ~TALLOC_FLAG_LOOP;
1871 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1873 const char *name = talloc_get_name(ptr);
1874 struct talloc_chunk *tc;
1875 FILE *f = (FILE *)_f;
1877 if (is_ref) {
1878 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1879 return;
1882 tc = talloc_chunk_from_ptr(ptr);
1883 if (tc->limit && tc->limit->parent == tc) {
1884 fprintf(f, "%*s%-30s is a memlimit context"
1885 " (max_size = %lu bytes, cur_size = %lu bytes)\n",
1886 depth*4, "",
1887 name,
1888 (unsigned long)tc->limit->max_size,
1889 (unsigned long)tc->limit->cur_size);
1892 if (depth == 0) {
1893 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1894 (max_depth < 0 ? "full " :""), name,
1895 (unsigned long)talloc_total_size(ptr),
1896 (unsigned long)talloc_total_blocks(ptr));
1897 return;
1900 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1901 depth*4, "",
1902 name,
1903 (unsigned long)talloc_total_size(ptr),
1904 (unsigned long)talloc_total_blocks(ptr),
1905 (int)talloc_reference_count(ptr), ptr);
1907 #if 0
1908 fprintf(f, "content: ");
1909 if (talloc_total_size(ptr)) {
1910 int tot = talloc_total_size(ptr);
1911 int i;
1913 for (i = 0; i < tot; i++) {
1914 if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1915 fprintf(f, "%c", ((char *)ptr)[i]);
1916 } else {
1917 fprintf(f, "~%02x", ((char *)ptr)[i]);
1921 fprintf(f, "\n");
1922 #endif
1926 report on memory usage by all children of a pointer, giving a full tree view
1928 _PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1930 if (f) {
1931 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1932 fflush(f);
1937 report on memory usage by all children of a pointer, giving a full tree view
1939 _PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
1941 talloc_report_depth_file(ptr, 0, -1, f);
1945 report on memory usage by all children of a pointer
1947 _PUBLIC_ void talloc_report(const void *ptr, FILE *f)
1949 talloc_report_depth_file(ptr, 0, 1, f);
1953 report on any memory hanging off the null context
1955 static void talloc_report_null(void)
1957 if (talloc_total_size(null_context) != 0) {
1958 talloc_report(null_context, stderr);
1963 report on any memory hanging off the null context
1965 static void talloc_report_null_full(void)
1967 if (talloc_total_size(null_context) != 0) {
1968 talloc_report_full(null_context, stderr);
1973 enable tracking of the NULL context
1975 _PUBLIC_ void talloc_enable_null_tracking(void)
1977 if (null_context == NULL) {
1978 null_context = _talloc_named_const(NULL, 0, "null_context");
1979 if (autofree_context != NULL) {
1980 talloc_reparent(NULL, null_context, autofree_context);
1986 enable tracking of the NULL context, not moving the autofree context
1987 into the NULL context. This is needed for the talloc testsuite
1989 _PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
1991 if (null_context == NULL) {
1992 null_context = _talloc_named_const(NULL, 0, "null_context");
1997 disable tracking of the NULL context
1999 _PUBLIC_ void talloc_disable_null_tracking(void)
2001 if (null_context != NULL) {
2002 /* we have to move any children onto the real NULL
2003 context */
2004 struct talloc_chunk *tc, *tc2;
2005 tc = talloc_chunk_from_ptr(null_context);
2006 for (tc2 = tc->child; tc2; tc2=tc2->next) {
2007 if (tc2->parent == tc) tc2->parent = NULL;
2008 if (tc2->prev == tc) tc2->prev = NULL;
2010 for (tc2 = tc->next; tc2; tc2=tc2->next) {
2011 if (tc2->parent == tc) tc2->parent = NULL;
2012 if (tc2->prev == tc) tc2->prev = NULL;
2014 tc->child = NULL;
2015 tc->next = NULL;
2017 talloc_free(null_context);
2018 null_context = NULL;
2022 enable leak reporting on exit
2024 _PUBLIC_ void talloc_enable_leak_report(void)
2026 talloc_enable_null_tracking();
2027 atexit(talloc_report_null);
2031 enable full leak reporting on exit
2033 _PUBLIC_ void talloc_enable_leak_report_full(void)
2035 talloc_enable_null_tracking();
2036 atexit(talloc_report_null_full);
2040 talloc and zero memory.
2042 _PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
2044 void *p = _talloc_named_const(ctx, size, name);
2046 if (p) {
2047 memset(p, '\0', size);
2050 return p;
2054 memdup with a talloc.
2056 _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
2058 void *newp = _talloc_named_const(t, size, name);
2060 if (likely(newp)) {
2061 memcpy(newp, p, size);
2064 return newp;
2067 static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
2069 char *ret;
2071 ret = (char *)__talloc(t, len + 1);
2072 if (unlikely(!ret)) return NULL;
2074 memcpy(ret, p, len);
2075 ret[len] = 0;
2077 _talloc_set_name_const(ret, ret);
2078 return ret;
2082 strdup with a talloc
2084 _PUBLIC_ char *talloc_strdup(const void *t, const char *p)
2086 if (unlikely(!p)) return NULL;
2087 return __talloc_strlendup(t, p, strlen(p));
2091 strndup with a talloc
2093 _PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
2095 if (unlikely(!p)) return NULL;
2096 return __talloc_strlendup(t, p, strnlen(p, n));
2099 static inline char *__talloc_strlendup_append(char *s, size_t slen,
2100 const char *a, size_t alen)
2102 char *ret;
2104 ret = talloc_realloc(NULL, s, char, slen + alen + 1);
2105 if (unlikely(!ret)) return NULL;
2107 /* append the string and the trailing \0 */
2108 memcpy(&ret[slen], a, alen);
2109 ret[slen+alen] = 0;
2111 _talloc_set_name_const(ret, ret);
2112 return ret;
2116 * Appends at the end of the string.
2118 _PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
2120 if (unlikely(!s)) {
2121 return talloc_strdup(NULL, a);
2124 if (unlikely(!a)) {
2125 return s;
2128 return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
2132 * Appends at the end of the talloc'ed buffer,
2133 * not the end of the string.
2135 _PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
2137 size_t slen;
2139 if (unlikely(!s)) {
2140 return talloc_strdup(NULL, a);
2143 if (unlikely(!a)) {
2144 return s;
2147 slen = talloc_get_size(s);
2148 if (likely(slen > 0)) {
2149 slen--;
2152 return __talloc_strlendup_append(s, slen, a, strlen(a));
2156 * Appends at the end of the string.
2158 _PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
2160 if (unlikely(!s)) {
2161 return talloc_strndup(NULL, a, n);
2164 if (unlikely(!a)) {
2165 return s;
2168 return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
2172 * Appends at the end of the talloc'ed buffer,
2173 * not the end of the string.
2175 _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
2177 size_t slen;
2179 if (unlikely(!s)) {
2180 return talloc_strndup(NULL, a, n);
2183 if (unlikely(!a)) {
2184 return s;
2187 slen = talloc_get_size(s);
2188 if (likely(slen > 0)) {
2189 slen--;
2192 return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
2195 #ifndef HAVE_VA_COPY
2196 #ifdef HAVE___VA_COPY
2197 #define va_copy(dest, src) __va_copy(dest, src)
2198 #else
2199 #define va_copy(dest, src) (dest) = (src)
2200 #endif
2201 #endif
2203 _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
2205 int len;
2206 char *ret;
2207 va_list ap2;
2208 char c;
2210 /* this call looks strange, but it makes it work on older solaris boxes */
2211 va_copy(ap2, ap);
2212 len = vsnprintf(&c, 1, fmt, ap2);
2213 va_end(ap2);
2214 if (unlikely(len < 0)) {
2215 return NULL;
2218 ret = (char *)__talloc(t, len+1);
2219 if (unlikely(!ret)) return NULL;
2221 va_copy(ap2, ap);
2222 vsnprintf(ret, len+1, fmt, ap2);
2223 va_end(ap2);
2225 _talloc_set_name_const(ret, ret);
2226 return ret;
2231 Perform string formatting, and return a pointer to newly allocated
2232 memory holding the result, inside a memory pool.
2234 _PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
2236 va_list ap;
2237 char *ret;
2239 va_start(ap, fmt);
2240 ret = talloc_vasprintf(t, fmt, ap);
2241 va_end(ap);
2242 return ret;
2245 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2246 const char *fmt, va_list ap)
2247 PRINTF_ATTRIBUTE(3,0);
2249 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2250 const char *fmt, va_list ap)
2252 ssize_t alen;
2253 va_list ap2;
2254 char c;
2256 va_copy(ap2, ap);
2257 alen = vsnprintf(&c, 1, fmt, ap2);
2258 va_end(ap2);
2260 if (alen <= 0) {
2261 /* Either the vsnprintf failed or the format resulted in
2262 * no characters being formatted. In the former case, we
2263 * ought to return NULL, in the latter we ought to return
2264 * the original string. Most current callers of this
2265 * function expect it to never return NULL.
2267 return s;
2270 s = talloc_realloc(NULL, s, char, slen + alen + 1);
2271 if (!s) return NULL;
2273 va_copy(ap2, ap);
2274 vsnprintf(s + slen, alen + 1, fmt, ap2);
2275 va_end(ap2);
2277 _talloc_set_name_const(s, s);
2278 return s;
2282 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2283 * and return @p s, which may have moved. Good for gradually
2284 * accumulating output into a string buffer. Appends at the end
2285 * of the string.
2287 _PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
2289 if (unlikely(!s)) {
2290 return talloc_vasprintf(NULL, fmt, ap);
2293 return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
2297 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2298 * and return @p s, which may have moved. Always appends at the
2299 * end of the talloc'ed buffer, not the end of the string.
2301 _PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
2303 size_t slen;
2305 if (unlikely(!s)) {
2306 return talloc_vasprintf(NULL, fmt, ap);
2309 slen = talloc_get_size(s);
2310 if (likely(slen > 0)) {
2311 slen--;
2314 return __talloc_vaslenprintf_append(s, slen, fmt, ap);
2318 Realloc @p s to append the formatted result of @p fmt and return @p
2319 s, which may have moved. Good for gradually accumulating output
2320 into a string buffer.
2322 _PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
2324 va_list ap;
2326 va_start(ap, fmt);
2327 s = talloc_vasprintf_append(s, fmt, ap);
2328 va_end(ap);
2329 return s;
2333 Realloc @p s to append the formatted result of @p fmt and return @p
2334 s, which may have moved. Good for gradually accumulating output
2335 into a buffer.
2337 _PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
2339 va_list ap;
2341 va_start(ap, fmt);
2342 s = talloc_vasprintf_append_buffer(s, fmt, ap);
2343 va_end(ap);
2344 return s;
2348 alloc an array, checking for integer overflow in the array size
2350 _PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2352 if (count >= MAX_TALLOC_SIZE/el_size) {
2353 return NULL;
2355 return _talloc_named_const(ctx, el_size * count, name);
2359 alloc an zero array, checking for integer overflow in the array size
2361 _PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2363 if (count >= MAX_TALLOC_SIZE/el_size) {
2364 return NULL;
2366 return _talloc_zero(ctx, el_size * count, name);
2370 realloc an array, checking for integer overflow in the array size
2372 _PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
2374 if (count >= MAX_TALLOC_SIZE/el_size) {
2375 return NULL;
2377 return _talloc_realloc(ctx, ptr, el_size * count, name);
2381 a function version of talloc_realloc(), so it can be passed as a function pointer
2382 to libraries that want a realloc function (a realloc function encapsulates
2383 all the basic capabilities of an allocation library, which is why this is useful)
2385 _PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
2387 return _talloc_realloc(context, ptr, size, NULL);
2391 static int talloc_autofree_destructor(void *ptr)
2393 autofree_context = NULL;
2394 return 0;
2397 static void talloc_autofree(void)
2399 talloc_free(autofree_context);
2403 return a context which will be auto-freed on exit
2404 this is useful for reducing the noise in leak reports
2406 _PUBLIC_ void *talloc_autofree_context(void)
2408 if (autofree_context == NULL) {
2409 autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
2410 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
2411 atexit(talloc_autofree);
2413 return autofree_context;
2416 _PUBLIC_ size_t talloc_get_size(const void *context)
2418 struct talloc_chunk *tc;
2420 if (context == NULL) {
2421 context = null_context;
2423 if (context == NULL) {
2424 return 0;
2427 tc = talloc_chunk_from_ptr(context);
2429 return tc->size;
2433 find a parent of this context that has the given name, if any
2435 _PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
2437 struct talloc_chunk *tc;
2439 if (context == NULL) {
2440 return NULL;
2443 tc = talloc_chunk_from_ptr(context);
2444 while (tc) {
2445 if (tc->name && strcmp(tc->name, name) == 0) {
2446 return TC_PTR_FROM_CHUNK(tc);
2448 while (tc && tc->prev) tc = tc->prev;
2449 if (tc) {
2450 tc = tc->parent;
2453 return NULL;
2457 show the parentage of a context
2459 _PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
2461 struct talloc_chunk *tc;
2463 if (context == NULL) {
2464 fprintf(file, "talloc no parents for NULL\n");
2465 return;
2468 tc = talloc_chunk_from_ptr(context);
2469 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
2470 while (tc) {
2471 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
2472 while (tc && tc->prev) tc = tc->prev;
2473 if (tc) {
2474 tc = tc->parent;
2477 fflush(file);
2481 return 1 if ptr is a parent of context
2483 static int _talloc_is_parent(const void *context, const void *ptr, int depth)
2485 struct talloc_chunk *tc;
2487 if (context == NULL) {
2488 return 0;
2491 tc = talloc_chunk_from_ptr(context);
2492 while (tc && depth > 0) {
2493 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
2494 while (tc && tc->prev) tc = tc->prev;
2495 if (tc) {
2496 tc = tc->parent;
2497 depth--;
2500 return 0;
2504 return 1 if ptr is a parent of context
2506 _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
2508 return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
2512 return the total size of memory used by this context and all children
2514 static size_t _talloc_total_limit_size(const void *ptr,
2515 struct talloc_memlimit *old_limit,
2516 struct talloc_memlimit *new_limit)
2518 return _talloc_total_mem_internal(ptr, TOTAL_MEM_LIMIT,
2519 old_limit, new_limit);
2522 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size)
2524 struct talloc_memlimit *l;
2526 for (l = limit; l != NULL; l = l->upper) {
2527 if (l->max_size != 0 &&
2528 ((l->max_size <= l->cur_size) ||
2529 (l->max_size - l->cur_size < size))) {
2530 return false;
2534 return true;
2538 Update memory limits when freeing a talloc_chunk.
2540 static void talloc_memlimit_update_on_free(struct talloc_chunk *tc)
2542 if (!tc->limit) {
2543 return;
2547 * Pool entries don't count. Only the pools
2548 * themselves are counted as part of the memory
2549 * limits.
2551 if (tc->flags & TALLOC_FLAG_POOLMEM) {
2552 return;
2556 * If we are part of a memory limited context hierarchy
2557 * we need to subtract the memory used from the counters
2560 talloc_memlimit_shrink(tc->limit, tc->size+TC_HDR_SIZE);
2562 if (tc->limit->parent == tc) {
2563 free(tc->limit);
2566 tc->limit = NULL;
2570 Increase memory limit accounting after a malloc/realloc.
2572 static void talloc_memlimit_grow(struct talloc_memlimit *limit,
2573 size_t size)
2575 struct talloc_memlimit *l;
2577 for (l = limit; l != NULL; l = l->upper) {
2578 size_t new_cur_size = l->cur_size + size;
2579 if (new_cur_size < l->cur_size) {
2580 talloc_abort("logic error in talloc_memlimit_grow\n");
2581 return;
2583 l->cur_size = new_cur_size;
2588 Decrease memory limit accounting after a free/realloc.
2590 static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
2591 size_t size)
2593 struct talloc_memlimit *l;
2595 for (l = limit; l != NULL; l = l->upper) {
2596 if (l->cur_size < size) {
2597 talloc_abort("logic error in talloc_memlimit_shrink\n");
2598 return;
2600 l->cur_size = l->cur_size - size;
2604 static bool talloc_memlimit_update(struct talloc_memlimit *limit,
2605 size_t old_size, size_t new_size)
2607 struct talloc_memlimit *l;
2608 ssize_t d;
2610 if (old_size == 0) {
2611 d = new_size + TC_HDR_SIZE;
2612 } else {
2613 d = new_size - old_size;
2615 for (l = limit; l != NULL; l = l->upper) {
2616 ssize_t new_cur_size = l->cur_size + d;
2617 if (new_cur_size < 0) {
2618 return false;
2620 l->cur_size = new_cur_size;
2623 return true;
2626 _PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size)
2628 struct talloc_chunk *tc = talloc_chunk_from_ptr(ctx);
2629 struct talloc_memlimit *orig_limit;
2630 struct talloc_memlimit *limit = NULL;
2632 if (tc->limit && tc->limit->parent == tc) {
2633 tc->limit->max_size = max_size;
2634 return 0;
2636 orig_limit = tc->limit;
2638 limit = malloc(sizeof(struct talloc_memlimit));
2639 if (limit == NULL) {
2640 return 1;
2642 limit->parent = tc;
2643 limit->max_size = max_size;
2644 limit->cur_size = _talloc_total_limit_size(ctx, tc->limit, limit);
2646 if (orig_limit) {
2647 limit->upper = orig_limit;
2648 } else {
2649 limit->upper = NULL;
2652 return 0;