Inside _talloc_free_internal(), always call talloc_memlimit_update_on_free() before...
[Samba.git] / lib / talloc / talloc.c
blob74eca3f5e65a63194c247aa088b9ec20e24c2114
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 if (!talloc_memlimit_update(tc->limit->upper, ctx_size, 0)) {
980 talloc_abort("cur_size memlimit counter not correct!");
981 errno = EINVAL;
982 return NULL;
985 if (tc->limit->parent == tc) {
986 tc->limit->upper = NULL;
987 } else {
988 tc->limit = NULL;
992 if (unlikely(new_ctx == NULL)) {
993 if (tc->parent) {
994 _TLIST_REMOVE(tc->parent->child, tc);
995 if (tc->parent->child) {
996 tc->parent->child->parent = tc->parent;
998 } else {
999 if (tc->prev) tc->prev->next = tc->next;
1000 if (tc->next) tc->next->prev = tc->prev;
1003 tc->parent = tc->next = tc->prev = NULL;
1004 return discard_const_p(void, ptr);
1007 new_tc = talloc_chunk_from_ptr(new_ctx);
1009 if (unlikely(tc == new_tc || tc->parent == new_tc)) {
1010 return discard_const_p(void, ptr);
1013 if (tc->parent) {
1014 _TLIST_REMOVE(tc->parent->child, tc);
1015 if (tc->parent->child) {
1016 tc->parent->child->parent = tc->parent;
1018 } else {
1019 if (tc->prev) tc->prev->next = tc->next;
1020 if (tc->next) tc->next->prev = tc->prev;
1021 tc->prev = tc->next = NULL;
1024 tc->parent = new_tc;
1025 if (new_tc->child) new_tc->child->parent = NULL;
1026 _TLIST_ADD(new_tc->child, tc);
1028 if (tc->limit || new_tc->limit) {
1029 ctx_size = _talloc_total_limit_size(ptr, tc->limit,
1030 new_tc->limit);
1033 if (new_tc->limit) {
1034 struct talloc_memlimit *l;
1036 for (l = new_tc->limit; l != NULL; l = l->upper) {
1037 l->cur_size += ctx_size;
1041 return discard_const_p(void, ptr);
1045 move a lump of memory from one talloc context to another return the
1046 ptr on success, or NULL if it could not be transferred.
1047 passing NULL as ptr will always return NULL with no side effects.
1049 _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
1051 struct talloc_chunk *tc;
1053 if (unlikely(ptr == NULL)) {
1054 return NULL;
1057 tc = talloc_chunk_from_ptr(ptr);
1059 if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
1060 struct talloc_reference_handle *h;
1062 talloc_log("WARNING: talloc_steal with references at %s\n",
1063 location);
1065 for (h=tc->refs; h; h=h->next) {
1066 talloc_log("\treference at %s\n",
1067 h->location);
1071 #if 0
1072 /* this test is probably too expensive to have on in the
1073 normal build, but it useful for debugging */
1074 if (talloc_is_parent(new_ctx, ptr)) {
1075 talloc_log("WARNING: stealing into talloc child at %s\n", location);
1077 #endif
1079 return _talloc_steal_internal(new_ctx, ptr);
1083 this is like a talloc_steal(), but you must supply the old
1084 parent. This resolves the ambiguity in a talloc_steal() which is
1085 called on a context that has more than one parent (via references)
1087 The old parent can be either a reference or a parent
1089 _PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
1091 struct talloc_chunk *tc;
1092 struct talloc_reference_handle *h;
1094 if (unlikely(ptr == NULL)) {
1095 return NULL;
1098 if (old_parent == talloc_parent(ptr)) {
1099 return _talloc_steal_internal(new_parent, ptr);
1102 tc = talloc_chunk_from_ptr(ptr);
1103 for (h=tc->refs;h;h=h->next) {
1104 if (talloc_parent(h) == old_parent) {
1105 if (_talloc_steal_internal(new_parent, h) != h) {
1106 return NULL;
1108 return discard_const_p(void, ptr);
1112 /* it wasn't a parent */
1113 return NULL;
1117 remove a secondary reference to a pointer. This undo's what
1118 talloc_reference() has done. The context and pointer arguments
1119 must match those given to a talloc_reference()
1121 static inline int talloc_unreference(const void *context, const void *ptr)
1123 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1124 struct talloc_reference_handle *h;
1126 if (unlikely(context == NULL)) {
1127 context = null_context;
1130 for (h=tc->refs;h;h=h->next) {
1131 struct talloc_chunk *p = talloc_parent_chunk(h);
1132 if (p == NULL) {
1133 if (context == NULL) break;
1134 } else if (TC_PTR_FROM_CHUNK(p) == context) {
1135 break;
1138 if (h == NULL) {
1139 return -1;
1142 return _talloc_free_internal(h, __location__);
1146 remove a specific parent context from a pointer. This is a more
1147 controlled variant of talloc_free()
1149 _PUBLIC_ int talloc_unlink(const void *context, void *ptr)
1151 struct talloc_chunk *tc_p, *new_p, *tc_c;
1152 void *new_parent;
1154 if (ptr == NULL) {
1155 return -1;
1158 if (context == NULL) {
1159 context = null_context;
1162 if (talloc_unreference(context, ptr) == 0) {
1163 return 0;
1166 if (context != NULL) {
1167 tc_c = talloc_chunk_from_ptr(context);
1168 } else {
1169 tc_c = NULL;
1171 if (tc_c != talloc_parent_chunk(ptr)) {
1172 return -1;
1175 tc_p = talloc_chunk_from_ptr(ptr);
1177 if (tc_p->refs == NULL) {
1178 return _talloc_free_internal(ptr, __location__);
1181 new_p = talloc_parent_chunk(tc_p->refs);
1182 if (new_p) {
1183 new_parent = TC_PTR_FROM_CHUNK(new_p);
1184 } else {
1185 new_parent = NULL;
1188 if (talloc_unreference(new_parent, ptr) != 0) {
1189 return -1;
1192 _talloc_steal_internal(new_parent, ptr);
1194 return 0;
1198 add a name to an existing pointer - va_list version
1200 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1202 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
1204 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1205 tc->name = talloc_vasprintf(ptr, fmt, ap);
1206 if (likely(tc->name)) {
1207 _talloc_set_name_const(tc->name, ".name");
1209 return tc->name;
1213 add a name to an existing pointer
1215 _PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
1217 const char *name;
1218 va_list ap;
1219 va_start(ap, fmt);
1220 name = talloc_set_name_v(ptr, fmt, ap);
1221 va_end(ap);
1222 return name;
1227 create a named talloc pointer. Any talloc pointer can be named, and
1228 talloc_named() operates just like talloc() except that it allows you
1229 to name the pointer.
1231 _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
1233 va_list ap;
1234 void *ptr;
1235 const char *name;
1237 ptr = __talloc(context, size);
1238 if (unlikely(ptr == NULL)) return NULL;
1240 va_start(ap, fmt);
1241 name = talloc_set_name_v(ptr, fmt, ap);
1242 va_end(ap);
1244 if (unlikely(name == NULL)) {
1245 _talloc_free_internal(ptr, __location__);
1246 return NULL;
1249 return ptr;
1253 return the name of a talloc ptr, or "UNNAMED"
1255 _PUBLIC_ const char *talloc_get_name(const void *ptr)
1257 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1258 if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
1259 return ".reference";
1261 if (likely(tc->name)) {
1262 return tc->name;
1264 return "UNNAMED";
1269 check if a pointer has the given name. If it does, return the pointer,
1270 otherwise return NULL
1272 _PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
1274 const char *pname;
1275 if (unlikely(ptr == NULL)) return NULL;
1276 pname = talloc_get_name(ptr);
1277 if (likely(pname == name || strcmp(pname, name) == 0)) {
1278 return discard_const_p(void, ptr);
1280 return NULL;
1283 static void talloc_abort_type_mismatch(const char *location,
1284 const char *name,
1285 const char *expected)
1287 const char *reason;
1289 reason = talloc_asprintf(NULL,
1290 "%s: Type mismatch: name[%s] expected[%s]",
1291 location,
1292 name?name:"NULL",
1293 expected);
1294 if (!reason) {
1295 reason = "Type mismatch";
1298 talloc_abort(reason);
1301 _PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
1303 const char *pname;
1305 if (unlikely(ptr == NULL)) {
1306 talloc_abort_type_mismatch(location, NULL, name);
1307 return NULL;
1310 pname = talloc_get_name(ptr);
1311 if (likely(pname == name || strcmp(pname, name) == 0)) {
1312 return discard_const_p(void, ptr);
1315 talloc_abort_type_mismatch(location, pname, name);
1316 return NULL;
1320 this is for compatibility with older versions of talloc
1322 _PUBLIC_ void *talloc_init(const char *fmt, ...)
1324 va_list ap;
1325 void *ptr;
1326 const char *name;
1328 ptr = __talloc(NULL, 0);
1329 if (unlikely(ptr == NULL)) return NULL;
1331 va_start(ap, fmt);
1332 name = talloc_set_name_v(ptr, fmt, ap);
1333 va_end(ap);
1335 if (unlikely(name == NULL)) {
1336 _talloc_free_internal(ptr, __location__);
1337 return NULL;
1340 return ptr;
1343 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
1344 void *ptr,
1345 const char *location)
1347 while (tc->child) {
1348 /* we need to work out who will own an abandoned child
1349 if it cannot be freed. In priority order, the first
1350 choice is owner of any remaining reference to this
1351 pointer, the second choice is our parent, and the
1352 final choice is the null context. */
1353 void *child = TC_PTR_FROM_CHUNK(tc->child);
1354 const void *new_parent = null_context;
1355 if (unlikely(tc->child->refs)) {
1356 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1357 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1359 if (unlikely(_talloc_free_internal(child, location) == -1)) {
1360 if (new_parent == null_context) {
1361 struct talloc_chunk *p = talloc_parent_chunk(ptr);
1362 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1364 _talloc_steal_internal(new_parent, child);
1370 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1371 should probably not be used in new code. It's in here to keep the talloc
1372 code consistent across Samba 3 and 4.
1374 _PUBLIC_ void talloc_free_children(void *ptr)
1376 struct talloc_chunk *tc_name = NULL;
1377 struct talloc_chunk *tc;
1379 if (unlikely(ptr == NULL)) {
1380 return;
1383 tc = talloc_chunk_from_ptr(ptr);
1385 /* we do not want to free the context name if it is a child .. */
1386 if (likely(tc->child)) {
1387 for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
1388 if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
1390 if (tc_name) {
1391 _TLIST_REMOVE(tc->child, tc_name);
1392 if (tc->child) {
1393 tc->child->parent = tc;
1398 _talloc_free_children_internal(tc, ptr, __location__);
1400 /* .. so we put it back after all other children have been freed */
1401 if (tc_name) {
1402 if (tc->child) {
1403 tc->child->parent = NULL;
1405 tc_name->parent = tc;
1406 _TLIST_ADD(tc->child, tc_name);
1411 Allocate a bit of memory as a child of an existing pointer
1413 _PUBLIC_ void *_talloc(const void *context, size_t size)
1415 return __talloc(context, size);
1419 externally callable talloc_set_name_const()
1421 _PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
1423 _talloc_set_name_const(ptr, name);
1427 create a named talloc pointer. Any talloc pointer can be named, and
1428 talloc_named() operates just like talloc() except that it allows you
1429 to name the pointer.
1431 _PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
1433 return _talloc_named_const(context, size, name);
1437 free a talloc pointer. This also frees all child pointers of this
1438 pointer recursively
1440 return 0 if the memory is actually freed, otherwise -1. The memory
1441 will not be freed if the ref_count is > 1 or the destructor (if
1442 any) returns non-zero
1444 _PUBLIC_ int _talloc_free(void *ptr, const char *location)
1446 struct talloc_chunk *tc;
1448 if (unlikely(ptr == NULL)) {
1449 return -1;
1452 tc = talloc_chunk_from_ptr(ptr);
1454 if (unlikely(tc->refs != NULL)) {
1455 struct talloc_reference_handle *h;
1457 if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
1458 /* in this case we do know which parent should
1459 get this pointer, as there is really only
1460 one parent */
1461 return talloc_unlink(null_context, ptr);
1464 talloc_log("ERROR: talloc_free with references at %s\n",
1465 location);
1467 for (h=tc->refs; h; h=h->next) {
1468 talloc_log("\treference at %s\n",
1469 h->location);
1471 return -1;
1474 return _talloc_free_internal(ptr, location);
1480 A talloc version of realloc. The context argument is only used if
1481 ptr is NULL
1483 _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
1485 struct talloc_chunk *tc;
1486 void *new_ptr;
1487 bool malloced = false;
1488 union talloc_pool_chunk *pool_tc = NULL;
1490 /* size zero is equivalent to free() */
1491 if (unlikely(size == 0)) {
1492 talloc_unlink(context, ptr);
1493 return NULL;
1496 if (unlikely(size >= MAX_TALLOC_SIZE)) {
1497 return NULL;
1500 /* realloc(NULL) is equivalent to malloc() */
1501 if (ptr == NULL) {
1502 return _talloc_named_const(context, size, name);
1505 tc = talloc_chunk_from_ptr(ptr);
1507 /* don't allow realloc on referenced pointers */
1508 if (unlikely(tc->refs)) {
1509 return NULL;
1512 /* don't let anybody try to realloc a talloc_pool */
1513 if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
1514 return NULL;
1517 if (tc->limit && (size - tc->size > 0)) {
1518 if (!talloc_memlimit_check(tc->limit, (size - tc->size))) {
1519 errno = ENOMEM;
1520 return NULL;
1524 /* handle realloc inside a talloc_pool */
1525 if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
1526 pool_tc = (union talloc_pool_chunk *)tc->pool;
1529 #if (ALWAYS_REALLOC == 0)
1530 /* don't shrink if we have less than 1k to gain */
1531 if (size < tc->size && tc->limit == NULL) {
1532 if (pool_tc) {
1533 void *next_tc = tc_next_chunk(tc);
1534 TC_INVALIDATE_SHRINK_CHUNK(tc, size);
1535 tc->size = size;
1536 if (next_tc == pool_tc->hdr.c.pool) {
1537 /* note: tc->size has changed, so this works */
1538 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1540 return ptr;
1541 } else if ((tc->size - size) < 1024) {
1543 * if we call TC_INVALIDATE_SHRINK_CHUNK() here
1544 * we would need to call TC_UNDEFINE_GROW_CHUNK()
1545 * after each realloc call, which slows down
1546 * testing a lot :-(.
1548 * That is why we only mark memory as undefined here.
1550 TC_UNDEFINE_SHRINK_CHUNK(tc, size);
1552 /* do not shrink if we have less than 1k to gain */
1553 tc->size = size;
1554 return ptr;
1556 } else if (tc->size == size) {
1558 * do not change the pointer if it is exactly
1559 * the same size.
1561 return ptr;
1563 #endif
1565 /* by resetting magic we catch users of the old memory */
1566 tc->flags |= TALLOC_FLAG_FREE;
1568 #if ALWAYS_REALLOC
1569 if (pool_tc) {
1570 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1571 pool_tc->hdr.object_count--;
1573 if (new_ptr == NULL) {
1574 new_ptr = malloc(TC_HDR_SIZE+size);
1575 malloced = true;
1578 if (new_ptr) {
1579 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1580 TC_INVALIDATE_FULL_CHUNK(tc);
1582 } else {
1583 new_ptr = malloc(size + TC_HDR_SIZE);
1584 if (new_ptr) {
1585 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1586 free(tc);
1589 #else
1590 if (pool_tc) {
1591 void *next_tc = tc_next_chunk(tc);
1592 size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size);
1593 size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
1594 size_t space_needed;
1595 size_t space_left;
1596 unsigned int chunk_count = pool_tc->hdr.object_count;
1598 if (!(pool_tc->hdr.c.flags & TALLOC_FLAG_FREE)) {
1599 chunk_count -= 1;
1602 if (chunk_count == 1) {
1604 * optimize for the case where 'tc' is the only
1605 * chunk in the pool.
1607 char *start = tc_pool_first_chunk(pool_tc);
1608 space_needed = new_chunk_size;
1609 space_left = (char *)tc_pool_end(pool_tc) - start;
1611 if (space_left >= space_needed) {
1612 size_t old_used = TC_HDR_SIZE + tc->size;
1613 size_t new_used = TC_HDR_SIZE + size;
1614 new_ptr = start;
1615 memmove(new_ptr, tc, old_used);
1617 tc = (struct talloc_chunk *)new_ptr;
1618 TC_UNDEFINE_GROW_CHUNK(tc, size);
1621 * first we do not align the pool pointer
1622 * because we want to invalidate the padding
1623 * too.
1625 pool_tc->hdr.c.pool = new_used + (char *)new_ptr;
1626 tc_invalidate_pool(pool_tc);
1628 /* now the aligned pointer */
1629 pool_tc->hdr.c.pool = new_chunk_size + (char *)new_ptr;
1630 goto got_new_ptr;
1633 next_tc = NULL;
1636 if (new_chunk_size == old_chunk_size) {
1637 TC_UNDEFINE_GROW_CHUNK(tc, size);
1638 tc->flags &= ~TALLOC_FLAG_FREE;
1639 if (!talloc_memlimit_update(tc->limit,
1640 tc->size, size)) {
1641 talloc_abort("cur_size memlimit counter not"
1642 " correct!");
1643 errno = EINVAL;
1644 return NULL;
1647 tc->size = size;
1648 return ptr;
1651 if (next_tc == pool_tc->hdr.c.pool) {
1653 * optimize for the case where 'tc' is the last
1654 * chunk in the pool.
1656 space_needed = new_chunk_size - old_chunk_size;
1657 space_left = tc_pool_space_left(pool_tc);
1659 if (space_left >= space_needed) {
1660 TC_UNDEFINE_GROW_CHUNK(tc, size);
1661 tc->flags &= ~TALLOC_FLAG_FREE;
1662 if (!talloc_memlimit_update(tc->limit,
1663 tc->size, size)) {
1664 talloc_abort("cur_size memlimit "
1665 "counter not correct!");
1666 errno = EINVAL;
1667 return NULL;
1669 tc->size = size;
1670 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1671 return ptr;
1675 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1677 if (new_ptr == NULL) {
1678 new_ptr = malloc(TC_HDR_SIZE+size);
1679 malloced = true;
1682 if (new_ptr) {
1683 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1685 _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
1688 else {
1689 new_ptr = realloc(tc, size + TC_HDR_SIZE);
1691 got_new_ptr:
1692 #endif
1693 if (unlikely(!new_ptr)) {
1694 tc->flags &= ~TALLOC_FLAG_FREE;
1695 return NULL;
1698 tc = (struct talloc_chunk *)new_ptr;
1699 tc->flags &= ~TALLOC_FLAG_FREE;
1700 if (malloced) {
1701 tc->flags &= ~TALLOC_FLAG_POOLMEM;
1703 if (tc->parent) {
1704 tc->parent->child = tc;
1706 if (tc->child) {
1707 tc->child->parent = tc;
1710 if (tc->prev) {
1711 tc->prev->next = tc;
1713 if (tc->next) {
1714 tc->next->prev = tc;
1717 if (!talloc_memlimit_update(tc->limit, tc->size, size)) {
1718 talloc_abort("cur_size memlimit counter not correct!");
1719 errno = EINVAL;
1720 return NULL;
1722 tc->size = size;
1723 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
1725 return TC_PTR_FROM_CHUNK(tc);
1729 a wrapper around talloc_steal() for situations where you are moving a pointer
1730 between two structures, and want the old pointer to be set to NULL
1732 _PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
1734 const void **pptr = discard_const_p(const void *,_pptr);
1735 void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
1736 (*pptr) = NULL;
1737 return ret;
1740 enum talloc_mem_count_type {
1741 TOTAL_MEM_SIZE,
1742 TOTAL_MEM_BLOCKS,
1743 TOTAL_MEM_LIMIT,
1746 static size_t _talloc_total_mem_internal(const void *ptr,
1747 enum talloc_mem_count_type type,
1748 struct talloc_memlimit *old_limit,
1749 struct talloc_memlimit *new_limit)
1751 size_t total = 0;
1752 struct talloc_chunk *c, *tc;
1754 if (ptr == NULL) {
1755 ptr = null_context;
1757 if (ptr == NULL) {
1758 return 0;
1761 tc = talloc_chunk_from_ptr(ptr);
1763 if (old_limit || new_limit) {
1764 if (tc->limit && tc->limit->upper == old_limit) {
1765 tc->limit->upper = new_limit;
1769 /* optimize in the memlimits case */
1770 if (type == TOTAL_MEM_LIMIT &&
1771 tc->limit != NULL &&
1772 tc->limit != old_limit &&
1773 tc->limit->parent == tc) {
1774 return tc->limit->cur_size;
1777 if (tc->flags & TALLOC_FLAG_LOOP) {
1778 return 0;
1781 tc->flags |= TALLOC_FLAG_LOOP;
1783 if (old_limit || new_limit) {
1784 if (old_limit == tc->limit) {
1785 tc->limit = new_limit;
1789 switch (type) {
1790 case TOTAL_MEM_SIZE:
1791 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1792 total = tc->size;
1794 break;
1795 case TOTAL_MEM_BLOCKS:
1796 total++;
1797 break;
1798 case TOTAL_MEM_LIMIT:
1799 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1801 * Don't count memory allocated from a pool
1802 * when calculating limits. Only count the
1803 * pool itself.
1805 if (!(tc->flags & TALLOC_FLAG_POOLMEM)) {
1806 total = tc->size + TC_HDR_SIZE;
1809 break;
1811 for (c = tc->child; c; c = c->next) {
1812 total += _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c), type,
1813 old_limit, new_limit);
1816 tc->flags &= ~TALLOC_FLAG_LOOP;
1818 return total;
1822 return the total size of a talloc pool (subtree)
1824 _PUBLIC_ size_t talloc_total_size(const void *ptr)
1826 return _talloc_total_mem_internal(ptr, TOTAL_MEM_SIZE, NULL, NULL);
1830 return the total number of blocks in a talloc pool (subtree)
1832 _PUBLIC_ size_t talloc_total_blocks(const void *ptr)
1834 return _talloc_total_mem_internal(ptr, TOTAL_MEM_BLOCKS, NULL, NULL);
1838 return the number of external references to a pointer
1840 _PUBLIC_ size_t talloc_reference_count(const void *ptr)
1842 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1843 struct talloc_reference_handle *h;
1844 size_t ret = 0;
1846 for (h=tc->refs;h;h=h->next) {
1847 ret++;
1849 return ret;
1853 report on memory usage by all children of a pointer, giving a full tree view
1855 _PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1856 void (*callback)(const void *ptr,
1857 int depth, int max_depth,
1858 int is_ref,
1859 void *private_data),
1860 void *private_data)
1862 struct talloc_chunk *c, *tc;
1864 if (ptr == NULL) {
1865 ptr = null_context;
1867 if (ptr == NULL) return;
1869 tc = talloc_chunk_from_ptr(ptr);
1871 if (tc->flags & TALLOC_FLAG_LOOP) {
1872 return;
1875 callback(ptr, depth, max_depth, 0, private_data);
1877 if (max_depth >= 0 && depth >= max_depth) {
1878 return;
1881 tc->flags |= TALLOC_FLAG_LOOP;
1882 for (c=tc->child;c;c=c->next) {
1883 if (c->name == TALLOC_MAGIC_REFERENCE) {
1884 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1885 callback(h->ptr, depth + 1, max_depth, 1, private_data);
1886 } else {
1887 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1890 tc->flags &= ~TALLOC_FLAG_LOOP;
1893 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1895 const char *name = talloc_get_name(ptr);
1896 struct talloc_chunk *tc;
1897 FILE *f = (FILE *)_f;
1899 if (is_ref) {
1900 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1901 return;
1904 tc = talloc_chunk_from_ptr(ptr);
1905 if (tc->limit && tc->limit->parent == tc) {
1906 fprintf(f, "%*s%-30s is a memlimit context"
1907 " (max_size = %lu bytes, cur_size = %lu bytes)\n",
1908 depth*4, "",
1909 name,
1910 (unsigned long)tc->limit->max_size,
1911 (unsigned long)tc->limit->cur_size);
1914 if (depth == 0) {
1915 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1916 (max_depth < 0 ? "full " :""), name,
1917 (unsigned long)talloc_total_size(ptr),
1918 (unsigned long)talloc_total_blocks(ptr));
1919 return;
1922 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1923 depth*4, "",
1924 name,
1925 (unsigned long)talloc_total_size(ptr),
1926 (unsigned long)talloc_total_blocks(ptr),
1927 (int)talloc_reference_count(ptr), ptr);
1929 #if 0
1930 fprintf(f, "content: ");
1931 if (talloc_total_size(ptr)) {
1932 int tot = talloc_total_size(ptr);
1933 int i;
1935 for (i = 0; i < tot; i++) {
1936 if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1937 fprintf(f, "%c", ((char *)ptr)[i]);
1938 } else {
1939 fprintf(f, "~%02x", ((char *)ptr)[i]);
1943 fprintf(f, "\n");
1944 #endif
1948 report on memory usage by all children of a pointer, giving a full tree view
1950 _PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1952 if (f) {
1953 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1954 fflush(f);
1959 report on memory usage by all children of a pointer, giving a full tree view
1961 _PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
1963 talloc_report_depth_file(ptr, 0, -1, f);
1967 report on memory usage by all children of a pointer
1969 _PUBLIC_ void talloc_report(const void *ptr, FILE *f)
1971 talloc_report_depth_file(ptr, 0, 1, f);
1975 report on any memory hanging off the null context
1977 static void talloc_report_null(void)
1979 if (talloc_total_size(null_context) != 0) {
1980 talloc_report(null_context, stderr);
1985 report on any memory hanging off the null context
1987 static void talloc_report_null_full(void)
1989 if (talloc_total_size(null_context) != 0) {
1990 talloc_report_full(null_context, stderr);
1995 enable tracking of the NULL context
1997 _PUBLIC_ void talloc_enable_null_tracking(void)
1999 if (null_context == NULL) {
2000 null_context = _talloc_named_const(NULL, 0, "null_context");
2001 if (autofree_context != NULL) {
2002 talloc_reparent(NULL, null_context, autofree_context);
2008 enable tracking of the NULL context, not moving the autofree context
2009 into the NULL context. This is needed for the talloc testsuite
2011 _PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
2013 if (null_context == NULL) {
2014 null_context = _talloc_named_const(NULL, 0, "null_context");
2019 disable tracking of the NULL context
2021 _PUBLIC_ void talloc_disable_null_tracking(void)
2023 if (null_context != NULL) {
2024 /* we have to move any children onto the real NULL
2025 context */
2026 struct talloc_chunk *tc, *tc2;
2027 tc = talloc_chunk_from_ptr(null_context);
2028 for (tc2 = tc->child; tc2; tc2=tc2->next) {
2029 if (tc2->parent == tc) tc2->parent = NULL;
2030 if (tc2->prev == tc) tc2->prev = NULL;
2032 for (tc2 = tc->next; tc2; tc2=tc2->next) {
2033 if (tc2->parent == tc) tc2->parent = NULL;
2034 if (tc2->prev == tc) tc2->prev = NULL;
2036 tc->child = NULL;
2037 tc->next = NULL;
2039 talloc_free(null_context);
2040 null_context = NULL;
2044 enable leak reporting on exit
2046 _PUBLIC_ void talloc_enable_leak_report(void)
2048 talloc_enable_null_tracking();
2049 atexit(talloc_report_null);
2053 enable full leak reporting on exit
2055 _PUBLIC_ void talloc_enable_leak_report_full(void)
2057 talloc_enable_null_tracking();
2058 atexit(talloc_report_null_full);
2062 talloc and zero memory.
2064 _PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
2066 void *p = _talloc_named_const(ctx, size, name);
2068 if (p) {
2069 memset(p, '\0', size);
2072 return p;
2076 memdup with a talloc.
2078 _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
2080 void *newp = _talloc_named_const(t, size, name);
2082 if (likely(newp)) {
2083 memcpy(newp, p, size);
2086 return newp;
2089 static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
2091 char *ret;
2093 ret = (char *)__talloc(t, len + 1);
2094 if (unlikely(!ret)) return NULL;
2096 memcpy(ret, p, len);
2097 ret[len] = 0;
2099 _talloc_set_name_const(ret, ret);
2100 return ret;
2104 strdup with a talloc
2106 _PUBLIC_ char *talloc_strdup(const void *t, const char *p)
2108 if (unlikely(!p)) return NULL;
2109 return __talloc_strlendup(t, p, strlen(p));
2113 strndup with a talloc
2115 _PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
2117 if (unlikely(!p)) return NULL;
2118 return __talloc_strlendup(t, p, strnlen(p, n));
2121 static inline char *__talloc_strlendup_append(char *s, size_t slen,
2122 const char *a, size_t alen)
2124 char *ret;
2126 ret = talloc_realloc(NULL, s, char, slen + alen + 1);
2127 if (unlikely(!ret)) return NULL;
2129 /* append the string and the trailing \0 */
2130 memcpy(&ret[slen], a, alen);
2131 ret[slen+alen] = 0;
2133 _talloc_set_name_const(ret, ret);
2134 return ret;
2138 * Appends at the end of the string.
2140 _PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
2142 if (unlikely(!s)) {
2143 return talloc_strdup(NULL, a);
2146 if (unlikely(!a)) {
2147 return s;
2150 return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
2154 * Appends at the end of the talloc'ed buffer,
2155 * not the end of the string.
2157 _PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
2159 size_t slen;
2161 if (unlikely(!s)) {
2162 return talloc_strdup(NULL, a);
2165 if (unlikely(!a)) {
2166 return s;
2169 slen = talloc_get_size(s);
2170 if (likely(slen > 0)) {
2171 slen--;
2174 return __talloc_strlendup_append(s, slen, a, strlen(a));
2178 * Appends at the end of the string.
2180 _PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
2182 if (unlikely(!s)) {
2183 return talloc_strndup(NULL, a, n);
2186 if (unlikely(!a)) {
2187 return s;
2190 return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
2194 * Appends at the end of the talloc'ed buffer,
2195 * not the end of the string.
2197 _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
2199 size_t slen;
2201 if (unlikely(!s)) {
2202 return talloc_strndup(NULL, a, n);
2205 if (unlikely(!a)) {
2206 return s;
2209 slen = talloc_get_size(s);
2210 if (likely(slen > 0)) {
2211 slen--;
2214 return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
2217 #ifndef HAVE_VA_COPY
2218 #ifdef HAVE___VA_COPY
2219 #define va_copy(dest, src) __va_copy(dest, src)
2220 #else
2221 #define va_copy(dest, src) (dest) = (src)
2222 #endif
2223 #endif
2225 _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
2227 int len;
2228 char *ret;
2229 va_list ap2;
2230 char c;
2232 /* this call looks strange, but it makes it work on older solaris boxes */
2233 va_copy(ap2, ap);
2234 len = vsnprintf(&c, 1, fmt, ap2);
2235 va_end(ap2);
2236 if (unlikely(len < 0)) {
2237 return NULL;
2240 ret = (char *)__talloc(t, len+1);
2241 if (unlikely(!ret)) return NULL;
2243 va_copy(ap2, ap);
2244 vsnprintf(ret, len+1, fmt, ap2);
2245 va_end(ap2);
2247 _talloc_set_name_const(ret, ret);
2248 return ret;
2253 Perform string formatting, and return a pointer to newly allocated
2254 memory holding the result, inside a memory pool.
2256 _PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
2258 va_list ap;
2259 char *ret;
2261 va_start(ap, fmt);
2262 ret = talloc_vasprintf(t, fmt, ap);
2263 va_end(ap);
2264 return ret;
2267 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2268 const char *fmt, va_list ap)
2269 PRINTF_ATTRIBUTE(3,0);
2271 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2272 const char *fmt, va_list ap)
2274 ssize_t alen;
2275 va_list ap2;
2276 char c;
2278 va_copy(ap2, ap);
2279 alen = vsnprintf(&c, 1, fmt, ap2);
2280 va_end(ap2);
2282 if (alen <= 0) {
2283 /* Either the vsnprintf failed or the format resulted in
2284 * no characters being formatted. In the former case, we
2285 * ought to return NULL, in the latter we ought to return
2286 * the original string. Most current callers of this
2287 * function expect it to never return NULL.
2289 return s;
2292 s = talloc_realloc(NULL, s, char, slen + alen + 1);
2293 if (!s) return NULL;
2295 va_copy(ap2, ap);
2296 vsnprintf(s + slen, alen + 1, fmt, ap2);
2297 va_end(ap2);
2299 _talloc_set_name_const(s, s);
2300 return s;
2304 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2305 * and return @p s, which may have moved. Good for gradually
2306 * accumulating output into a string buffer. Appends at the end
2307 * of the string.
2309 _PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
2311 if (unlikely(!s)) {
2312 return talloc_vasprintf(NULL, fmt, ap);
2315 return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
2319 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2320 * and return @p s, which may have moved. Always appends at the
2321 * end of the talloc'ed buffer, not the end of the string.
2323 _PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
2325 size_t slen;
2327 if (unlikely(!s)) {
2328 return talloc_vasprintf(NULL, fmt, ap);
2331 slen = talloc_get_size(s);
2332 if (likely(slen > 0)) {
2333 slen--;
2336 return __talloc_vaslenprintf_append(s, slen, fmt, ap);
2340 Realloc @p s to append the formatted result of @p fmt and return @p
2341 s, which may have moved. Good for gradually accumulating output
2342 into a string buffer.
2344 _PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
2346 va_list ap;
2348 va_start(ap, fmt);
2349 s = talloc_vasprintf_append(s, fmt, ap);
2350 va_end(ap);
2351 return s;
2355 Realloc @p s to append the formatted result of @p fmt and return @p
2356 s, which may have moved. Good for gradually accumulating output
2357 into a buffer.
2359 _PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
2361 va_list ap;
2363 va_start(ap, fmt);
2364 s = talloc_vasprintf_append_buffer(s, fmt, ap);
2365 va_end(ap);
2366 return s;
2370 alloc an array, checking for integer overflow in the array size
2372 _PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2374 if (count >= MAX_TALLOC_SIZE/el_size) {
2375 return NULL;
2377 return _talloc_named_const(ctx, el_size * count, name);
2381 alloc an zero array, checking for integer overflow in the array size
2383 _PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2385 if (count >= MAX_TALLOC_SIZE/el_size) {
2386 return NULL;
2388 return _talloc_zero(ctx, el_size * count, name);
2392 realloc an array, checking for integer overflow in the array size
2394 _PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
2396 if (count >= MAX_TALLOC_SIZE/el_size) {
2397 return NULL;
2399 return _talloc_realloc(ctx, ptr, el_size * count, name);
2403 a function version of talloc_realloc(), so it can be passed as a function pointer
2404 to libraries that want a realloc function (a realloc function encapsulates
2405 all the basic capabilities of an allocation library, which is why this is useful)
2407 _PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
2409 return _talloc_realloc(context, ptr, size, NULL);
2413 static int talloc_autofree_destructor(void *ptr)
2415 autofree_context = NULL;
2416 return 0;
2419 static void talloc_autofree(void)
2421 talloc_free(autofree_context);
2425 return a context which will be auto-freed on exit
2426 this is useful for reducing the noise in leak reports
2428 _PUBLIC_ void *talloc_autofree_context(void)
2430 if (autofree_context == NULL) {
2431 autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
2432 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
2433 atexit(talloc_autofree);
2435 return autofree_context;
2438 _PUBLIC_ size_t talloc_get_size(const void *context)
2440 struct talloc_chunk *tc;
2442 if (context == NULL) {
2443 context = null_context;
2445 if (context == NULL) {
2446 return 0;
2449 tc = talloc_chunk_from_ptr(context);
2451 return tc->size;
2455 find a parent of this context that has the given name, if any
2457 _PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
2459 struct talloc_chunk *tc;
2461 if (context == NULL) {
2462 return NULL;
2465 tc = talloc_chunk_from_ptr(context);
2466 while (tc) {
2467 if (tc->name && strcmp(tc->name, name) == 0) {
2468 return TC_PTR_FROM_CHUNK(tc);
2470 while (tc && tc->prev) tc = tc->prev;
2471 if (tc) {
2472 tc = tc->parent;
2475 return NULL;
2479 show the parentage of a context
2481 _PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
2483 struct talloc_chunk *tc;
2485 if (context == NULL) {
2486 fprintf(file, "talloc no parents for NULL\n");
2487 return;
2490 tc = talloc_chunk_from_ptr(context);
2491 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
2492 while (tc) {
2493 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
2494 while (tc && tc->prev) tc = tc->prev;
2495 if (tc) {
2496 tc = tc->parent;
2499 fflush(file);
2503 return 1 if ptr is a parent of context
2505 static int _talloc_is_parent(const void *context, const void *ptr, int depth)
2507 struct talloc_chunk *tc;
2509 if (context == NULL) {
2510 return 0;
2513 tc = talloc_chunk_from_ptr(context);
2514 while (tc && depth > 0) {
2515 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
2516 while (tc && tc->prev) tc = tc->prev;
2517 if (tc) {
2518 tc = tc->parent;
2519 depth--;
2522 return 0;
2526 return 1 if ptr is a parent of context
2528 _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
2530 return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
2534 return the total size of memory used by this context and all children
2536 static size_t _talloc_total_limit_size(const void *ptr,
2537 struct talloc_memlimit *old_limit,
2538 struct talloc_memlimit *new_limit)
2540 return _talloc_total_mem_internal(ptr, TOTAL_MEM_LIMIT,
2541 old_limit, new_limit);
2544 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size)
2546 struct talloc_memlimit *l;
2548 for (l = limit; l != NULL; l = l->upper) {
2549 if (l->max_size != 0 &&
2550 ((l->max_size <= l->cur_size) ||
2551 (l->max_size - l->cur_size < size))) {
2552 return false;
2556 return true;
2560 Update memory limits when freeing a talloc_chunk.
2562 static void talloc_memlimit_update_on_free(struct talloc_chunk *tc)
2564 if (!tc->limit) {
2565 return;
2569 * Pool entries don't count. Only the pools
2570 * themselves are counted as part of the memory
2571 * limits.
2573 if (tc->flags & TALLOC_FLAG_POOLMEM) {
2574 return;
2578 * If we are part of a memory limited context hierarchy
2579 * we need to subtract the memory used from the counters
2582 talloc_memlimit_shrink(tc->limit, tc->size+TC_HDR_SIZE);
2584 if (tc->limit->parent == tc) {
2585 free(tc->limit);
2588 tc->limit = NULL;
2592 Increase memory limit accounting after a malloc/realloc.
2594 static void talloc_memlimit_grow(struct talloc_memlimit *limit,
2595 size_t size)
2597 struct talloc_memlimit *l;
2599 for (l = limit; l != NULL; l = l->upper) {
2600 size_t new_cur_size = l->cur_size + size;
2601 if (new_cur_size < l->cur_size) {
2602 talloc_abort("logic error in talloc_memlimit_grow\n");
2603 return;
2605 l->cur_size = new_cur_size;
2610 Decrease memory limit accounting after a free/realloc.
2612 static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
2613 size_t size)
2615 struct talloc_memlimit *l;
2617 for (l = limit; l != NULL; l = l->upper) {
2618 if (l->cur_size < size) {
2619 talloc_abort("logic error in talloc_memlimit_shrink\n");
2620 return;
2622 l->cur_size = l->cur_size - size;
2626 static bool talloc_memlimit_update(struct talloc_memlimit *limit,
2627 size_t old_size, size_t new_size)
2629 struct talloc_memlimit *l;
2630 ssize_t d;
2632 if (old_size == 0) {
2633 d = new_size + TC_HDR_SIZE;
2634 } else {
2635 d = new_size - old_size;
2637 for (l = limit; l != NULL; l = l->upper) {
2638 ssize_t new_cur_size = l->cur_size + d;
2639 if (new_cur_size < 0) {
2640 return false;
2642 l->cur_size = new_cur_size;
2645 return true;
2648 _PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size)
2650 struct talloc_chunk *tc = talloc_chunk_from_ptr(ctx);
2651 struct talloc_memlimit *orig_limit;
2652 struct talloc_memlimit *limit = NULL;
2654 if (tc->limit && tc->limit->parent == tc) {
2655 tc->limit->max_size = max_size;
2656 return 0;
2658 orig_limit = tc->limit;
2660 limit = malloc(sizeof(struct talloc_memlimit));
2661 if (limit == NULL) {
2662 return 1;
2664 limit->parent = tc;
2665 limit->max_size = max_size;
2666 limit->cur_size = _talloc_total_limit_size(ctx, tc->limit, limit);
2668 if (orig_limit) {
2669 limit->upper = orig_limit;
2670 } else {
2671 limit->upper = NULL;
2674 return 0;