tevent: preferr the write handler if there're two possible handlers registered with...
[Samba/bjacke.git] / lib / talloc / talloc.c
blob3e33fc0fad5122e945dfbfb3017cd09834419208
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--;
934 if (unlikely(pool->hdr.object_count == 0)) {
935 TC_INVALIDATE_FULL_CHUNK(tc);
936 free(tc);
938 } else if (tc->flags & TALLOC_FLAG_POOLMEM) {
939 _talloc_free_poolmem(tc, location);
940 } else {
941 TC_INVALIDATE_FULL_CHUNK(tc);
942 free(tc);
944 return 0;
947 static size_t _talloc_total_limit_size(const void *ptr,
948 struct talloc_memlimit *old_limit,
949 struct talloc_memlimit *new_limit);
952 move a lump of memory from one talloc context to another return the
953 ptr on success, or NULL if it could not be transferred.
954 passing NULL as ptr will always return NULL with no side effects.
956 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr)
958 struct talloc_chunk *tc, *new_tc;
959 size_t ctx_size = 0;
961 if (unlikely(!ptr)) {
962 return NULL;
965 if (unlikely(new_ctx == NULL)) {
966 new_ctx = null_context;
969 tc = talloc_chunk_from_ptr(ptr);
971 if (tc->limit != NULL) {
973 ctx_size = _talloc_total_limit_size(ptr, NULL, NULL);
975 if (!talloc_memlimit_update(tc->limit->upper, ctx_size, 0)) {
976 talloc_abort("cur_size memlimit counter not correct!");
977 errno = EINVAL;
978 return NULL;
981 if (tc->limit->parent == tc) {
982 tc->limit->upper = NULL;
983 } else {
984 tc->limit = NULL;
988 if (unlikely(new_ctx == NULL)) {
989 if (tc->parent) {
990 _TLIST_REMOVE(tc->parent->child, tc);
991 if (tc->parent->child) {
992 tc->parent->child->parent = tc->parent;
994 } else {
995 if (tc->prev) tc->prev->next = tc->next;
996 if (tc->next) tc->next->prev = tc->prev;
999 tc->parent = tc->next = tc->prev = NULL;
1000 return discard_const_p(void, ptr);
1003 new_tc = talloc_chunk_from_ptr(new_ctx);
1005 if (unlikely(tc == new_tc || tc->parent == new_tc)) {
1006 return discard_const_p(void, ptr);
1009 if (tc->parent) {
1010 _TLIST_REMOVE(tc->parent->child, tc);
1011 if (tc->parent->child) {
1012 tc->parent->child->parent = tc->parent;
1014 } else {
1015 if (tc->prev) tc->prev->next = tc->next;
1016 if (tc->next) tc->next->prev = tc->prev;
1017 tc->prev = tc->next = NULL;
1020 tc->parent = new_tc;
1021 if (new_tc->child) new_tc->child->parent = NULL;
1022 _TLIST_ADD(new_tc->child, tc);
1024 if (tc->limit || new_tc->limit) {
1025 ctx_size = _talloc_total_limit_size(ptr, tc->limit,
1026 new_tc->limit);
1029 if (new_tc->limit) {
1030 struct talloc_memlimit *l;
1032 for (l = new_tc->limit; l != NULL; l = l->upper) {
1033 l->cur_size += ctx_size;
1037 return discard_const_p(void, ptr);
1041 move a lump of memory from one talloc context to another return the
1042 ptr on success, or NULL if it could not be transferred.
1043 passing NULL as ptr will always return NULL with no side effects.
1045 _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
1047 struct talloc_chunk *tc;
1049 if (unlikely(ptr == NULL)) {
1050 return NULL;
1053 tc = talloc_chunk_from_ptr(ptr);
1055 if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
1056 struct talloc_reference_handle *h;
1058 talloc_log("WARNING: talloc_steal with references at %s\n",
1059 location);
1061 for (h=tc->refs; h; h=h->next) {
1062 talloc_log("\treference at %s\n",
1063 h->location);
1067 #if 0
1068 /* this test is probably too expensive to have on in the
1069 normal build, but it useful for debugging */
1070 if (talloc_is_parent(new_ctx, ptr)) {
1071 talloc_log("WARNING: stealing into talloc child at %s\n", location);
1073 #endif
1075 return _talloc_steal_internal(new_ctx, ptr);
1079 this is like a talloc_steal(), but you must supply the old
1080 parent. This resolves the ambiguity in a talloc_steal() which is
1081 called on a context that has more than one parent (via references)
1083 The old parent can be either a reference or a parent
1085 _PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
1087 struct talloc_chunk *tc;
1088 struct talloc_reference_handle *h;
1090 if (unlikely(ptr == NULL)) {
1091 return NULL;
1094 if (old_parent == talloc_parent(ptr)) {
1095 return _talloc_steal_internal(new_parent, ptr);
1098 tc = talloc_chunk_from_ptr(ptr);
1099 for (h=tc->refs;h;h=h->next) {
1100 if (talloc_parent(h) == old_parent) {
1101 if (_talloc_steal_internal(new_parent, h) != h) {
1102 return NULL;
1104 return discard_const_p(void, ptr);
1108 /* it wasn't a parent */
1109 return NULL;
1113 remove a secondary reference to a pointer. This undo's what
1114 talloc_reference() has done. The context and pointer arguments
1115 must match those given to a talloc_reference()
1117 static inline int talloc_unreference(const void *context, const void *ptr)
1119 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1120 struct talloc_reference_handle *h;
1122 if (unlikely(context == NULL)) {
1123 context = null_context;
1126 for (h=tc->refs;h;h=h->next) {
1127 struct talloc_chunk *p = talloc_parent_chunk(h);
1128 if (p == NULL) {
1129 if (context == NULL) break;
1130 } else if (TC_PTR_FROM_CHUNK(p) == context) {
1131 break;
1134 if (h == NULL) {
1135 return -1;
1138 return _talloc_free_internal(h, __location__);
1142 remove a specific parent context from a pointer. This is a more
1143 controlled variant of talloc_free()
1145 _PUBLIC_ int talloc_unlink(const void *context, void *ptr)
1147 struct talloc_chunk *tc_p, *new_p, *tc_c;
1148 void *new_parent;
1150 if (ptr == NULL) {
1151 return -1;
1154 if (context == NULL) {
1155 context = null_context;
1158 if (talloc_unreference(context, ptr) == 0) {
1159 return 0;
1162 if (context != NULL) {
1163 tc_c = talloc_chunk_from_ptr(context);
1164 } else {
1165 tc_c = NULL;
1167 if (tc_c != talloc_parent_chunk(ptr)) {
1168 return -1;
1171 tc_p = talloc_chunk_from_ptr(ptr);
1173 if (tc_p->refs == NULL) {
1174 return _talloc_free_internal(ptr, __location__);
1177 new_p = talloc_parent_chunk(tc_p->refs);
1178 if (new_p) {
1179 new_parent = TC_PTR_FROM_CHUNK(new_p);
1180 } else {
1181 new_parent = NULL;
1184 if (talloc_unreference(new_parent, ptr) != 0) {
1185 return -1;
1188 _talloc_steal_internal(new_parent, ptr);
1190 return 0;
1194 add a name to an existing pointer - va_list version
1196 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1198 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
1200 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1201 tc->name = talloc_vasprintf(ptr, fmt, ap);
1202 if (likely(tc->name)) {
1203 _talloc_set_name_const(tc->name, ".name");
1205 return tc->name;
1209 add a name to an existing pointer
1211 _PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
1213 const char *name;
1214 va_list ap;
1215 va_start(ap, fmt);
1216 name = talloc_set_name_v(ptr, fmt, ap);
1217 va_end(ap);
1218 return name;
1223 create a named talloc pointer. Any talloc pointer can be named, and
1224 talloc_named() operates just like talloc() except that it allows you
1225 to name the pointer.
1227 _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
1229 va_list ap;
1230 void *ptr;
1231 const char *name;
1233 ptr = __talloc(context, size);
1234 if (unlikely(ptr == NULL)) return NULL;
1236 va_start(ap, fmt);
1237 name = talloc_set_name_v(ptr, fmt, ap);
1238 va_end(ap);
1240 if (unlikely(name == NULL)) {
1241 _talloc_free_internal(ptr, __location__);
1242 return NULL;
1245 return ptr;
1249 return the name of a talloc ptr, or "UNNAMED"
1251 _PUBLIC_ const char *talloc_get_name(const void *ptr)
1253 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1254 if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
1255 return ".reference";
1257 if (likely(tc->name)) {
1258 return tc->name;
1260 return "UNNAMED";
1265 check if a pointer has the given name. If it does, return the pointer,
1266 otherwise return NULL
1268 _PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
1270 const char *pname;
1271 if (unlikely(ptr == NULL)) return NULL;
1272 pname = talloc_get_name(ptr);
1273 if (likely(pname == name || strcmp(pname, name) == 0)) {
1274 return discard_const_p(void, ptr);
1276 return NULL;
1279 static void talloc_abort_type_mismatch(const char *location,
1280 const char *name,
1281 const char *expected)
1283 const char *reason;
1285 reason = talloc_asprintf(NULL,
1286 "%s: Type mismatch: name[%s] expected[%s]",
1287 location,
1288 name?name:"NULL",
1289 expected);
1290 if (!reason) {
1291 reason = "Type mismatch";
1294 talloc_abort(reason);
1297 _PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
1299 const char *pname;
1301 if (unlikely(ptr == NULL)) {
1302 talloc_abort_type_mismatch(location, NULL, name);
1303 return NULL;
1306 pname = talloc_get_name(ptr);
1307 if (likely(pname == name || strcmp(pname, name) == 0)) {
1308 return discard_const_p(void, ptr);
1311 talloc_abort_type_mismatch(location, pname, name);
1312 return NULL;
1316 this is for compatibility with older versions of talloc
1318 _PUBLIC_ void *talloc_init(const char *fmt, ...)
1320 va_list ap;
1321 void *ptr;
1322 const char *name;
1324 ptr = __talloc(NULL, 0);
1325 if (unlikely(ptr == NULL)) return NULL;
1327 va_start(ap, fmt);
1328 name = talloc_set_name_v(ptr, fmt, ap);
1329 va_end(ap);
1331 if (unlikely(name == NULL)) {
1332 _talloc_free_internal(ptr, __location__);
1333 return NULL;
1336 return ptr;
1339 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
1340 void *ptr,
1341 const char *location)
1343 while (tc->child) {
1344 /* we need to work out who will own an abandoned child
1345 if it cannot be freed. In priority order, the first
1346 choice is owner of any remaining reference to this
1347 pointer, the second choice is our parent, and the
1348 final choice is the null context. */
1349 void *child = TC_PTR_FROM_CHUNK(tc->child);
1350 const void *new_parent = null_context;
1351 if (unlikely(tc->child->refs)) {
1352 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1353 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1355 if (unlikely(_talloc_free_internal(child, location) == -1)) {
1356 if (new_parent == null_context) {
1357 struct talloc_chunk *p = talloc_parent_chunk(ptr);
1358 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1360 _talloc_steal_internal(new_parent, child);
1366 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1367 should probably not be used in new code. It's in here to keep the talloc
1368 code consistent across Samba 3 and 4.
1370 _PUBLIC_ void talloc_free_children(void *ptr)
1372 struct talloc_chunk *tc_name = NULL;
1373 struct talloc_chunk *tc;
1375 if (unlikely(ptr == NULL)) {
1376 return;
1379 tc = talloc_chunk_from_ptr(ptr);
1381 /* we do not want to free the context name if it is a child .. */
1382 if (likely(tc->child)) {
1383 for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
1384 if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
1386 if (tc_name) {
1387 _TLIST_REMOVE(tc->child, tc_name);
1388 if (tc->child) {
1389 tc->child->parent = tc;
1394 _talloc_free_children_internal(tc, ptr, __location__);
1396 /* .. so we put it back after all other children have been freed */
1397 if (tc_name) {
1398 if (tc->child) {
1399 tc->child->parent = NULL;
1401 tc_name->parent = tc;
1402 _TLIST_ADD(tc->child, tc_name);
1407 Allocate a bit of memory as a child of an existing pointer
1409 _PUBLIC_ void *_talloc(const void *context, size_t size)
1411 return __talloc(context, size);
1415 externally callable talloc_set_name_const()
1417 _PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
1419 _talloc_set_name_const(ptr, name);
1423 create a named talloc pointer. Any talloc pointer can be named, and
1424 talloc_named() operates just like talloc() except that it allows you
1425 to name the pointer.
1427 _PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
1429 return _talloc_named_const(context, size, name);
1433 free a talloc pointer. This also frees all child pointers of this
1434 pointer recursively
1436 return 0 if the memory is actually freed, otherwise -1. The memory
1437 will not be freed if the ref_count is > 1 or the destructor (if
1438 any) returns non-zero
1440 _PUBLIC_ int _talloc_free(void *ptr, const char *location)
1442 struct talloc_chunk *tc;
1444 if (unlikely(ptr == NULL)) {
1445 return -1;
1448 tc = talloc_chunk_from_ptr(ptr);
1450 if (unlikely(tc->refs != NULL)) {
1451 struct talloc_reference_handle *h;
1453 if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
1454 /* in this case we do know which parent should
1455 get this pointer, as there is really only
1456 one parent */
1457 return talloc_unlink(null_context, ptr);
1460 talloc_log("ERROR: talloc_free with references at %s\n",
1461 location);
1463 for (h=tc->refs; h; h=h->next) {
1464 talloc_log("\treference at %s\n",
1465 h->location);
1467 return -1;
1470 return _talloc_free_internal(ptr, location);
1476 A talloc version of realloc. The context argument is only used if
1477 ptr is NULL
1479 _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
1481 struct talloc_chunk *tc;
1482 void *new_ptr;
1483 bool malloced = false;
1484 union talloc_pool_chunk *pool_tc = NULL;
1486 /* size zero is equivalent to free() */
1487 if (unlikely(size == 0)) {
1488 talloc_unlink(context, ptr);
1489 return NULL;
1492 if (unlikely(size >= MAX_TALLOC_SIZE)) {
1493 return NULL;
1496 /* realloc(NULL) is equivalent to malloc() */
1497 if (ptr == NULL) {
1498 return _talloc_named_const(context, size, name);
1501 tc = talloc_chunk_from_ptr(ptr);
1503 /* don't allow realloc on referenced pointers */
1504 if (unlikely(tc->refs)) {
1505 return NULL;
1508 /* don't let anybody try to realloc a talloc_pool */
1509 if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
1510 return NULL;
1513 if (tc->limit && (size - tc->size > 0)) {
1514 if (!talloc_memlimit_check(tc->limit, (size - tc->size))) {
1515 errno = ENOMEM;
1516 return NULL;
1520 /* handle realloc inside a talloc_pool */
1521 if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
1522 pool_tc = (union talloc_pool_chunk *)tc->pool;
1525 #if (ALWAYS_REALLOC == 0)
1526 /* don't shrink if we have less than 1k to gain */
1527 if (size < tc->size && tc->limit == NULL) {
1528 if (pool_tc) {
1529 void *next_tc = tc_next_chunk(tc);
1530 TC_INVALIDATE_SHRINK_CHUNK(tc, size);
1531 tc->size = size;
1532 if (next_tc == pool_tc->hdr.c.pool) {
1533 /* note: tc->size has changed, so this works */
1534 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1536 return ptr;
1537 } else if ((tc->size - size) < 1024) {
1539 * if we call TC_INVALIDATE_SHRINK_CHUNK() here
1540 * we would need to call TC_UNDEFINE_GROW_CHUNK()
1541 * after each realloc call, which slows down
1542 * testing a lot :-(.
1544 * That is why we only mark memory as undefined here.
1546 TC_UNDEFINE_SHRINK_CHUNK(tc, size);
1548 /* do not shrink if we have less than 1k to gain */
1549 tc->size = size;
1550 return ptr;
1552 } else if (tc->size == size) {
1554 * do not change the pointer if it is exactly
1555 * the same size.
1557 return ptr;
1559 #endif
1561 /* by resetting magic we catch users of the old memory */
1562 tc->flags |= TALLOC_FLAG_FREE;
1564 #if ALWAYS_REALLOC
1565 if (pool_tc) {
1566 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1567 pool_tc->hdr.object_count--;
1569 if (new_ptr == NULL) {
1570 new_ptr = malloc(TC_HDR_SIZE+size);
1571 malloced = true;
1574 if (new_ptr) {
1575 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1576 TC_INVALIDATE_FULL_CHUNK(tc);
1578 } else {
1579 new_ptr = malloc(size + TC_HDR_SIZE);
1580 if (new_ptr) {
1581 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1582 free(tc);
1585 #else
1586 if (pool_tc) {
1587 void *next_tc = tc_next_chunk(tc);
1588 size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size);
1589 size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
1590 size_t space_needed;
1591 size_t space_left;
1592 unsigned int chunk_count = pool_tc->hdr.object_count;
1594 if (!(pool_tc->hdr.c.flags & TALLOC_FLAG_FREE)) {
1595 chunk_count -= 1;
1598 if (chunk_count == 1) {
1600 * optimize for the case where 'tc' is the only
1601 * chunk in the pool.
1603 char *start = tc_pool_first_chunk(pool_tc);
1604 space_needed = new_chunk_size;
1605 space_left = (char *)tc_pool_end(pool_tc) - start;
1607 if (space_left >= space_needed) {
1608 size_t old_used = TC_HDR_SIZE + tc->size;
1609 size_t new_used = TC_HDR_SIZE + size;
1610 new_ptr = start;
1611 memmove(new_ptr, tc, old_used);
1613 tc = (struct talloc_chunk *)new_ptr;
1614 TC_UNDEFINE_GROW_CHUNK(tc, size);
1617 * first we do not align the pool pointer
1618 * because we want to invalidate the padding
1619 * too.
1621 pool_tc->hdr.c.pool = new_used + (char *)new_ptr;
1622 tc_invalidate_pool(pool_tc);
1624 /* now the aligned pointer */
1625 pool_tc->hdr.c.pool = new_chunk_size + (char *)new_ptr;
1626 goto got_new_ptr;
1629 next_tc = NULL;
1632 if (new_chunk_size == old_chunk_size) {
1633 TC_UNDEFINE_GROW_CHUNK(tc, size);
1634 tc->flags &= ~TALLOC_FLAG_FREE;
1635 if (!talloc_memlimit_update(tc->limit,
1636 tc->size, size)) {
1637 talloc_abort("cur_size memlimit counter not"
1638 " correct!");
1639 errno = EINVAL;
1640 return NULL;
1643 tc->size = size;
1644 return ptr;
1647 if (next_tc == pool_tc->hdr.c.pool) {
1649 * optimize for the case where 'tc' is the last
1650 * chunk in the pool.
1652 space_needed = new_chunk_size - old_chunk_size;
1653 space_left = tc_pool_space_left(pool_tc);
1655 if (space_left >= space_needed) {
1656 TC_UNDEFINE_GROW_CHUNK(tc, size);
1657 tc->flags &= ~TALLOC_FLAG_FREE;
1658 if (!talloc_memlimit_update(tc->limit,
1659 tc->size, size)) {
1660 talloc_abort("cur_size memlimit "
1661 "counter not correct!");
1662 errno = EINVAL;
1663 return NULL;
1665 tc->size = size;
1666 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1667 return ptr;
1671 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1673 if (new_ptr == NULL) {
1674 new_ptr = malloc(TC_HDR_SIZE+size);
1675 malloced = true;
1678 if (new_ptr) {
1679 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1681 _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
1684 else {
1685 new_ptr = realloc(tc, size + TC_HDR_SIZE);
1687 got_new_ptr:
1688 #endif
1689 if (unlikely(!new_ptr)) {
1690 tc->flags &= ~TALLOC_FLAG_FREE;
1691 return NULL;
1694 tc = (struct talloc_chunk *)new_ptr;
1695 tc->flags &= ~TALLOC_FLAG_FREE;
1696 if (malloced) {
1697 tc->flags &= ~TALLOC_FLAG_POOLMEM;
1699 if (tc->parent) {
1700 tc->parent->child = tc;
1702 if (tc->child) {
1703 tc->child->parent = tc;
1706 if (tc->prev) {
1707 tc->prev->next = tc;
1709 if (tc->next) {
1710 tc->next->prev = tc;
1713 if (!talloc_memlimit_update(tc->limit, tc->size, size)) {
1714 talloc_abort("cur_size memlimit counter not correct!");
1715 errno = EINVAL;
1716 return NULL;
1718 tc->size = size;
1719 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
1721 return TC_PTR_FROM_CHUNK(tc);
1725 a wrapper around talloc_steal() for situations where you are moving a pointer
1726 between two structures, and want the old pointer to be set to NULL
1728 _PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
1730 const void **pptr = discard_const_p(const void *,_pptr);
1731 void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
1732 (*pptr) = NULL;
1733 return ret;
1736 enum talloc_mem_count_type {
1737 TOTAL_MEM_SIZE,
1738 TOTAL_MEM_BLOCKS,
1739 TOTAL_MEM_LIMIT,
1742 static size_t _talloc_total_mem_internal(const void *ptr,
1743 enum talloc_mem_count_type type,
1744 struct talloc_memlimit *old_limit,
1745 struct talloc_memlimit *new_limit)
1747 size_t total = 0;
1748 struct talloc_chunk *c, *tc;
1750 if (ptr == NULL) {
1751 ptr = null_context;
1753 if (ptr == NULL) {
1754 return 0;
1757 tc = talloc_chunk_from_ptr(ptr);
1759 if (old_limit || new_limit) {
1760 if (tc->limit && tc->limit->upper == old_limit) {
1761 tc->limit->upper = new_limit;
1765 /* optimize in the memlimits case */
1766 if (type == TOTAL_MEM_LIMIT &&
1767 tc->limit != NULL &&
1768 tc->limit != old_limit &&
1769 tc->limit->parent == tc) {
1770 return tc->limit->cur_size;
1773 if (tc->flags & TALLOC_FLAG_LOOP) {
1774 return 0;
1777 tc->flags |= TALLOC_FLAG_LOOP;
1779 if (old_limit || new_limit) {
1780 if (old_limit == tc->limit) {
1781 tc->limit = new_limit;
1785 switch (type) {
1786 case TOTAL_MEM_SIZE:
1787 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1788 total = tc->size;
1790 break;
1791 case TOTAL_MEM_BLOCKS:
1792 total++;
1793 break;
1794 case TOTAL_MEM_LIMIT:
1795 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1796 total = tc->size + TC_HDR_SIZE;
1798 break;
1800 for (c = tc->child; c; c = c->next) {
1801 total += _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c), type,
1802 old_limit, new_limit);
1805 tc->flags &= ~TALLOC_FLAG_LOOP;
1807 return total;
1811 return the total size of a talloc pool (subtree)
1813 _PUBLIC_ size_t talloc_total_size(const void *ptr)
1815 return _talloc_total_mem_internal(ptr, TOTAL_MEM_SIZE, NULL, NULL);
1819 return the total number of blocks in a talloc pool (subtree)
1821 _PUBLIC_ size_t talloc_total_blocks(const void *ptr)
1823 return _talloc_total_mem_internal(ptr, TOTAL_MEM_BLOCKS, NULL, NULL);
1827 return the number of external references to a pointer
1829 _PUBLIC_ size_t talloc_reference_count(const void *ptr)
1831 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1832 struct talloc_reference_handle *h;
1833 size_t ret = 0;
1835 for (h=tc->refs;h;h=h->next) {
1836 ret++;
1838 return ret;
1842 report on memory usage by all children of a pointer, giving a full tree view
1844 _PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1845 void (*callback)(const void *ptr,
1846 int depth, int max_depth,
1847 int is_ref,
1848 void *private_data),
1849 void *private_data)
1851 struct talloc_chunk *c, *tc;
1853 if (ptr == NULL) {
1854 ptr = null_context;
1856 if (ptr == NULL) return;
1858 tc = talloc_chunk_from_ptr(ptr);
1860 if (tc->flags & TALLOC_FLAG_LOOP) {
1861 return;
1864 callback(ptr, depth, max_depth, 0, private_data);
1866 if (max_depth >= 0 && depth >= max_depth) {
1867 return;
1870 tc->flags |= TALLOC_FLAG_LOOP;
1871 for (c=tc->child;c;c=c->next) {
1872 if (c->name == TALLOC_MAGIC_REFERENCE) {
1873 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1874 callback(h->ptr, depth + 1, max_depth, 1, private_data);
1875 } else {
1876 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1879 tc->flags &= ~TALLOC_FLAG_LOOP;
1882 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1884 const char *name = talloc_get_name(ptr);
1885 struct talloc_chunk *tc;
1886 FILE *f = (FILE *)_f;
1888 if (is_ref) {
1889 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1890 return;
1893 tc = talloc_chunk_from_ptr(ptr);
1894 if (tc->limit && tc->limit->parent == tc) {
1895 fprintf(f, "%*s%-30s is a memlimit context"
1896 " (max_size = %lu bytes, cur_size = %lu bytes)\n",
1897 depth*4, "",
1898 name,
1899 (unsigned long)tc->limit->max_size,
1900 (unsigned long)tc->limit->cur_size);
1903 if (depth == 0) {
1904 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1905 (max_depth < 0 ? "full " :""), name,
1906 (unsigned long)talloc_total_size(ptr),
1907 (unsigned long)talloc_total_blocks(ptr));
1908 return;
1911 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1912 depth*4, "",
1913 name,
1914 (unsigned long)talloc_total_size(ptr),
1915 (unsigned long)talloc_total_blocks(ptr),
1916 (int)talloc_reference_count(ptr), ptr);
1918 #if 0
1919 fprintf(f, "content: ");
1920 if (talloc_total_size(ptr)) {
1921 int tot = talloc_total_size(ptr);
1922 int i;
1924 for (i = 0; i < tot; i++) {
1925 if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1926 fprintf(f, "%c", ((char *)ptr)[i]);
1927 } else {
1928 fprintf(f, "~%02x", ((char *)ptr)[i]);
1932 fprintf(f, "\n");
1933 #endif
1937 report on memory usage by all children of a pointer, giving a full tree view
1939 _PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1941 if (f) {
1942 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1943 fflush(f);
1948 report on memory usage by all children of a pointer, giving a full tree view
1950 _PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
1952 talloc_report_depth_file(ptr, 0, -1, f);
1956 report on memory usage by all children of a pointer
1958 _PUBLIC_ void talloc_report(const void *ptr, FILE *f)
1960 talloc_report_depth_file(ptr, 0, 1, f);
1964 report on any memory hanging off the null context
1966 static void talloc_report_null(void)
1968 if (talloc_total_size(null_context) != 0) {
1969 talloc_report(null_context, stderr);
1974 report on any memory hanging off the null context
1976 static void talloc_report_null_full(void)
1978 if (talloc_total_size(null_context) != 0) {
1979 talloc_report_full(null_context, stderr);
1984 enable tracking of the NULL context
1986 _PUBLIC_ void talloc_enable_null_tracking(void)
1988 if (null_context == NULL) {
1989 null_context = _talloc_named_const(NULL, 0, "null_context");
1990 if (autofree_context != NULL) {
1991 talloc_reparent(NULL, null_context, autofree_context);
1997 enable tracking of the NULL context, not moving the autofree context
1998 into the NULL context. This is needed for the talloc testsuite
2000 _PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
2002 if (null_context == NULL) {
2003 null_context = _talloc_named_const(NULL, 0, "null_context");
2008 disable tracking of the NULL context
2010 _PUBLIC_ void talloc_disable_null_tracking(void)
2012 if (null_context != NULL) {
2013 /* we have to move any children onto the real NULL
2014 context */
2015 struct talloc_chunk *tc, *tc2;
2016 tc = talloc_chunk_from_ptr(null_context);
2017 for (tc2 = tc->child; tc2; tc2=tc2->next) {
2018 if (tc2->parent == tc) tc2->parent = NULL;
2019 if (tc2->prev == tc) tc2->prev = NULL;
2021 for (tc2 = tc->next; tc2; tc2=tc2->next) {
2022 if (tc2->parent == tc) tc2->parent = NULL;
2023 if (tc2->prev == tc) tc2->prev = NULL;
2025 tc->child = NULL;
2026 tc->next = NULL;
2028 talloc_free(null_context);
2029 null_context = NULL;
2033 enable leak reporting on exit
2035 _PUBLIC_ void talloc_enable_leak_report(void)
2037 talloc_enable_null_tracking();
2038 atexit(talloc_report_null);
2042 enable full leak reporting on exit
2044 _PUBLIC_ void talloc_enable_leak_report_full(void)
2046 talloc_enable_null_tracking();
2047 atexit(talloc_report_null_full);
2051 talloc and zero memory.
2053 _PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
2055 void *p = _talloc_named_const(ctx, size, name);
2057 if (p) {
2058 memset(p, '\0', size);
2061 return p;
2065 memdup with a talloc.
2067 _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
2069 void *newp = _talloc_named_const(t, size, name);
2071 if (likely(newp)) {
2072 memcpy(newp, p, size);
2075 return newp;
2078 static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
2080 char *ret;
2082 ret = (char *)__talloc(t, len + 1);
2083 if (unlikely(!ret)) return NULL;
2085 memcpy(ret, p, len);
2086 ret[len] = 0;
2088 _talloc_set_name_const(ret, ret);
2089 return ret;
2093 strdup with a talloc
2095 _PUBLIC_ char *talloc_strdup(const void *t, const char *p)
2097 if (unlikely(!p)) return NULL;
2098 return __talloc_strlendup(t, p, strlen(p));
2102 strndup with a talloc
2104 _PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
2106 if (unlikely(!p)) return NULL;
2107 return __talloc_strlendup(t, p, strnlen(p, n));
2110 static inline char *__talloc_strlendup_append(char *s, size_t slen,
2111 const char *a, size_t alen)
2113 char *ret;
2115 ret = talloc_realloc(NULL, s, char, slen + alen + 1);
2116 if (unlikely(!ret)) return NULL;
2118 /* append the string and the trailing \0 */
2119 memcpy(&ret[slen], a, alen);
2120 ret[slen+alen] = 0;
2122 _talloc_set_name_const(ret, ret);
2123 return ret;
2127 * Appends at the end of the string.
2129 _PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
2131 if (unlikely(!s)) {
2132 return talloc_strdup(NULL, a);
2135 if (unlikely(!a)) {
2136 return s;
2139 return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
2143 * Appends at the end of the talloc'ed buffer,
2144 * not the end of the string.
2146 _PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
2148 size_t slen;
2150 if (unlikely(!s)) {
2151 return talloc_strdup(NULL, a);
2154 if (unlikely(!a)) {
2155 return s;
2158 slen = talloc_get_size(s);
2159 if (likely(slen > 0)) {
2160 slen--;
2163 return __talloc_strlendup_append(s, slen, a, strlen(a));
2167 * Appends at the end of the string.
2169 _PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
2171 if (unlikely(!s)) {
2172 return talloc_strndup(NULL, a, n);
2175 if (unlikely(!a)) {
2176 return s;
2179 return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
2183 * Appends at the end of the talloc'ed buffer,
2184 * not the end of the string.
2186 _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
2188 size_t slen;
2190 if (unlikely(!s)) {
2191 return talloc_strndup(NULL, a, n);
2194 if (unlikely(!a)) {
2195 return s;
2198 slen = talloc_get_size(s);
2199 if (likely(slen > 0)) {
2200 slen--;
2203 return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
2206 #ifndef HAVE_VA_COPY
2207 #ifdef HAVE___VA_COPY
2208 #define va_copy(dest, src) __va_copy(dest, src)
2209 #else
2210 #define va_copy(dest, src) (dest) = (src)
2211 #endif
2212 #endif
2214 _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
2216 int len;
2217 char *ret;
2218 va_list ap2;
2219 char c;
2221 /* this call looks strange, but it makes it work on older solaris boxes */
2222 va_copy(ap2, ap);
2223 len = vsnprintf(&c, 1, fmt, ap2);
2224 va_end(ap2);
2225 if (unlikely(len < 0)) {
2226 return NULL;
2229 ret = (char *)__talloc(t, len+1);
2230 if (unlikely(!ret)) return NULL;
2232 va_copy(ap2, ap);
2233 vsnprintf(ret, len+1, fmt, ap2);
2234 va_end(ap2);
2236 _talloc_set_name_const(ret, ret);
2237 return ret;
2242 Perform string formatting, and return a pointer to newly allocated
2243 memory holding the result, inside a memory pool.
2245 _PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
2247 va_list ap;
2248 char *ret;
2250 va_start(ap, fmt);
2251 ret = talloc_vasprintf(t, fmt, ap);
2252 va_end(ap);
2253 return ret;
2256 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2257 const char *fmt, va_list ap)
2258 PRINTF_ATTRIBUTE(3,0);
2260 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2261 const char *fmt, va_list ap)
2263 ssize_t alen;
2264 va_list ap2;
2265 char c;
2267 va_copy(ap2, ap);
2268 alen = vsnprintf(&c, 1, fmt, ap2);
2269 va_end(ap2);
2271 if (alen <= 0) {
2272 /* Either the vsnprintf failed or the format resulted in
2273 * no characters being formatted. In the former case, we
2274 * ought to return NULL, in the latter we ought to return
2275 * the original string. Most current callers of this
2276 * function expect it to never return NULL.
2278 return s;
2281 s = talloc_realloc(NULL, s, char, slen + alen + 1);
2282 if (!s) return NULL;
2284 va_copy(ap2, ap);
2285 vsnprintf(s + slen, alen + 1, fmt, ap2);
2286 va_end(ap2);
2288 _talloc_set_name_const(s, s);
2289 return s;
2293 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2294 * and return @p s, which may have moved. Good for gradually
2295 * accumulating output into a string buffer. Appends at the end
2296 * of the string.
2298 _PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
2300 if (unlikely(!s)) {
2301 return talloc_vasprintf(NULL, fmt, ap);
2304 return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
2308 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2309 * and return @p s, which may have moved. Always appends at the
2310 * end of the talloc'ed buffer, not the end of the string.
2312 _PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
2314 size_t slen;
2316 if (unlikely(!s)) {
2317 return talloc_vasprintf(NULL, fmt, ap);
2320 slen = talloc_get_size(s);
2321 if (likely(slen > 0)) {
2322 slen--;
2325 return __talloc_vaslenprintf_append(s, slen, fmt, ap);
2329 Realloc @p s to append the formatted result of @p fmt and return @p
2330 s, which may have moved. Good for gradually accumulating output
2331 into a string buffer.
2333 _PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
2335 va_list ap;
2337 va_start(ap, fmt);
2338 s = talloc_vasprintf_append(s, fmt, ap);
2339 va_end(ap);
2340 return s;
2344 Realloc @p s to append the formatted result of @p fmt and return @p
2345 s, which may have moved. Good for gradually accumulating output
2346 into a buffer.
2348 _PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
2350 va_list ap;
2352 va_start(ap, fmt);
2353 s = talloc_vasprintf_append_buffer(s, fmt, ap);
2354 va_end(ap);
2355 return s;
2359 alloc an array, checking for integer overflow in the array size
2361 _PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2363 if (count >= MAX_TALLOC_SIZE/el_size) {
2364 return NULL;
2366 return _talloc_named_const(ctx, el_size * count, name);
2370 alloc an zero array, checking for integer overflow in the array size
2372 _PUBLIC_ void *_talloc_zero_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_zero(ctx, el_size * count, name);
2381 realloc an array, checking for integer overflow in the array size
2383 _PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
2385 if (count >= MAX_TALLOC_SIZE/el_size) {
2386 return NULL;
2388 return _talloc_realloc(ctx, ptr, el_size * count, name);
2392 a function version of talloc_realloc(), so it can be passed as a function pointer
2393 to libraries that want a realloc function (a realloc function encapsulates
2394 all the basic capabilities of an allocation library, which is why this is useful)
2396 _PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
2398 return _talloc_realloc(context, ptr, size, NULL);
2402 static int talloc_autofree_destructor(void *ptr)
2404 autofree_context = NULL;
2405 return 0;
2408 static void talloc_autofree(void)
2410 talloc_free(autofree_context);
2414 return a context which will be auto-freed on exit
2415 this is useful for reducing the noise in leak reports
2417 _PUBLIC_ void *talloc_autofree_context(void)
2419 if (autofree_context == NULL) {
2420 autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
2421 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
2422 atexit(talloc_autofree);
2424 return autofree_context;
2427 _PUBLIC_ size_t talloc_get_size(const void *context)
2429 struct talloc_chunk *tc;
2431 if (context == NULL) {
2432 context = null_context;
2434 if (context == NULL) {
2435 return 0;
2438 tc = talloc_chunk_from_ptr(context);
2440 return tc->size;
2444 find a parent of this context that has the given name, if any
2446 _PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
2448 struct talloc_chunk *tc;
2450 if (context == NULL) {
2451 return NULL;
2454 tc = talloc_chunk_from_ptr(context);
2455 while (tc) {
2456 if (tc->name && strcmp(tc->name, name) == 0) {
2457 return TC_PTR_FROM_CHUNK(tc);
2459 while (tc && tc->prev) tc = tc->prev;
2460 if (tc) {
2461 tc = tc->parent;
2464 return NULL;
2468 show the parentage of a context
2470 _PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
2472 struct talloc_chunk *tc;
2474 if (context == NULL) {
2475 fprintf(file, "talloc no parents for NULL\n");
2476 return;
2479 tc = talloc_chunk_from_ptr(context);
2480 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
2481 while (tc) {
2482 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
2483 while (tc && tc->prev) tc = tc->prev;
2484 if (tc) {
2485 tc = tc->parent;
2488 fflush(file);
2492 return 1 if ptr is a parent of context
2494 static int _talloc_is_parent(const void *context, const void *ptr, int depth)
2496 struct talloc_chunk *tc;
2498 if (context == NULL) {
2499 return 0;
2502 tc = talloc_chunk_from_ptr(context);
2503 while (tc && depth > 0) {
2504 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
2505 while (tc && tc->prev) tc = tc->prev;
2506 if (tc) {
2507 tc = tc->parent;
2508 depth--;
2511 return 0;
2515 return 1 if ptr is a parent of context
2517 _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
2519 return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
2523 return the total size of memory used by this context and all children
2525 static size_t _talloc_total_limit_size(const void *ptr,
2526 struct talloc_memlimit *old_limit,
2527 struct talloc_memlimit *new_limit)
2529 return _talloc_total_mem_internal(ptr, TOTAL_MEM_LIMIT,
2530 old_limit, new_limit);
2533 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size)
2535 struct talloc_memlimit *l;
2537 for (l = limit; l != NULL; l = l->upper) {
2538 if (l->max_size != 0 &&
2539 ((l->max_size <= l->cur_size) ||
2540 (l->max_size - l->cur_size < TC_HDR_SIZE+size))) {
2541 return false;
2545 return true;
2548 static bool talloc_memlimit_update(struct talloc_memlimit *limit,
2549 size_t old_size, size_t new_size)
2551 struct talloc_memlimit *l;
2552 ssize_t d;
2554 if (old_size == 0) {
2555 d = new_size + TC_HDR_SIZE;
2556 } else {
2557 d = new_size - old_size;
2559 for (l = limit; l != NULL; l = l->upper) {
2560 ssize_t new_cur_size = l->cur_size + d;
2561 if (new_cur_size < 0) {
2562 return false;
2564 l->cur_size = new_cur_size;
2567 return true;
2570 _PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size)
2572 struct talloc_chunk *tc = talloc_chunk_from_ptr(ctx);
2573 struct talloc_memlimit *orig_limit;
2574 struct talloc_memlimit *limit = NULL;
2576 if (tc->limit && tc->limit->parent == tc) {
2577 tc->limit->max_size = max_size;
2578 return 0;
2580 orig_limit = tc->limit;
2582 limit = malloc(sizeof(struct talloc_memlimit));
2583 if (limit == NULL) {
2584 return 1;
2586 limit->parent = tc;
2587 limit->max_size = max_size;
2588 limit->cur_size = _talloc_total_limit_size(ctx, tc->limit, limit);
2590 if (orig_limit) {
2591 limit->upper = orig_limit;
2592 } else {
2593 limit->upper = NULL;
2596 return 0;