talloc: Do an early return
[Samba.git] / lib / talloc / talloc.c
blob0078b07ca67f7353deb6bd66888913444c78515e
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);
242 typedef int (*talloc_destructor_t)(void *);
244 struct talloc_chunk {
245 struct talloc_chunk *next, *prev;
246 struct talloc_chunk *parent, *child;
247 struct talloc_reference_handle *refs;
248 talloc_destructor_t destructor;
249 const char *name;
250 size_t size;
251 unsigned flags;
254 * limit semantics:
255 * if 'limit' is set it means all *new* children of the context will
256 * be limited to a total aggregate size ox max_size for memory
257 * allocations.
258 * cur_size is used to kep track of the current use
260 struct talloc_memlimit *limit;
263 * "pool" has dual use:
265 * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
266 * marks the end of the currently allocated area.
268 * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
269 * is a pointer to the struct talloc_chunk of the pool that it was
270 * allocated from. This way children can quickly find the pool to chew
271 * from.
273 void *pool;
276 /* 16 byte alignment seems to keep everyone happy */
277 #define TC_ALIGN16(s) (((s)+15)&~15)
278 #define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
279 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
281 _PUBLIC_ int talloc_version_major(void)
283 return TALLOC_VERSION_MAJOR;
286 _PUBLIC_ int talloc_version_minor(void)
288 return TALLOC_VERSION_MINOR;
291 static void (*talloc_log_fn)(const char *message);
293 _PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
295 talloc_log_fn = log_fn;
298 static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
299 static void talloc_log(const char *fmt, ...)
301 va_list ap;
302 char *message;
304 if (!talloc_log_fn) {
305 return;
308 va_start(ap, fmt);
309 message = talloc_vasprintf(NULL, fmt, ap);
310 va_end(ap);
312 talloc_log_fn(message);
313 talloc_free(message);
316 static void talloc_log_stderr(const char *message)
318 fprintf(stderr, "%s", message);
321 _PUBLIC_ void talloc_set_log_stderr(void)
323 talloc_set_log_fn(talloc_log_stderr);
326 static void (*talloc_abort_fn)(const char *reason);
328 _PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
330 talloc_abort_fn = abort_fn;
333 static void talloc_abort(const char *reason)
335 talloc_log("%s\n", reason);
337 if (!talloc_abort_fn) {
338 TALLOC_ABORT(reason);
341 talloc_abort_fn(reason);
344 static void talloc_abort_magic(unsigned magic)
346 unsigned striped = magic - TALLOC_MAGIC_BASE;
347 unsigned major = (striped & 0xFFFFF000) >> 12;
348 unsigned minor = (striped & 0x00000FF0) >> 4;
349 talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
350 magic, major, minor,
351 TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR);
352 talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
355 static void talloc_abort_access_after_free(void)
357 talloc_abort("Bad talloc magic value - access after free");
360 static void talloc_abort_unknown_value(void)
362 talloc_abort("Bad talloc magic value - unknown value");
365 /* panic if we get a bad magic value */
366 static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
368 const char *pp = (const char *)ptr;
369 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
370 if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
371 if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) {
372 talloc_abort_magic(tc->flags & (~0xF));
373 return NULL;
376 if (tc->flags & TALLOC_FLAG_FREE) {
377 talloc_log("talloc: access after free error - first free may be at %s\n", tc->name);
378 talloc_abort_access_after_free();
379 return NULL;
380 } else {
381 talloc_abort_unknown_value();
382 return NULL;
385 return tc;
388 /* hook into the front of the list */
389 #define _TLIST_ADD(list, p) \
390 do { \
391 if (!(list)) { \
392 (list) = (p); \
393 (p)->next = (p)->prev = NULL; \
394 } else { \
395 (list)->prev = (p); \
396 (p)->next = (list); \
397 (p)->prev = NULL; \
398 (list) = (p); \
400 } while (0)
402 /* remove an element from a list - element doesn't have to be in list. */
403 #define _TLIST_REMOVE(list, p) \
404 do { \
405 if ((p) == (list)) { \
406 (list) = (p)->next; \
407 if (list) (list)->prev = NULL; \
408 } else { \
409 if ((p)->prev) (p)->prev->next = (p)->next; \
410 if ((p)->next) (p)->next->prev = (p)->prev; \
412 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
413 } while (0)
417 return the parent chunk of a pointer
419 static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
421 struct talloc_chunk *tc;
423 if (unlikely(ptr == NULL)) {
424 return NULL;
427 tc = talloc_chunk_from_ptr(ptr);
428 while (tc->prev) tc=tc->prev;
430 return tc->parent;
433 _PUBLIC_ void *talloc_parent(const void *ptr)
435 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
436 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
440 find parents name
442 _PUBLIC_ const char *talloc_parent_name(const void *ptr)
444 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
445 return tc? tc->name : NULL;
449 A pool carries an in-pool object count count in the first 16 bytes.
450 bytes. This is done to support talloc_steal() to a parent outside of the
451 pool. The count includes the pool itself, so a talloc_free() on a pool will
452 only destroy the pool if the count has dropped to zero. A talloc_free() of a
453 pool member will reduce the count, and eventually also call free(3) on the
454 pool memory.
456 The object count is not put into "struct talloc_chunk" because it is only
457 relevant for talloc pools and the alignment to 16 bytes would increase the
458 memory footprint of each talloc chunk by those 16 bytes.
461 union talloc_pool_chunk {
462 /* This lets object_count nestle into 16-byte padding of talloc_chunk,
463 * on 32-bit platforms. */
464 struct tc_pool_hdr {
465 struct talloc_chunk c;
466 unsigned int object_count;
467 } hdr;
468 /* This makes it always 16 byte aligned. */
469 char pad[TC_ALIGN16(sizeof(struct tc_pool_hdr))];
472 static void *tc_pool_end(union talloc_pool_chunk *pool_tc)
474 return (char *)pool_tc + TC_HDR_SIZE + pool_tc->hdr.c.size;
477 static size_t tc_pool_space_left(union talloc_pool_chunk *pool_tc)
479 return (char *)tc_pool_end(pool_tc) - (char *)pool_tc->hdr.c.pool;
482 static void *tc_pool_first_chunk(union talloc_pool_chunk *pool_tc)
484 return pool_tc + 1;
487 /* If tc is inside a pool, this gives the next neighbour. */
488 static void *tc_next_chunk(struct talloc_chunk *tc)
490 return (char *)tc + TC_ALIGN16(TC_HDR_SIZE + tc->size);
493 /* Mark the whole remaining pool as not accessable */
494 static void tc_invalidate_pool(union talloc_pool_chunk *pool_tc)
496 size_t flen = tc_pool_space_left(pool_tc);
498 if (unlikely(talloc_fill.enabled)) {
499 memset(pool_tc->hdr.c.pool, talloc_fill.fill_value, flen);
502 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
503 VALGRIND_MAKE_MEM_NOACCESS(pool_tc->hdr.c.pool, flen);
504 #endif
508 Allocate from a pool
511 static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
512 size_t size)
514 union talloc_pool_chunk *pool_ctx = NULL;
515 size_t space_left;
516 struct talloc_chunk *result;
517 size_t chunk_size;
519 if (parent == NULL) {
520 return NULL;
523 if (parent->flags & TALLOC_FLAG_POOL) {
524 pool_ctx = (union talloc_pool_chunk *)parent;
526 else if (parent->flags & TALLOC_FLAG_POOLMEM) {
527 pool_ctx = (union talloc_pool_chunk *)parent->pool;
530 if (pool_ctx == NULL) {
531 return NULL;
534 space_left = tc_pool_space_left(pool_ctx);
537 * Align size to 16 bytes
539 chunk_size = TC_ALIGN16(size);
541 if (space_left < chunk_size) {
542 return NULL;
545 result = (struct talloc_chunk *)pool_ctx->hdr.c.pool;
547 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
548 VALGRIND_MAKE_MEM_UNDEFINED(result, size);
549 #endif
551 pool_ctx->hdr.c.pool = (void *)((char *)result + chunk_size);
553 result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
554 result->pool = pool_ctx;
556 pool_ctx->hdr.object_count++;
558 return result;
562 Allocate a bit of memory as a child of an existing pointer
564 static inline void *__talloc(const void *context, size_t size)
566 struct talloc_chunk *tc = NULL;
567 struct talloc_memlimit *limit = NULL;
569 if (unlikely(context == NULL)) {
570 context = null_context;
573 if (unlikely(size >= MAX_TALLOC_SIZE)) {
574 return NULL;
577 if (context != NULL) {
578 struct talloc_chunk *ptc = talloc_chunk_from_ptr(context);
580 if (ptc->limit != NULL) {
581 limit = ptc->limit;
584 if (!talloc_memlimit_check(limit, (TC_HDR_SIZE+size))) {
585 errno = ENOMEM;
586 return NULL;
589 tc = talloc_alloc_pool(ptc, TC_HDR_SIZE+size);
592 if (tc == NULL) {
593 tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
594 if (unlikely(tc == NULL)) return NULL;
595 tc->flags = TALLOC_MAGIC;
596 tc->pool = NULL;
599 if (limit != NULL) {
600 struct talloc_memlimit *l;
602 for (l = limit; l != NULL; l = l->upper) {
603 l->cur_size += TC_HDR_SIZE+size;
607 tc->limit = limit;
608 tc->size = size;
609 tc->destructor = NULL;
610 tc->child = NULL;
611 tc->name = NULL;
612 tc->refs = NULL;
614 if (likely(context)) {
615 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
617 if (parent->child) {
618 parent->child->parent = NULL;
619 tc->next = parent->child;
620 tc->next->prev = tc;
621 } else {
622 tc->next = NULL;
624 tc->parent = parent;
625 tc->prev = NULL;
626 parent->child = tc;
627 } else {
628 tc->next = tc->prev = tc->parent = NULL;
631 return TC_PTR_FROM_CHUNK(tc);
635 * Create a talloc pool
638 _PUBLIC_ void *talloc_pool(const void *context, size_t size)
640 union talloc_pool_chunk *pool_tc;
641 void *result = __talloc(context, sizeof(*pool_tc) - TC_HDR_SIZE + size);
643 if (unlikely(result == NULL)) {
644 return NULL;
647 pool_tc = (union talloc_pool_chunk *)talloc_chunk_from_ptr(result);
648 if (unlikely(pool_tc->hdr.c.flags & TALLOC_FLAG_POOLMEM)) {
649 /* We don't handle this correctly, so fail. */
650 talloc_log("talloc: cannot allocate pool off another pool %s\n",
651 talloc_get_name(context));
652 talloc_free(result);
653 return NULL;
655 pool_tc->hdr.c.flags |= TALLOC_FLAG_POOL;
656 pool_tc->hdr.c.pool = tc_pool_first_chunk(pool_tc);
658 pool_tc->hdr.object_count = 1;
660 tc_invalidate_pool(pool_tc);
662 return result;
666 setup a destructor to be called on free of a pointer
667 the destructor should return 0 on success, or -1 on failure.
668 if the destructor fails then the free is failed, and the memory can
669 be continued to be used
671 _PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
673 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
674 tc->destructor = destructor;
678 increase the reference count on a piece of memory.
680 _PUBLIC_ int talloc_increase_ref_count(const void *ptr)
682 if (unlikely(!talloc_reference(null_context, ptr))) {
683 return -1;
685 return 0;
689 helper for talloc_reference()
691 this is referenced by a function pointer and should not be inline
693 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
695 struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
696 _TLIST_REMOVE(ptr_tc->refs, handle);
697 return 0;
701 more efficient way to add a name to a pointer - the name must point to a
702 true string constant
704 static inline void _talloc_set_name_const(const void *ptr, const char *name)
706 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
707 tc->name = name;
711 internal talloc_named_const()
713 static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
715 void *ptr;
717 ptr = __talloc(context, size);
718 if (unlikely(ptr == NULL)) {
719 return NULL;
722 _talloc_set_name_const(ptr, name);
724 return ptr;
728 make a secondary reference to a pointer, hanging off the given context.
729 the pointer remains valid until both the original caller and this given
730 context are freed.
732 the major use for this is when two different structures need to reference the
733 same underlying data, and you want to be able to free the two instances separately,
734 and in either order
736 _PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
738 struct talloc_chunk *tc;
739 struct talloc_reference_handle *handle;
740 if (unlikely(ptr == NULL)) return NULL;
742 tc = talloc_chunk_from_ptr(ptr);
743 handle = (struct talloc_reference_handle *)_talloc_named_const(context,
744 sizeof(struct talloc_reference_handle),
745 TALLOC_MAGIC_REFERENCE);
746 if (unlikely(handle == NULL)) return NULL;
748 /* note that we hang the destructor off the handle, not the
749 main context as that allows the caller to still setup their
750 own destructor on the context if they want to */
751 talloc_set_destructor(handle, talloc_reference_destructor);
752 handle->ptr = discard_const_p(void, ptr);
753 handle->location = location;
754 _TLIST_ADD(tc->refs, handle);
755 return handle->ptr;
758 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
760 static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
761 const char *location)
763 union talloc_pool_chunk *pool;
764 void *next_tc;
766 pool = (union talloc_pool_chunk *)tc->pool;
767 next_tc = tc_next_chunk(tc);
769 tc->flags |= TALLOC_FLAG_FREE;
771 /* we mark the freed memory with where we called the free
772 * from. This means on a double free error we can report where
773 * the first free came from
775 tc->name = location;
777 TC_INVALIDATE_FULL_CHUNK(tc);
779 if (unlikely(pool->hdr.object_count == 0)) {
780 talloc_abort("Pool object count zero!");
781 return;
784 pool->hdr.object_count--;
786 if (unlikely(pool->hdr.object_count == 1
787 && !(pool->hdr.c.flags & TALLOC_FLAG_FREE))) {
789 * if there is just one object left in the pool
790 * and pool->flags does not have TALLOC_FLAG_FREE,
791 * it means this is the pool itself and
792 * the rest is available for new objects
793 * again.
795 pool->hdr.c.pool = tc_pool_first_chunk(pool);
796 tc_invalidate_pool(pool);
797 } else if (unlikely(pool->hdr.object_count == 0)) {
799 * we mark the freed memory with where we called the free
800 * from. This means on a double free error we can report where
801 * the first free came from
803 pool->hdr.c.name = location;
805 TC_INVALIDATE_FULL_CHUNK(&pool->hdr.c);
806 free(pool);
807 } else if (pool->hdr.c.pool == next_tc) {
809 * if pool->pool still points to end of
810 * 'tc' (which is stored in the 'next_tc' variable),
811 * we can reclaim the memory of 'tc'.
813 pool->hdr.c.pool = tc;
817 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
818 void *ptr,
819 const char *location);
822 internal talloc_free call
824 static inline int _talloc_free_internal(void *ptr, const char *location)
826 struct talloc_chunk *tc;
828 if (unlikely(ptr == NULL)) {
829 return -1;
832 /* possibly initialised the talloc fill value */
833 if (unlikely(!talloc_fill.initialised)) {
834 const char *fill = getenv(TALLOC_FILL_ENV);
835 if (fill != NULL) {
836 talloc_fill.enabled = true;
837 talloc_fill.fill_value = strtoul(fill, NULL, 0);
839 talloc_fill.initialised = true;
842 tc = talloc_chunk_from_ptr(ptr);
844 if (unlikely(tc->refs)) {
845 int is_child;
846 /* check if this is a reference from a child or
847 * grandchild back to it's parent or grandparent
849 * in that case we need to remove the reference and
850 * call another instance of talloc_free() on the current
851 * pointer.
853 is_child = talloc_is_parent(tc->refs, ptr);
854 _talloc_free_internal(tc->refs, location);
855 if (is_child) {
856 return _talloc_free_internal(ptr, location);
858 return -1;
861 if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
862 /* we have a free loop - stop looping */
863 return 0;
866 if (unlikely(tc->destructor)) {
867 talloc_destructor_t d = tc->destructor;
868 if (d == (talloc_destructor_t)-1) {
869 return -1;
871 tc->destructor = (talloc_destructor_t)-1;
872 if (d(ptr) == -1) {
873 tc->destructor = d;
874 return -1;
876 tc->destructor = NULL;
879 if (tc->parent) {
880 _TLIST_REMOVE(tc->parent->child, tc);
881 if (tc->parent->child) {
882 tc->parent->child->parent = tc->parent;
884 } else {
885 if (tc->prev) tc->prev->next = tc->next;
886 if (tc->next) tc->next->prev = tc->prev;
887 tc->prev = tc->next = NULL;
890 tc->flags |= TALLOC_FLAG_LOOP;
892 _talloc_free_children_internal(tc, ptr, location);
894 tc->flags |= TALLOC_FLAG_FREE;
897 * If we are part of a memory limited context hierarchy
898 * we need to subtract the memory used from the counters
900 if (tc->limit) {
901 struct talloc_memlimit *l;
903 for (l = tc->limit; l != NULL; l = l->upper) {
904 if (l->cur_size >= tc->size+TC_HDR_SIZE) {
905 l->cur_size -= tc->size+TC_HDR_SIZE;
906 } else {
907 talloc_abort("cur_size memlimit counter not correct!");
908 return 0;
912 if (tc->limit->parent == tc) {
913 free(tc->limit);
916 tc->limit = NULL;
919 /* we mark the freed memory with where we called the free
920 * from. This means on a double free error we can report where
921 * the first free came from
923 tc->name = location;
925 if (tc->flags & TALLOC_FLAG_POOL) {
926 union talloc_pool_chunk *pool = (union talloc_pool_chunk *)tc;
928 if (unlikely(pool->hdr.object_count == 0)) {
929 talloc_abort("Pool object count zero!");
930 return 0;
933 pool->hdr.object_count--;
935 if (likely(pool->hdr.object_count != 0)) {
936 return 0;
939 TC_INVALIDATE_FULL_CHUNK(tc);
940 free(tc);
941 return 0;
944 if (tc->flags & TALLOC_FLAG_POOLMEM) {
945 _talloc_free_poolmem(tc, location);
946 return 0;
949 TC_INVALIDATE_FULL_CHUNK(tc);
950 free(tc);
951 return 0;
954 static size_t _talloc_total_limit_size(const void *ptr,
955 struct talloc_memlimit *old_limit,
956 struct talloc_memlimit *new_limit);
959 move a lump of memory from one talloc context to another return the
960 ptr on success, or NULL if it could not be transferred.
961 passing NULL as ptr will always return NULL with no side effects.
963 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr)
965 struct talloc_chunk *tc, *new_tc;
966 size_t ctx_size = 0;
968 if (unlikely(!ptr)) {
969 return NULL;
972 if (unlikely(new_ctx == NULL)) {
973 new_ctx = null_context;
976 tc = talloc_chunk_from_ptr(ptr);
978 if (tc->limit != NULL) {
980 ctx_size = _talloc_total_limit_size(ptr, NULL, NULL);
982 if (!talloc_memlimit_update(tc->limit->upper, ctx_size, 0)) {
983 talloc_abort("cur_size memlimit counter not correct!");
984 errno = EINVAL;
985 return NULL;
988 if (tc->limit->parent == tc) {
989 tc->limit->upper = NULL;
990 } else {
991 tc->limit = NULL;
995 if (unlikely(new_ctx == NULL)) {
996 if (tc->parent) {
997 _TLIST_REMOVE(tc->parent->child, tc);
998 if (tc->parent->child) {
999 tc->parent->child->parent = tc->parent;
1001 } else {
1002 if (tc->prev) tc->prev->next = tc->next;
1003 if (tc->next) tc->next->prev = tc->prev;
1006 tc->parent = tc->next = tc->prev = NULL;
1007 return discard_const_p(void, ptr);
1010 new_tc = talloc_chunk_from_ptr(new_ctx);
1012 if (unlikely(tc == new_tc || tc->parent == new_tc)) {
1013 return discard_const_p(void, ptr);
1016 if (tc->parent) {
1017 _TLIST_REMOVE(tc->parent->child, tc);
1018 if (tc->parent->child) {
1019 tc->parent->child->parent = tc->parent;
1021 } else {
1022 if (tc->prev) tc->prev->next = tc->next;
1023 if (tc->next) tc->next->prev = tc->prev;
1024 tc->prev = tc->next = NULL;
1027 tc->parent = new_tc;
1028 if (new_tc->child) new_tc->child->parent = NULL;
1029 _TLIST_ADD(new_tc->child, tc);
1031 if (tc->limit || new_tc->limit) {
1032 ctx_size = _talloc_total_limit_size(ptr, tc->limit,
1033 new_tc->limit);
1036 if (new_tc->limit) {
1037 struct talloc_memlimit *l;
1039 for (l = new_tc->limit; l != NULL; l = l->upper) {
1040 l->cur_size += ctx_size;
1044 return discard_const_p(void, ptr);
1048 move a lump of memory from one talloc context to another return the
1049 ptr on success, or NULL if it could not be transferred.
1050 passing NULL as ptr will always return NULL with no side effects.
1052 _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
1054 struct talloc_chunk *tc;
1056 if (unlikely(ptr == NULL)) {
1057 return NULL;
1060 tc = talloc_chunk_from_ptr(ptr);
1062 if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
1063 struct talloc_reference_handle *h;
1065 talloc_log("WARNING: talloc_steal with references at %s\n",
1066 location);
1068 for (h=tc->refs; h; h=h->next) {
1069 talloc_log("\treference at %s\n",
1070 h->location);
1074 #if 0
1075 /* this test is probably too expensive to have on in the
1076 normal build, but it useful for debugging */
1077 if (talloc_is_parent(new_ctx, ptr)) {
1078 talloc_log("WARNING: stealing into talloc child at %s\n", location);
1080 #endif
1082 return _talloc_steal_internal(new_ctx, ptr);
1086 this is like a talloc_steal(), but you must supply the old
1087 parent. This resolves the ambiguity in a talloc_steal() which is
1088 called on a context that has more than one parent (via references)
1090 The old parent can be either a reference or a parent
1092 _PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
1094 struct talloc_chunk *tc;
1095 struct talloc_reference_handle *h;
1097 if (unlikely(ptr == NULL)) {
1098 return NULL;
1101 if (old_parent == talloc_parent(ptr)) {
1102 return _talloc_steal_internal(new_parent, ptr);
1105 tc = talloc_chunk_from_ptr(ptr);
1106 for (h=tc->refs;h;h=h->next) {
1107 if (talloc_parent(h) == old_parent) {
1108 if (_talloc_steal_internal(new_parent, h) != h) {
1109 return NULL;
1111 return discard_const_p(void, ptr);
1115 /* it wasn't a parent */
1116 return NULL;
1120 remove a secondary reference to a pointer. This undo's what
1121 talloc_reference() has done. The context and pointer arguments
1122 must match those given to a talloc_reference()
1124 static inline int talloc_unreference(const void *context, const void *ptr)
1126 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1127 struct talloc_reference_handle *h;
1129 if (unlikely(context == NULL)) {
1130 context = null_context;
1133 for (h=tc->refs;h;h=h->next) {
1134 struct talloc_chunk *p = talloc_parent_chunk(h);
1135 if (p == NULL) {
1136 if (context == NULL) break;
1137 } else if (TC_PTR_FROM_CHUNK(p) == context) {
1138 break;
1141 if (h == NULL) {
1142 return -1;
1145 return _talloc_free_internal(h, __location__);
1149 remove a specific parent context from a pointer. This is a more
1150 controlled variant of talloc_free()
1152 _PUBLIC_ int talloc_unlink(const void *context, void *ptr)
1154 struct talloc_chunk *tc_p, *new_p, *tc_c;
1155 void *new_parent;
1157 if (ptr == NULL) {
1158 return -1;
1161 if (context == NULL) {
1162 context = null_context;
1165 if (talloc_unreference(context, ptr) == 0) {
1166 return 0;
1169 if (context != NULL) {
1170 tc_c = talloc_chunk_from_ptr(context);
1171 } else {
1172 tc_c = NULL;
1174 if (tc_c != talloc_parent_chunk(ptr)) {
1175 return -1;
1178 tc_p = talloc_chunk_from_ptr(ptr);
1180 if (tc_p->refs == NULL) {
1181 return _talloc_free_internal(ptr, __location__);
1184 new_p = talloc_parent_chunk(tc_p->refs);
1185 if (new_p) {
1186 new_parent = TC_PTR_FROM_CHUNK(new_p);
1187 } else {
1188 new_parent = NULL;
1191 if (talloc_unreference(new_parent, ptr) != 0) {
1192 return -1;
1195 _talloc_steal_internal(new_parent, ptr);
1197 return 0;
1201 add a name to an existing pointer - va_list version
1203 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1205 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
1207 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1208 tc->name = talloc_vasprintf(ptr, fmt, ap);
1209 if (likely(tc->name)) {
1210 _talloc_set_name_const(tc->name, ".name");
1212 return tc->name;
1216 add a name to an existing pointer
1218 _PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
1220 const char *name;
1221 va_list ap;
1222 va_start(ap, fmt);
1223 name = talloc_set_name_v(ptr, fmt, ap);
1224 va_end(ap);
1225 return name;
1230 create a named talloc pointer. Any talloc pointer can be named, and
1231 talloc_named() operates just like talloc() except that it allows you
1232 to name the pointer.
1234 _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
1236 va_list ap;
1237 void *ptr;
1238 const char *name;
1240 ptr = __talloc(context, size);
1241 if (unlikely(ptr == NULL)) return NULL;
1243 va_start(ap, fmt);
1244 name = talloc_set_name_v(ptr, fmt, ap);
1245 va_end(ap);
1247 if (unlikely(name == NULL)) {
1248 _talloc_free_internal(ptr, __location__);
1249 return NULL;
1252 return ptr;
1256 return the name of a talloc ptr, or "UNNAMED"
1258 _PUBLIC_ const char *talloc_get_name(const void *ptr)
1260 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1261 if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
1262 return ".reference";
1264 if (likely(tc->name)) {
1265 return tc->name;
1267 return "UNNAMED";
1272 check if a pointer has the given name. If it does, return the pointer,
1273 otherwise return NULL
1275 _PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
1277 const char *pname;
1278 if (unlikely(ptr == NULL)) return NULL;
1279 pname = talloc_get_name(ptr);
1280 if (likely(pname == name || strcmp(pname, name) == 0)) {
1281 return discard_const_p(void, ptr);
1283 return NULL;
1286 static void talloc_abort_type_mismatch(const char *location,
1287 const char *name,
1288 const char *expected)
1290 const char *reason;
1292 reason = talloc_asprintf(NULL,
1293 "%s: Type mismatch: name[%s] expected[%s]",
1294 location,
1295 name?name:"NULL",
1296 expected);
1297 if (!reason) {
1298 reason = "Type mismatch";
1301 talloc_abort(reason);
1304 _PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
1306 const char *pname;
1308 if (unlikely(ptr == NULL)) {
1309 talloc_abort_type_mismatch(location, NULL, name);
1310 return NULL;
1313 pname = talloc_get_name(ptr);
1314 if (likely(pname == name || strcmp(pname, name) == 0)) {
1315 return discard_const_p(void, ptr);
1318 talloc_abort_type_mismatch(location, pname, name);
1319 return NULL;
1323 this is for compatibility with older versions of talloc
1325 _PUBLIC_ void *talloc_init(const char *fmt, ...)
1327 va_list ap;
1328 void *ptr;
1329 const char *name;
1331 ptr = __talloc(NULL, 0);
1332 if (unlikely(ptr == NULL)) return NULL;
1334 va_start(ap, fmt);
1335 name = talloc_set_name_v(ptr, fmt, ap);
1336 va_end(ap);
1338 if (unlikely(name == NULL)) {
1339 _talloc_free_internal(ptr, __location__);
1340 return NULL;
1343 return ptr;
1346 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
1347 void *ptr,
1348 const char *location)
1350 while (tc->child) {
1351 /* we need to work out who will own an abandoned child
1352 if it cannot be freed. In priority order, the first
1353 choice is owner of any remaining reference to this
1354 pointer, the second choice is our parent, and the
1355 final choice is the null context. */
1356 void *child = TC_PTR_FROM_CHUNK(tc->child);
1357 const void *new_parent = null_context;
1358 if (unlikely(tc->child->refs)) {
1359 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1360 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1362 if (unlikely(_talloc_free_internal(child, location) == -1)) {
1363 if (new_parent == null_context) {
1364 struct talloc_chunk *p = talloc_parent_chunk(ptr);
1365 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1367 _talloc_steal_internal(new_parent, child);
1373 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1374 should probably not be used in new code. It's in here to keep the talloc
1375 code consistent across Samba 3 and 4.
1377 _PUBLIC_ void talloc_free_children(void *ptr)
1379 struct talloc_chunk *tc_name = NULL;
1380 struct talloc_chunk *tc;
1382 if (unlikely(ptr == NULL)) {
1383 return;
1386 tc = talloc_chunk_from_ptr(ptr);
1388 /* we do not want to free the context name if it is a child .. */
1389 if (likely(tc->child)) {
1390 for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
1391 if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
1393 if (tc_name) {
1394 _TLIST_REMOVE(tc->child, tc_name);
1395 if (tc->child) {
1396 tc->child->parent = tc;
1401 _talloc_free_children_internal(tc, ptr, __location__);
1403 /* .. so we put it back after all other children have been freed */
1404 if (tc_name) {
1405 if (tc->child) {
1406 tc->child->parent = NULL;
1408 tc_name->parent = tc;
1409 _TLIST_ADD(tc->child, tc_name);
1414 Allocate a bit of memory as a child of an existing pointer
1416 _PUBLIC_ void *_talloc(const void *context, size_t size)
1418 return __talloc(context, size);
1422 externally callable talloc_set_name_const()
1424 _PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
1426 _talloc_set_name_const(ptr, name);
1430 create a named talloc pointer. Any talloc pointer can be named, and
1431 talloc_named() operates just like talloc() except that it allows you
1432 to name the pointer.
1434 _PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
1436 return _talloc_named_const(context, size, name);
1440 free a talloc pointer. This also frees all child pointers of this
1441 pointer recursively
1443 return 0 if the memory is actually freed, otherwise -1. The memory
1444 will not be freed if the ref_count is > 1 or the destructor (if
1445 any) returns non-zero
1447 _PUBLIC_ int _talloc_free(void *ptr, const char *location)
1449 struct talloc_chunk *tc;
1451 if (unlikely(ptr == NULL)) {
1452 return -1;
1455 tc = talloc_chunk_from_ptr(ptr);
1457 if (unlikely(tc->refs != NULL)) {
1458 struct talloc_reference_handle *h;
1460 if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
1461 /* in this case we do know which parent should
1462 get this pointer, as there is really only
1463 one parent */
1464 return talloc_unlink(null_context, ptr);
1467 talloc_log("ERROR: talloc_free with references at %s\n",
1468 location);
1470 for (h=tc->refs; h; h=h->next) {
1471 talloc_log("\treference at %s\n",
1472 h->location);
1474 return -1;
1477 return _talloc_free_internal(ptr, location);
1483 A talloc version of realloc. The context argument is only used if
1484 ptr is NULL
1486 _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
1488 struct talloc_chunk *tc;
1489 void *new_ptr;
1490 bool malloced = false;
1491 union talloc_pool_chunk *pool_tc = NULL;
1493 /* size zero is equivalent to free() */
1494 if (unlikely(size == 0)) {
1495 talloc_unlink(context, ptr);
1496 return NULL;
1499 if (unlikely(size >= MAX_TALLOC_SIZE)) {
1500 return NULL;
1503 /* realloc(NULL) is equivalent to malloc() */
1504 if (ptr == NULL) {
1505 return _talloc_named_const(context, size, name);
1508 tc = talloc_chunk_from_ptr(ptr);
1510 /* don't allow realloc on referenced pointers */
1511 if (unlikely(tc->refs)) {
1512 return NULL;
1515 /* don't let anybody try to realloc a talloc_pool */
1516 if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
1517 return NULL;
1520 if (tc->limit && (size - tc->size > 0)) {
1521 if (!talloc_memlimit_check(tc->limit, (size - tc->size))) {
1522 errno = ENOMEM;
1523 return NULL;
1527 /* handle realloc inside a talloc_pool */
1528 if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
1529 pool_tc = (union talloc_pool_chunk *)tc->pool;
1532 #if (ALWAYS_REALLOC == 0)
1533 /* don't shrink if we have less than 1k to gain */
1534 if (size < tc->size && tc->limit == NULL) {
1535 if (pool_tc) {
1536 void *next_tc = tc_next_chunk(tc);
1537 TC_INVALIDATE_SHRINK_CHUNK(tc, size);
1538 tc->size = size;
1539 if (next_tc == pool_tc->hdr.c.pool) {
1540 /* note: tc->size has changed, so this works */
1541 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1543 return ptr;
1544 } else if ((tc->size - size) < 1024) {
1546 * if we call TC_INVALIDATE_SHRINK_CHUNK() here
1547 * we would need to call TC_UNDEFINE_GROW_CHUNK()
1548 * after each realloc call, which slows down
1549 * testing a lot :-(.
1551 * That is why we only mark memory as undefined here.
1553 TC_UNDEFINE_SHRINK_CHUNK(tc, size);
1555 /* do not shrink if we have less than 1k to gain */
1556 tc->size = size;
1557 return ptr;
1559 } else if (tc->size == size) {
1561 * do not change the pointer if it is exactly
1562 * the same size.
1564 return ptr;
1566 #endif
1568 /* by resetting magic we catch users of the old memory */
1569 tc->flags |= TALLOC_FLAG_FREE;
1571 #if ALWAYS_REALLOC
1572 if (pool_tc) {
1573 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1574 pool_tc->hdr.object_count--;
1576 if (new_ptr == NULL) {
1577 new_ptr = malloc(TC_HDR_SIZE+size);
1578 malloced = true;
1581 if (new_ptr) {
1582 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1583 TC_INVALIDATE_FULL_CHUNK(tc);
1585 } else {
1586 new_ptr = malloc(size + TC_HDR_SIZE);
1587 if (new_ptr) {
1588 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1589 free(tc);
1592 #else
1593 if (pool_tc) {
1594 void *next_tc = tc_next_chunk(tc);
1595 size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size);
1596 size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
1597 size_t space_needed;
1598 size_t space_left;
1599 unsigned int chunk_count = pool_tc->hdr.object_count;
1601 if (!(pool_tc->hdr.c.flags & TALLOC_FLAG_FREE)) {
1602 chunk_count -= 1;
1605 if (chunk_count == 1) {
1607 * optimize for the case where 'tc' is the only
1608 * chunk in the pool.
1610 char *start = tc_pool_first_chunk(pool_tc);
1611 space_needed = new_chunk_size;
1612 space_left = (char *)tc_pool_end(pool_tc) - start;
1614 if (space_left >= space_needed) {
1615 size_t old_used = TC_HDR_SIZE + tc->size;
1616 size_t new_used = TC_HDR_SIZE + size;
1617 new_ptr = start;
1618 memmove(new_ptr, tc, old_used);
1620 tc = (struct talloc_chunk *)new_ptr;
1621 TC_UNDEFINE_GROW_CHUNK(tc, size);
1624 * first we do not align the pool pointer
1625 * because we want to invalidate the padding
1626 * too.
1628 pool_tc->hdr.c.pool = new_used + (char *)new_ptr;
1629 tc_invalidate_pool(pool_tc);
1631 /* now the aligned pointer */
1632 pool_tc->hdr.c.pool = new_chunk_size + (char *)new_ptr;
1633 goto got_new_ptr;
1636 next_tc = NULL;
1639 if (new_chunk_size == old_chunk_size) {
1640 TC_UNDEFINE_GROW_CHUNK(tc, size);
1641 tc->flags &= ~TALLOC_FLAG_FREE;
1642 if (!talloc_memlimit_update(tc->limit,
1643 tc->size, size)) {
1644 talloc_abort("cur_size memlimit counter not"
1645 " correct!");
1646 errno = EINVAL;
1647 return NULL;
1650 tc->size = size;
1651 return ptr;
1654 if (next_tc == pool_tc->hdr.c.pool) {
1656 * optimize for the case where 'tc' is the last
1657 * chunk in the pool.
1659 space_needed = new_chunk_size - old_chunk_size;
1660 space_left = tc_pool_space_left(pool_tc);
1662 if (space_left >= space_needed) {
1663 TC_UNDEFINE_GROW_CHUNK(tc, size);
1664 tc->flags &= ~TALLOC_FLAG_FREE;
1665 if (!talloc_memlimit_update(tc->limit,
1666 tc->size, size)) {
1667 talloc_abort("cur_size memlimit "
1668 "counter not correct!");
1669 errno = EINVAL;
1670 return NULL;
1672 tc->size = size;
1673 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1674 return ptr;
1678 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1680 if (new_ptr == NULL) {
1681 new_ptr = malloc(TC_HDR_SIZE+size);
1682 malloced = true;
1685 if (new_ptr) {
1686 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1688 _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
1691 else {
1692 new_ptr = realloc(tc, size + TC_HDR_SIZE);
1694 got_new_ptr:
1695 #endif
1696 if (unlikely(!new_ptr)) {
1697 tc->flags &= ~TALLOC_FLAG_FREE;
1698 return NULL;
1701 tc = (struct talloc_chunk *)new_ptr;
1702 tc->flags &= ~TALLOC_FLAG_FREE;
1703 if (malloced) {
1704 tc->flags &= ~TALLOC_FLAG_POOLMEM;
1706 if (tc->parent) {
1707 tc->parent->child = tc;
1709 if (tc->child) {
1710 tc->child->parent = tc;
1713 if (tc->prev) {
1714 tc->prev->next = tc;
1716 if (tc->next) {
1717 tc->next->prev = tc;
1720 if (!talloc_memlimit_update(tc->limit, tc->size, size)) {
1721 talloc_abort("cur_size memlimit counter not correct!");
1722 errno = EINVAL;
1723 return NULL;
1725 tc->size = size;
1726 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
1728 return TC_PTR_FROM_CHUNK(tc);
1732 a wrapper around talloc_steal() for situations where you are moving a pointer
1733 between two structures, and want the old pointer to be set to NULL
1735 _PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
1737 const void **pptr = discard_const_p(const void *,_pptr);
1738 void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
1739 (*pptr) = NULL;
1740 return ret;
1743 enum talloc_mem_count_type {
1744 TOTAL_MEM_SIZE,
1745 TOTAL_MEM_BLOCKS,
1746 TOTAL_MEM_LIMIT,
1749 static size_t _talloc_total_mem_internal(const void *ptr,
1750 enum talloc_mem_count_type type,
1751 struct talloc_memlimit *old_limit,
1752 struct talloc_memlimit *new_limit)
1754 size_t total = 0;
1755 struct talloc_chunk *c, *tc;
1757 if (ptr == NULL) {
1758 ptr = null_context;
1760 if (ptr == NULL) {
1761 return 0;
1764 tc = talloc_chunk_from_ptr(ptr);
1766 if (old_limit || new_limit) {
1767 if (tc->limit && tc->limit->upper == old_limit) {
1768 tc->limit->upper = new_limit;
1772 /* optimize in the memlimits case */
1773 if (type == TOTAL_MEM_LIMIT &&
1774 tc->limit != NULL &&
1775 tc->limit != old_limit &&
1776 tc->limit->parent == tc) {
1777 return tc->limit->cur_size;
1780 if (tc->flags & TALLOC_FLAG_LOOP) {
1781 return 0;
1784 tc->flags |= TALLOC_FLAG_LOOP;
1786 if (old_limit || new_limit) {
1787 if (old_limit == tc->limit) {
1788 tc->limit = new_limit;
1792 switch (type) {
1793 case TOTAL_MEM_SIZE:
1794 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1795 total = tc->size;
1797 break;
1798 case TOTAL_MEM_BLOCKS:
1799 total++;
1800 break;
1801 case TOTAL_MEM_LIMIT:
1802 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1803 total = tc->size + TC_HDR_SIZE;
1805 break;
1807 for (c = tc->child; c; c = c->next) {
1808 total += _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c), type,
1809 old_limit, new_limit);
1812 tc->flags &= ~TALLOC_FLAG_LOOP;
1814 return total;
1818 return the total size of a talloc pool (subtree)
1820 _PUBLIC_ size_t talloc_total_size(const void *ptr)
1822 return _talloc_total_mem_internal(ptr, TOTAL_MEM_SIZE, NULL, NULL);
1826 return the total number of blocks in a talloc pool (subtree)
1828 _PUBLIC_ size_t talloc_total_blocks(const void *ptr)
1830 return _talloc_total_mem_internal(ptr, TOTAL_MEM_BLOCKS, NULL, NULL);
1834 return the number of external references to a pointer
1836 _PUBLIC_ size_t talloc_reference_count(const void *ptr)
1838 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1839 struct talloc_reference_handle *h;
1840 size_t ret = 0;
1842 for (h=tc->refs;h;h=h->next) {
1843 ret++;
1845 return ret;
1849 report on memory usage by all children of a pointer, giving a full tree view
1851 _PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1852 void (*callback)(const void *ptr,
1853 int depth, int max_depth,
1854 int is_ref,
1855 void *private_data),
1856 void *private_data)
1858 struct talloc_chunk *c, *tc;
1860 if (ptr == NULL) {
1861 ptr = null_context;
1863 if (ptr == NULL) return;
1865 tc = talloc_chunk_from_ptr(ptr);
1867 if (tc->flags & TALLOC_FLAG_LOOP) {
1868 return;
1871 callback(ptr, depth, max_depth, 0, private_data);
1873 if (max_depth >= 0 && depth >= max_depth) {
1874 return;
1877 tc->flags |= TALLOC_FLAG_LOOP;
1878 for (c=tc->child;c;c=c->next) {
1879 if (c->name == TALLOC_MAGIC_REFERENCE) {
1880 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1881 callback(h->ptr, depth + 1, max_depth, 1, private_data);
1882 } else {
1883 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1886 tc->flags &= ~TALLOC_FLAG_LOOP;
1889 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1891 const char *name = talloc_get_name(ptr);
1892 struct talloc_chunk *tc;
1893 FILE *f = (FILE *)_f;
1895 if (is_ref) {
1896 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1897 return;
1900 tc = talloc_chunk_from_ptr(ptr);
1901 if (tc->limit && tc->limit->parent == tc) {
1902 fprintf(f, "%*s%-30s is a memlimit context"
1903 " (max_size = %lu bytes, cur_size = %lu bytes)\n",
1904 depth*4, "",
1905 name,
1906 (unsigned long)tc->limit->max_size,
1907 (unsigned long)tc->limit->cur_size);
1910 if (depth == 0) {
1911 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1912 (max_depth < 0 ? "full " :""), name,
1913 (unsigned long)talloc_total_size(ptr),
1914 (unsigned long)talloc_total_blocks(ptr));
1915 return;
1918 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1919 depth*4, "",
1920 name,
1921 (unsigned long)talloc_total_size(ptr),
1922 (unsigned long)talloc_total_blocks(ptr),
1923 (int)talloc_reference_count(ptr), ptr);
1925 #if 0
1926 fprintf(f, "content: ");
1927 if (talloc_total_size(ptr)) {
1928 int tot = talloc_total_size(ptr);
1929 int i;
1931 for (i = 0; i < tot; i++) {
1932 if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1933 fprintf(f, "%c", ((char *)ptr)[i]);
1934 } else {
1935 fprintf(f, "~%02x", ((char *)ptr)[i]);
1939 fprintf(f, "\n");
1940 #endif
1944 report on memory usage by all children of a pointer, giving a full tree view
1946 _PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1948 if (f) {
1949 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1950 fflush(f);
1955 report on memory usage by all children of a pointer, giving a full tree view
1957 _PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
1959 talloc_report_depth_file(ptr, 0, -1, f);
1963 report on memory usage by all children of a pointer
1965 _PUBLIC_ void talloc_report(const void *ptr, FILE *f)
1967 talloc_report_depth_file(ptr, 0, 1, f);
1971 report on any memory hanging off the null context
1973 static void talloc_report_null(void)
1975 if (talloc_total_size(null_context) != 0) {
1976 talloc_report(null_context, stderr);
1981 report on any memory hanging off the null context
1983 static void talloc_report_null_full(void)
1985 if (talloc_total_size(null_context) != 0) {
1986 talloc_report_full(null_context, stderr);
1991 enable tracking of the NULL context
1993 _PUBLIC_ void talloc_enable_null_tracking(void)
1995 if (null_context == NULL) {
1996 null_context = _talloc_named_const(NULL, 0, "null_context");
1997 if (autofree_context != NULL) {
1998 talloc_reparent(NULL, null_context, autofree_context);
2004 enable tracking of the NULL context, not moving the autofree context
2005 into the NULL context. This is needed for the talloc testsuite
2007 _PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
2009 if (null_context == NULL) {
2010 null_context = _talloc_named_const(NULL, 0, "null_context");
2015 disable tracking of the NULL context
2017 _PUBLIC_ void talloc_disable_null_tracking(void)
2019 if (null_context != NULL) {
2020 /* we have to move any children onto the real NULL
2021 context */
2022 struct talloc_chunk *tc, *tc2;
2023 tc = talloc_chunk_from_ptr(null_context);
2024 for (tc2 = tc->child; tc2; tc2=tc2->next) {
2025 if (tc2->parent == tc) tc2->parent = NULL;
2026 if (tc2->prev == tc) tc2->prev = NULL;
2028 for (tc2 = tc->next; tc2; tc2=tc2->next) {
2029 if (tc2->parent == tc) tc2->parent = NULL;
2030 if (tc2->prev == tc) tc2->prev = NULL;
2032 tc->child = NULL;
2033 tc->next = NULL;
2035 talloc_free(null_context);
2036 null_context = NULL;
2040 enable leak reporting on exit
2042 _PUBLIC_ void talloc_enable_leak_report(void)
2044 talloc_enable_null_tracking();
2045 atexit(talloc_report_null);
2049 enable full leak reporting on exit
2051 _PUBLIC_ void talloc_enable_leak_report_full(void)
2053 talloc_enable_null_tracking();
2054 atexit(talloc_report_null_full);
2058 talloc and zero memory.
2060 _PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
2062 void *p = _talloc_named_const(ctx, size, name);
2064 if (p) {
2065 memset(p, '\0', size);
2068 return p;
2072 memdup with a talloc.
2074 _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
2076 void *newp = _talloc_named_const(t, size, name);
2078 if (likely(newp)) {
2079 memcpy(newp, p, size);
2082 return newp;
2085 static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
2087 char *ret;
2089 ret = (char *)__talloc(t, len + 1);
2090 if (unlikely(!ret)) return NULL;
2092 memcpy(ret, p, len);
2093 ret[len] = 0;
2095 _talloc_set_name_const(ret, ret);
2096 return ret;
2100 strdup with a talloc
2102 _PUBLIC_ char *talloc_strdup(const void *t, const char *p)
2104 if (unlikely(!p)) return NULL;
2105 return __talloc_strlendup(t, p, strlen(p));
2109 strndup with a talloc
2111 _PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
2113 if (unlikely(!p)) return NULL;
2114 return __talloc_strlendup(t, p, strnlen(p, n));
2117 static inline char *__talloc_strlendup_append(char *s, size_t slen,
2118 const char *a, size_t alen)
2120 char *ret;
2122 ret = talloc_realloc(NULL, s, char, slen + alen + 1);
2123 if (unlikely(!ret)) return NULL;
2125 /* append the string and the trailing \0 */
2126 memcpy(&ret[slen], a, alen);
2127 ret[slen+alen] = 0;
2129 _talloc_set_name_const(ret, ret);
2130 return ret;
2134 * Appends at the end of the string.
2136 _PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
2138 if (unlikely(!s)) {
2139 return talloc_strdup(NULL, a);
2142 if (unlikely(!a)) {
2143 return s;
2146 return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
2150 * Appends at the end of the talloc'ed buffer,
2151 * not the end of the string.
2153 _PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
2155 size_t slen;
2157 if (unlikely(!s)) {
2158 return talloc_strdup(NULL, a);
2161 if (unlikely(!a)) {
2162 return s;
2165 slen = talloc_get_size(s);
2166 if (likely(slen > 0)) {
2167 slen--;
2170 return __talloc_strlendup_append(s, slen, a, strlen(a));
2174 * Appends at the end of the string.
2176 _PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
2178 if (unlikely(!s)) {
2179 return talloc_strndup(NULL, a, n);
2182 if (unlikely(!a)) {
2183 return s;
2186 return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
2190 * Appends at the end of the talloc'ed buffer,
2191 * not the end of the string.
2193 _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
2195 size_t slen;
2197 if (unlikely(!s)) {
2198 return talloc_strndup(NULL, a, n);
2201 if (unlikely(!a)) {
2202 return s;
2205 slen = talloc_get_size(s);
2206 if (likely(slen > 0)) {
2207 slen--;
2210 return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
2213 #ifndef HAVE_VA_COPY
2214 #ifdef HAVE___VA_COPY
2215 #define va_copy(dest, src) __va_copy(dest, src)
2216 #else
2217 #define va_copy(dest, src) (dest) = (src)
2218 #endif
2219 #endif
2221 _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
2223 int len;
2224 char *ret;
2225 va_list ap2;
2226 char c;
2228 /* this call looks strange, but it makes it work on older solaris boxes */
2229 va_copy(ap2, ap);
2230 len = vsnprintf(&c, 1, fmt, ap2);
2231 va_end(ap2);
2232 if (unlikely(len < 0)) {
2233 return NULL;
2236 ret = (char *)__talloc(t, len+1);
2237 if (unlikely(!ret)) return NULL;
2239 va_copy(ap2, ap);
2240 vsnprintf(ret, len+1, fmt, ap2);
2241 va_end(ap2);
2243 _talloc_set_name_const(ret, ret);
2244 return ret;
2249 Perform string formatting, and return a pointer to newly allocated
2250 memory holding the result, inside a memory pool.
2252 _PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
2254 va_list ap;
2255 char *ret;
2257 va_start(ap, fmt);
2258 ret = talloc_vasprintf(t, fmt, ap);
2259 va_end(ap);
2260 return ret;
2263 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2264 const char *fmt, va_list ap)
2265 PRINTF_ATTRIBUTE(3,0);
2267 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2268 const char *fmt, va_list ap)
2270 ssize_t alen;
2271 va_list ap2;
2272 char c;
2274 va_copy(ap2, ap);
2275 alen = vsnprintf(&c, 1, fmt, ap2);
2276 va_end(ap2);
2278 if (alen <= 0) {
2279 /* Either the vsnprintf failed or the format resulted in
2280 * no characters being formatted. In the former case, we
2281 * ought to return NULL, in the latter we ought to return
2282 * the original string. Most current callers of this
2283 * function expect it to never return NULL.
2285 return s;
2288 s = talloc_realloc(NULL, s, char, slen + alen + 1);
2289 if (!s) return NULL;
2291 va_copy(ap2, ap);
2292 vsnprintf(s + slen, alen + 1, fmt, ap2);
2293 va_end(ap2);
2295 _talloc_set_name_const(s, s);
2296 return s;
2300 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2301 * and return @p s, which may have moved. Good for gradually
2302 * accumulating output into a string buffer. Appends at the end
2303 * of the string.
2305 _PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
2307 if (unlikely(!s)) {
2308 return talloc_vasprintf(NULL, fmt, ap);
2311 return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
2315 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2316 * and return @p s, which may have moved. Always appends at the
2317 * end of the talloc'ed buffer, not the end of the string.
2319 _PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
2321 size_t slen;
2323 if (unlikely(!s)) {
2324 return talloc_vasprintf(NULL, fmt, ap);
2327 slen = talloc_get_size(s);
2328 if (likely(slen > 0)) {
2329 slen--;
2332 return __talloc_vaslenprintf_append(s, slen, fmt, ap);
2336 Realloc @p s to append the formatted result of @p fmt and return @p
2337 s, which may have moved. Good for gradually accumulating output
2338 into a string buffer.
2340 _PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
2342 va_list ap;
2344 va_start(ap, fmt);
2345 s = talloc_vasprintf_append(s, fmt, ap);
2346 va_end(ap);
2347 return s;
2351 Realloc @p s to append the formatted result of @p fmt and return @p
2352 s, which may have moved. Good for gradually accumulating output
2353 into a buffer.
2355 _PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
2357 va_list ap;
2359 va_start(ap, fmt);
2360 s = talloc_vasprintf_append_buffer(s, fmt, ap);
2361 va_end(ap);
2362 return s;
2366 alloc an array, checking for integer overflow in the array size
2368 _PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2370 if (count >= MAX_TALLOC_SIZE/el_size) {
2371 return NULL;
2373 return _talloc_named_const(ctx, el_size * count, name);
2377 alloc an zero array, checking for integer overflow in the array size
2379 _PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2381 if (count >= MAX_TALLOC_SIZE/el_size) {
2382 return NULL;
2384 return _talloc_zero(ctx, el_size * count, name);
2388 realloc an array, checking for integer overflow in the array size
2390 _PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
2392 if (count >= MAX_TALLOC_SIZE/el_size) {
2393 return NULL;
2395 return _talloc_realloc(ctx, ptr, el_size * count, name);
2399 a function version of talloc_realloc(), so it can be passed as a function pointer
2400 to libraries that want a realloc function (a realloc function encapsulates
2401 all the basic capabilities of an allocation library, which is why this is useful)
2403 _PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
2405 return _talloc_realloc(context, ptr, size, NULL);
2409 static int talloc_autofree_destructor(void *ptr)
2411 autofree_context = NULL;
2412 return 0;
2415 static void talloc_autofree(void)
2417 talloc_free(autofree_context);
2421 return a context which will be auto-freed on exit
2422 this is useful for reducing the noise in leak reports
2424 _PUBLIC_ void *talloc_autofree_context(void)
2426 if (autofree_context == NULL) {
2427 autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
2428 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
2429 atexit(talloc_autofree);
2431 return autofree_context;
2434 _PUBLIC_ size_t talloc_get_size(const void *context)
2436 struct talloc_chunk *tc;
2438 if (context == NULL) {
2439 context = null_context;
2441 if (context == NULL) {
2442 return 0;
2445 tc = talloc_chunk_from_ptr(context);
2447 return tc->size;
2451 find a parent of this context that has the given name, if any
2453 _PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
2455 struct talloc_chunk *tc;
2457 if (context == NULL) {
2458 return NULL;
2461 tc = talloc_chunk_from_ptr(context);
2462 while (tc) {
2463 if (tc->name && strcmp(tc->name, name) == 0) {
2464 return TC_PTR_FROM_CHUNK(tc);
2466 while (tc && tc->prev) tc = tc->prev;
2467 if (tc) {
2468 tc = tc->parent;
2471 return NULL;
2475 show the parentage of a context
2477 _PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
2479 struct talloc_chunk *tc;
2481 if (context == NULL) {
2482 fprintf(file, "talloc no parents for NULL\n");
2483 return;
2486 tc = talloc_chunk_from_ptr(context);
2487 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
2488 while (tc) {
2489 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
2490 while (tc && tc->prev) tc = tc->prev;
2491 if (tc) {
2492 tc = tc->parent;
2495 fflush(file);
2499 return 1 if ptr is a parent of context
2501 static int _talloc_is_parent(const void *context, const void *ptr, int depth)
2503 struct talloc_chunk *tc;
2505 if (context == NULL) {
2506 return 0;
2509 tc = talloc_chunk_from_ptr(context);
2510 while (tc && depth > 0) {
2511 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
2512 while (tc && tc->prev) tc = tc->prev;
2513 if (tc) {
2514 tc = tc->parent;
2515 depth--;
2518 return 0;
2522 return 1 if ptr is a parent of context
2524 _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
2526 return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
2530 return the total size of memory used by this context and all children
2532 static size_t _talloc_total_limit_size(const void *ptr,
2533 struct talloc_memlimit *old_limit,
2534 struct talloc_memlimit *new_limit)
2536 return _talloc_total_mem_internal(ptr, TOTAL_MEM_LIMIT,
2537 old_limit, new_limit);
2540 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size)
2542 struct talloc_memlimit *l;
2544 for (l = limit; l != NULL; l = l->upper) {
2545 if (l->max_size != 0 &&
2546 ((l->max_size <= l->cur_size) ||
2547 (l->max_size - l->cur_size < TC_HDR_SIZE+size))) {
2548 return false;
2552 return true;
2555 static bool talloc_memlimit_update(struct talloc_memlimit *limit,
2556 size_t old_size, size_t new_size)
2558 struct talloc_memlimit *l;
2559 ssize_t d;
2561 if (old_size == 0) {
2562 d = new_size + TC_HDR_SIZE;
2563 } else {
2564 d = new_size - old_size;
2566 for (l = limit; l != NULL; l = l->upper) {
2567 ssize_t new_cur_size = l->cur_size + d;
2568 if (new_cur_size < 0) {
2569 return false;
2571 l->cur_size = new_cur_size;
2574 return true;
2577 _PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size)
2579 struct talloc_chunk *tc = talloc_chunk_from_ptr(ctx);
2580 struct talloc_memlimit *orig_limit;
2581 struct talloc_memlimit *limit = NULL;
2583 if (tc->limit && tc->limit->parent == tc) {
2584 tc->limit->max_size = max_size;
2585 return 0;
2587 orig_limit = tc->limit;
2589 limit = malloc(sizeof(struct talloc_memlimit));
2590 if (limit == NULL) {
2591 return 1;
2593 limit->parent = tc;
2594 limit->max_size = max_size;
2595 limit->cur_size = _talloc_total_limit_size(ctx, tc->limit, limit);
2597 if (orig_limit) {
2598 limit->upper = orig_limit;
2599 } else {
2600 limit->upper = NULL;
2603 return 0;