Start to fix talloc memlimits with talloc pools.
[Samba.git] / lib / talloc / talloc.c
blob067d46f97d3100c2bc3fe53fc4f624166d2650c7
1 /*
2 Samba Unix SMB/CIFS implementation.
4 Samba trivial allocation library - new interface
6 NOTE: Please read talloc_guide.txt for full documentation
8 Copyright (C) Andrew Tridgell 2004
9 Copyright (C) Stefan Metzmacher 2006
11 ** NOTE! The following LGPL license applies to the talloc
12 ** library. This does NOT imply that all of Samba is released
13 ** under the LGPL
15 This library is free software; you can redistribute it and/or
16 modify it under the terms of the GNU Lesser General Public
17 License as published by the Free Software Foundation; either
18 version 3 of the License, or (at your option) any later version.
20 This library is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Lesser General Public License for more details.
25 You should have received a copy of the GNU Lesser General Public
26 License along with this library; if not, see <http://www.gnu.org/licenses/>.
30 inspired by http://swapped.cc/halloc/
33 #include "replace.h"
34 #include "talloc.h"
36 #ifdef TALLOC_BUILD_VERSION_MAJOR
37 #if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR)
38 #error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR"
39 #endif
40 #endif
42 #ifdef TALLOC_BUILD_VERSION_MINOR
43 #if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR)
44 #error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR"
45 #endif
46 #endif
48 /* Special macros that are no-ops except when run under Valgrind on
49 * x86. They've moved a little bit from valgrind 1.0.4 to 1.9.4 */
50 #ifdef HAVE_VALGRIND_MEMCHECK_H
51 /* memcheck.h includes valgrind.h */
52 #include <valgrind/memcheck.h>
53 #elif defined(HAVE_VALGRIND_H)
54 #include <valgrind.h>
55 #endif
57 /* use this to force every realloc to change the pointer, to stress test
58 code that might not cope */
59 #define ALWAYS_REALLOC 0
62 #define MAX_TALLOC_SIZE 0x10000000
63 #define TALLOC_MAGIC_BASE 0xe814ec70
64 #define TALLOC_MAGIC ( \
65 TALLOC_MAGIC_BASE + \
66 (TALLOC_VERSION_MAJOR << 12) + \
67 (TALLOC_VERSION_MINOR << 4) \
70 #define TALLOC_FLAG_FREE 0x01
71 #define TALLOC_FLAG_LOOP 0x02
72 #define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */
73 #define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */
75 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
77 /* by default we abort when given a bad pointer (such as when talloc_free() is called
78 on a pointer that came from malloc() */
79 #ifndef TALLOC_ABORT
80 #define TALLOC_ABORT(reason) abort()
81 #endif
83 #ifndef discard_const_p
84 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
85 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
86 #else
87 # define discard_const_p(type, ptr) ((type *)(ptr))
88 #endif
89 #endif
91 /* these macros gain us a few percent of speed on gcc */
92 #if (__GNUC__ >= 3)
93 /* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
94 as its first argument */
95 #ifndef likely
96 #define likely(x) __builtin_expect(!!(x), 1)
97 #endif
98 #ifndef unlikely
99 #define unlikely(x) __builtin_expect(!!(x), 0)
100 #endif
101 #else
102 #ifndef likely
103 #define likely(x) (x)
104 #endif
105 #ifndef unlikely
106 #define unlikely(x) (x)
107 #endif
108 #endif
110 /* this null_context is only used if talloc_enable_leak_report() or
111 talloc_enable_leak_report_full() is called, otherwise it remains
112 NULL
114 static void *null_context;
115 static void *autofree_context;
117 /* used to enable fill of memory on free, which can be useful for
118 * catching use after free errors when valgrind is too slow
120 static struct {
121 bool initialised;
122 bool enabled;
123 uint8_t fill_value;
124 } talloc_fill;
126 #define TALLOC_FILL_ENV "TALLOC_FREE_FILL"
129 * do not wipe the header, to allow the
130 * double-free logic to still work
132 #define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \
133 if (unlikely(talloc_fill.enabled)) { \
134 size_t _flen = (_tc)->size; \
135 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
136 memset(_fptr, talloc_fill.fill_value, _flen); \
138 } while (0)
140 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
141 /* Mark the whole chunk as not accessable */
142 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \
143 size_t _flen = TC_HDR_SIZE + (_tc)->size; \
144 char *_fptr = (char *)(_tc); \
145 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
146 } while(0)
147 #else
148 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0)
149 #endif
151 #define TC_INVALIDATE_FULL_CHUNK(_tc) do { \
152 TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \
153 TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \
154 } while (0)
156 #define TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
157 if (unlikely(talloc_fill.enabled)) { \
158 size_t _flen = (_tc)->size - (_new_size); \
159 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
160 _fptr += (_new_size); \
161 memset(_fptr, talloc_fill.fill_value, _flen); \
163 } while (0)
165 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
166 /* Mark the unused bytes not accessable */
167 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
168 size_t _flen = (_tc)->size - (_new_size); \
169 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
170 _fptr += (_new_size); \
171 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
172 } while (0)
173 #else
174 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
175 #endif
177 #define TC_INVALIDATE_SHRINK_CHUNK(_tc, _new_size) do { \
178 TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size); \
179 TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
180 } while (0)
182 #define TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
183 if (unlikely(talloc_fill.enabled)) { \
184 size_t _flen = (_tc)->size - (_new_size); \
185 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
186 _fptr += (_new_size); \
187 memset(_fptr, talloc_fill.fill_value, _flen); \
189 } while (0)
191 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
192 /* Mark the unused bytes as undefined */
193 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
194 size_t _flen = (_tc)->size - (_new_size); \
195 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
196 _fptr += (_new_size); \
197 VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
198 } while (0)
199 #else
200 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
201 #endif
203 #define TC_UNDEFINE_SHRINK_CHUNK(_tc, _new_size) do { \
204 TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size); \
205 TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
206 } while (0)
208 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
209 /* Mark the new bytes as undefined */
210 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { \
211 size_t _old_used = TC_HDR_SIZE + (_tc)->size; \
212 size_t _new_used = TC_HDR_SIZE + (_new_size); \
213 size_t _flen = _new_used - _old_used; \
214 char *_fptr = _old_used + (char *)(_tc); \
215 VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
216 } while (0)
217 #else
218 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
219 #endif
221 #define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \
222 TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \
223 } while (0)
225 struct talloc_reference_handle {
226 struct talloc_reference_handle *next, *prev;
227 void *ptr;
228 const char *location;
231 struct talloc_memlimit {
232 struct talloc_chunk *parent;
233 struct talloc_memlimit *upper;
234 size_t max_size;
235 size_t cur_size;
238 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size);
239 static bool talloc_memlimit_update(struct talloc_memlimit *limit,
240 size_t old_size, size_t new_size);
241 static void talloc_memlimit_grow(struct talloc_memlimit *limit,
242 size_t size);
243 static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
244 size_t size);
245 static void talloc_memlimit_update_on_free(struct talloc_chunk *tc);
247 typedef int (*talloc_destructor_t)(void *);
249 struct talloc_chunk {
250 struct talloc_chunk *next, *prev;
251 struct talloc_chunk *parent, *child;
252 struct talloc_reference_handle *refs;
253 talloc_destructor_t destructor;
254 const char *name;
255 size_t size;
256 unsigned flags;
259 * limit semantics:
260 * if 'limit' is set it means all *new* children of the context will
261 * be limited to a total aggregate size ox max_size for memory
262 * allocations.
263 * cur_size is used to keep track of the current use
265 struct talloc_memlimit *limit;
268 * "pool" has dual use:
270 * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
271 * marks the end of the currently allocated area.
273 * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
274 * is a pointer to the struct talloc_chunk of the pool that it was
275 * allocated from. This way children can quickly find the pool to chew
276 * from.
278 void *pool;
281 /* 16 byte alignment seems to keep everyone happy */
282 #define TC_ALIGN16(s) (((s)+15)&~15)
283 #define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
284 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
286 _PUBLIC_ int talloc_version_major(void)
288 return TALLOC_VERSION_MAJOR;
291 _PUBLIC_ int talloc_version_minor(void)
293 return TALLOC_VERSION_MINOR;
296 static void (*talloc_log_fn)(const char *message);
298 _PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
300 talloc_log_fn = log_fn;
303 static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
304 static void talloc_log(const char *fmt, ...)
306 va_list ap;
307 char *message;
309 if (!talloc_log_fn) {
310 return;
313 va_start(ap, fmt);
314 message = talloc_vasprintf(NULL, fmt, ap);
315 va_end(ap);
317 talloc_log_fn(message);
318 talloc_free(message);
321 static void talloc_log_stderr(const char *message)
323 fprintf(stderr, "%s", message);
326 _PUBLIC_ void talloc_set_log_stderr(void)
328 talloc_set_log_fn(talloc_log_stderr);
331 static void (*talloc_abort_fn)(const char *reason);
333 _PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
335 talloc_abort_fn = abort_fn;
338 static void talloc_abort(const char *reason)
340 talloc_log("%s\n", reason);
342 if (!talloc_abort_fn) {
343 TALLOC_ABORT(reason);
346 talloc_abort_fn(reason);
349 static void talloc_abort_magic(unsigned magic)
351 unsigned striped = magic - TALLOC_MAGIC_BASE;
352 unsigned major = (striped & 0xFFFFF000) >> 12;
353 unsigned minor = (striped & 0x00000FF0) >> 4;
354 talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
355 magic, major, minor,
356 TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR);
357 talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
360 static void talloc_abort_access_after_free(void)
362 talloc_abort("Bad talloc magic value - access after free");
365 static void talloc_abort_unknown_value(void)
367 talloc_abort("Bad talloc magic value - unknown value");
370 /* panic if we get a bad magic value */
371 static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
373 const char *pp = (const char *)ptr;
374 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
375 if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
376 if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) {
377 talloc_abort_magic(tc->flags & (~0xF));
378 return NULL;
381 if (tc->flags & TALLOC_FLAG_FREE) {
382 talloc_log("talloc: access after free error - first free may be at %s\n", tc->name);
383 talloc_abort_access_after_free();
384 return NULL;
385 } else {
386 talloc_abort_unknown_value();
387 return NULL;
390 return tc;
393 /* hook into the front of the list */
394 #define _TLIST_ADD(list, p) \
395 do { \
396 if (!(list)) { \
397 (list) = (p); \
398 (p)->next = (p)->prev = NULL; \
399 } else { \
400 (list)->prev = (p); \
401 (p)->next = (list); \
402 (p)->prev = NULL; \
403 (list) = (p); \
405 } while (0)
407 /* remove an element from a list - element doesn't have to be in list. */
408 #define _TLIST_REMOVE(list, p) \
409 do { \
410 if ((p) == (list)) { \
411 (list) = (p)->next; \
412 if (list) (list)->prev = NULL; \
413 } else { \
414 if ((p)->prev) (p)->prev->next = (p)->next; \
415 if ((p)->next) (p)->next->prev = (p)->prev; \
417 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
418 } while (0)
422 return the parent chunk of a pointer
424 static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
426 struct talloc_chunk *tc;
428 if (unlikely(ptr == NULL)) {
429 return NULL;
432 tc = talloc_chunk_from_ptr(ptr);
433 while (tc->prev) tc=tc->prev;
435 return tc->parent;
438 _PUBLIC_ void *talloc_parent(const void *ptr)
440 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
441 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
445 find parents name
447 _PUBLIC_ const char *talloc_parent_name(const void *ptr)
449 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
450 return tc? tc->name : NULL;
454 A pool carries an in-pool object count count in the first 16 bytes.
455 bytes. This is done to support talloc_steal() to a parent outside of the
456 pool. The count includes the pool itself, so a talloc_free() on a pool will
457 only destroy the pool if the count has dropped to zero. A talloc_free() of a
458 pool member will reduce the count, and eventually also call free(3) on the
459 pool memory.
461 The object count is not put into "struct talloc_chunk" because it is only
462 relevant for talloc pools and the alignment to 16 bytes would increase the
463 memory footprint of each talloc chunk by those 16 bytes.
466 union talloc_pool_chunk {
467 /* This lets object_count nestle into 16-byte padding of talloc_chunk,
468 * on 32-bit platforms. */
469 struct tc_pool_hdr {
470 struct talloc_chunk c;
471 unsigned int object_count;
472 } hdr;
473 /* This makes it always 16 byte aligned. */
474 char pad[TC_ALIGN16(sizeof(struct tc_pool_hdr))];
477 static void *tc_pool_end(union talloc_pool_chunk *pool_tc)
479 return (char *)pool_tc + TC_HDR_SIZE + pool_tc->hdr.c.size;
482 static size_t tc_pool_space_left(union talloc_pool_chunk *pool_tc)
484 return (char *)tc_pool_end(pool_tc) - (char *)pool_tc->hdr.c.pool;
487 static void *tc_pool_first_chunk(union talloc_pool_chunk *pool_tc)
489 return pool_tc + 1;
492 /* If tc is inside a pool, this gives the next neighbour. */
493 static void *tc_next_chunk(struct talloc_chunk *tc)
495 return (char *)tc + TC_ALIGN16(TC_HDR_SIZE + tc->size);
498 /* Mark the whole remaining pool as not accessable */
499 static void tc_invalidate_pool(union talloc_pool_chunk *pool_tc)
501 size_t flen = tc_pool_space_left(pool_tc);
503 if (unlikely(talloc_fill.enabled)) {
504 memset(pool_tc->hdr.c.pool, talloc_fill.fill_value, flen);
507 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
508 VALGRIND_MAKE_MEM_NOACCESS(pool_tc->hdr.c.pool, flen);
509 #endif
513 Allocate from a pool
516 static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
517 size_t size)
519 union talloc_pool_chunk *pool_ctx = NULL;
520 size_t space_left;
521 struct talloc_chunk *result;
522 size_t chunk_size;
524 if (parent == NULL) {
525 return NULL;
528 if (parent->flags & TALLOC_FLAG_POOL) {
529 pool_ctx = (union talloc_pool_chunk *)parent;
531 else if (parent->flags & TALLOC_FLAG_POOLMEM) {
532 pool_ctx = (union talloc_pool_chunk *)parent->pool;
535 if (pool_ctx == NULL) {
536 return NULL;
539 space_left = tc_pool_space_left(pool_ctx);
542 * Align size to 16 bytes
544 chunk_size = TC_ALIGN16(size);
546 if (space_left < chunk_size) {
547 return NULL;
550 result = (struct talloc_chunk *)pool_ctx->hdr.c.pool;
552 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
553 VALGRIND_MAKE_MEM_UNDEFINED(result, size);
554 #endif
556 pool_ctx->hdr.c.pool = (void *)((char *)result + chunk_size);
558 result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
559 result->pool = pool_ctx;
561 pool_ctx->hdr.object_count++;
563 return result;
567 Allocate a bit of memory as a child of an existing pointer
569 static inline void *__talloc(const void *context, size_t size)
571 struct talloc_chunk *tc = NULL;
572 struct talloc_memlimit *limit = NULL;
574 if (unlikely(context == NULL)) {
575 context = null_context;
578 if (unlikely(size >= MAX_TALLOC_SIZE)) {
579 return NULL;
582 if (context != NULL) {
583 struct talloc_chunk *ptc = talloc_chunk_from_ptr(context);
585 if (ptc->limit != NULL) {
586 limit = ptc->limit;
589 if (!talloc_memlimit_check(limit, (TC_HDR_SIZE+size))) {
590 errno = ENOMEM;
591 return NULL;
594 tc = talloc_alloc_pool(ptc, TC_HDR_SIZE+size);
597 if (tc == NULL) {
598 tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
599 if (unlikely(tc == NULL)) return NULL;
600 tc->flags = TALLOC_MAGIC;
601 tc->pool = NULL;
604 if (limit != NULL) {
605 struct talloc_memlimit *l;
607 for (l = limit; l != NULL; l = l->upper) {
608 l->cur_size += TC_HDR_SIZE+size;
612 tc->limit = limit;
613 tc->size = size;
614 tc->destructor = NULL;
615 tc->child = NULL;
616 tc->name = NULL;
617 tc->refs = NULL;
619 if (likely(context)) {
620 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
622 if (parent->child) {
623 parent->child->parent = NULL;
624 tc->next = parent->child;
625 tc->next->prev = tc;
626 } else {
627 tc->next = NULL;
629 tc->parent = parent;
630 tc->prev = NULL;
631 parent->child = tc;
632 } else {
633 tc->next = tc->prev = tc->parent = NULL;
636 return TC_PTR_FROM_CHUNK(tc);
640 * Create a talloc pool
643 _PUBLIC_ void *talloc_pool(const void *context, size_t size)
645 union talloc_pool_chunk *pool_tc;
646 void *result = __talloc(context, sizeof(*pool_tc) - TC_HDR_SIZE + size);
648 if (unlikely(result == NULL)) {
649 return NULL;
652 pool_tc = (union talloc_pool_chunk *)talloc_chunk_from_ptr(result);
653 if (unlikely(pool_tc->hdr.c.flags & TALLOC_FLAG_POOLMEM)) {
654 /* We don't handle this correctly, so fail. */
655 talloc_log("talloc: cannot allocate pool off another pool %s\n",
656 talloc_get_name(context));
657 talloc_free(result);
658 return NULL;
660 pool_tc->hdr.c.flags |= TALLOC_FLAG_POOL;
661 pool_tc->hdr.c.pool = tc_pool_first_chunk(pool_tc);
663 pool_tc->hdr.object_count = 1;
665 tc_invalidate_pool(pool_tc);
667 return result;
671 setup a destructor to be called on free of a pointer
672 the destructor should return 0 on success, or -1 on failure.
673 if the destructor fails then the free is failed, and the memory can
674 be continued to be used
676 _PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
678 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
679 tc->destructor = destructor;
683 increase the reference count on a piece of memory.
685 _PUBLIC_ int talloc_increase_ref_count(const void *ptr)
687 if (unlikely(!talloc_reference(null_context, ptr))) {
688 return -1;
690 return 0;
694 helper for talloc_reference()
696 this is referenced by a function pointer and should not be inline
698 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
700 struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
701 _TLIST_REMOVE(ptr_tc->refs, handle);
702 return 0;
706 more efficient way to add a name to a pointer - the name must point to a
707 true string constant
709 static inline void _talloc_set_name_const(const void *ptr, const char *name)
711 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
712 tc->name = name;
716 internal talloc_named_const()
718 static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
720 void *ptr;
722 ptr = __talloc(context, size);
723 if (unlikely(ptr == NULL)) {
724 return NULL;
727 _talloc_set_name_const(ptr, name);
729 return ptr;
733 make a secondary reference to a pointer, hanging off the given context.
734 the pointer remains valid until both the original caller and this given
735 context are freed.
737 the major use for this is when two different structures need to reference the
738 same underlying data, and you want to be able to free the two instances separately,
739 and in either order
741 _PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
743 struct talloc_chunk *tc;
744 struct talloc_reference_handle *handle;
745 if (unlikely(ptr == NULL)) return NULL;
747 tc = talloc_chunk_from_ptr(ptr);
748 handle = (struct talloc_reference_handle *)_talloc_named_const(context,
749 sizeof(struct talloc_reference_handle),
750 TALLOC_MAGIC_REFERENCE);
751 if (unlikely(handle == NULL)) return NULL;
753 /* note that we hang the destructor off the handle, not the
754 main context as that allows the caller to still setup their
755 own destructor on the context if they want to */
756 talloc_set_destructor(handle, talloc_reference_destructor);
757 handle->ptr = discard_const_p(void, ptr);
758 handle->location = location;
759 _TLIST_ADD(tc->refs, handle);
760 return handle->ptr;
763 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
765 static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
766 const char *location)
768 union talloc_pool_chunk *pool;
769 void *next_tc;
771 pool = (union talloc_pool_chunk *)tc->pool;
772 next_tc = tc_next_chunk(tc);
774 tc->flags |= TALLOC_FLAG_FREE;
776 /* we mark the freed memory with where we called the free
777 * from. This means on a double free error we can report where
778 * the first free came from
780 tc->name = location;
782 TC_INVALIDATE_FULL_CHUNK(tc);
784 if (unlikely(pool->hdr.object_count == 0)) {
785 talloc_abort("Pool object count zero!");
786 return;
789 pool->hdr.object_count--;
791 if (unlikely(pool->hdr.object_count == 1
792 && !(pool->hdr.c.flags & TALLOC_FLAG_FREE))) {
794 * if there is just one object left in the pool
795 * and pool->flags does not have TALLOC_FLAG_FREE,
796 * it means this is the pool itself and
797 * the rest is available for new objects
798 * again.
800 pool->hdr.c.pool = tc_pool_first_chunk(pool);
801 tc_invalidate_pool(pool);
802 return;
805 if (unlikely(pool->hdr.object_count == 0)) {
807 * we mark the freed memory with where we called the free
808 * from. This means on a double free error we can report where
809 * the first free came from
811 pool->hdr.c.name = location;
813 TC_INVALIDATE_FULL_CHUNK(&pool->hdr.c);
814 free(pool);
815 return;
818 if (pool->hdr.c.pool == next_tc) {
820 * if pool->pool still points to end of
821 * 'tc' (which is stored in the 'next_tc' variable),
822 * we can reclaim the memory of 'tc'.
824 pool->hdr.c.pool = tc;
825 return;
829 * Do nothing. The memory is just "wasted", waiting for the pool
830 * itself to be freed.
834 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
835 void *ptr,
836 const char *location);
839 internal talloc_free call
841 static inline int _talloc_free_internal(void *ptr, const char *location)
843 struct talloc_chunk *tc;
845 if (unlikely(ptr == NULL)) {
846 return -1;
849 /* possibly initialised the talloc fill value */
850 if (unlikely(!talloc_fill.initialised)) {
851 const char *fill = getenv(TALLOC_FILL_ENV);
852 if (fill != NULL) {
853 talloc_fill.enabled = true;
854 talloc_fill.fill_value = strtoul(fill, NULL, 0);
856 talloc_fill.initialised = true;
859 tc = talloc_chunk_from_ptr(ptr);
861 if (unlikely(tc->refs)) {
862 int is_child;
863 /* check if this is a reference from a child or
864 * grandchild back to it's parent or grandparent
866 * in that case we need to remove the reference and
867 * call another instance of talloc_free() on the current
868 * pointer.
870 is_child = talloc_is_parent(tc->refs, ptr);
871 _talloc_free_internal(tc->refs, location);
872 if (is_child) {
873 return _talloc_free_internal(ptr, location);
875 return -1;
878 if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
879 /* we have a free loop - stop looping */
880 return 0;
883 if (unlikely(tc->destructor)) {
884 talloc_destructor_t d = tc->destructor;
885 if (d == (talloc_destructor_t)-1) {
886 return -1;
888 tc->destructor = (talloc_destructor_t)-1;
889 if (d(ptr) == -1) {
890 tc->destructor = d;
891 return -1;
893 tc->destructor = NULL;
896 if (tc->parent) {
897 _TLIST_REMOVE(tc->parent->child, tc);
898 if (tc->parent->child) {
899 tc->parent->child->parent = tc->parent;
901 } else {
902 if (tc->prev) tc->prev->next = tc->next;
903 if (tc->next) tc->next->prev = tc->prev;
904 tc->prev = tc->next = NULL;
907 tc->flags |= TALLOC_FLAG_LOOP;
909 _talloc_free_children_internal(tc, ptr, location);
911 tc->flags |= TALLOC_FLAG_FREE;
914 * If we are part of a memory limited context hierarchy
915 * we need to subtract the memory used from the counters
917 if (tc->limit) {
918 struct talloc_memlimit *l;
920 for (l = tc->limit; l != NULL; l = l->upper) {
921 if (l->cur_size >= tc->size+TC_HDR_SIZE) {
922 l->cur_size -= tc->size+TC_HDR_SIZE;
923 } else {
924 talloc_abort("cur_size memlimit counter not correct!");
925 return 0;
929 if (tc->limit->parent == tc) {
930 free(tc->limit);
933 tc->limit = NULL;
936 /* we mark the freed memory with where we called the free
937 * from. This means on a double free error we can report where
938 * the first free came from
940 tc->name = location;
942 if (tc->flags & TALLOC_FLAG_POOL) {
943 union talloc_pool_chunk *pool = (union talloc_pool_chunk *)tc;
945 if (unlikely(pool->hdr.object_count == 0)) {
946 talloc_abort("Pool object count zero!");
947 return 0;
950 pool->hdr.object_count--;
952 if (likely(pool->hdr.object_count != 0)) {
953 return 0;
956 TC_INVALIDATE_FULL_CHUNK(tc);
957 free(tc);
958 return 0;
961 if (tc->flags & TALLOC_FLAG_POOLMEM) {
962 _talloc_free_poolmem(tc, location);
963 return 0;
966 TC_INVALIDATE_FULL_CHUNK(tc);
967 free(tc);
968 return 0;
971 static size_t _talloc_total_limit_size(const void *ptr,
972 struct talloc_memlimit *old_limit,
973 struct talloc_memlimit *new_limit);
976 move a lump of memory from one talloc context to another return the
977 ptr on success, or NULL if it could not be transferred.
978 passing NULL as ptr will always return NULL with no side effects.
980 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr)
982 struct talloc_chunk *tc, *new_tc;
983 size_t ctx_size = 0;
985 if (unlikely(!ptr)) {
986 return NULL;
989 if (unlikely(new_ctx == NULL)) {
990 new_ctx = null_context;
993 tc = talloc_chunk_from_ptr(ptr);
995 if (tc->limit != NULL) {
997 ctx_size = _talloc_total_limit_size(ptr, NULL, NULL);
999 if (!talloc_memlimit_update(tc->limit->upper, ctx_size, 0)) {
1000 talloc_abort("cur_size memlimit counter not correct!");
1001 errno = EINVAL;
1002 return NULL;
1005 if (tc->limit->parent == tc) {
1006 tc->limit->upper = NULL;
1007 } else {
1008 tc->limit = NULL;
1012 if (unlikely(new_ctx == NULL)) {
1013 if (tc->parent) {
1014 _TLIST_REMOVE(tc->parent->child, tc);
1015 if (tc->parent->child) {
1016 tc->parent->child->parent = tc->parent;
1018 } else {
1019 if (tc->prev) tc->prev->next = tc->next;
1020 if (tc->next) tc->next->prev = tc->prev;
1023 tc->parent = tc->next = tc->prev = NULL;
1024 return discard_const_p(void, ptr);
1027 new_tc = talloc_chunk_from_ptr(new_ctx);
1029 if (unlikely(tc == new_tc || tc->parent == new_tc)) {
1030 return discard_const_p(void, ptr);
1033 if (tc->parent) {
1034 _TLIST_REMOVE(tc->parent->child, tc);
1035 if (tc->parent->child) {
1036 tc->parent->child->parent = tc->parent;
1038 } else {
1039 if (tc->prev) tc->prev->next = tc->next;
1040 if (tc->next) tc->next->prev = tc->prev;
1041 tc->prev = tc->next = NULL;
1044 tc->parent = new_tc;
1045 if (new_tc->child) new_tc->child->parent = NULL;
1046 _TLIST_ADD(new_tc->child, tc);
1048 if (tc->limit || new_tc->limit) {
1049 ctx_size = _talloc_total_limit_size(ptr, tc->limit,
1050 new_tc->limit);
1053 if (new_tc->limit) {
1054 struct talloc_memlimit *l;
1056 for (l = new_tc->limit; l != NULL; l = l->upper) {
1057 l->cur_size += ctx_size;
1061 return discard_const_p(void, ptr);
1065 move a lump of memory from one talloc context to another return the
1066 ptr on success, or NULL if it could not be transferred.
1067 passing NULL as ptr will always return NULL with no side effects.
1069 _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
1071 struct talloc_chunk *tc;
1073 if (unlikely(ptr == NULL)) {
1074 return NULL;
1077 tc = talloc_chunk_from_ptr(ptr);
1079 if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
1080 struct talloc_reference_handle *h;
1082 talloc_log("WARNING: talloc_steal with references at %s\n",
1083 location);
1085 for (h=tc->refs; h; h=h->next) {
1086 talloc_log("\treference at %s\n",
1087 h->location);
1091 #if 0
1092 /* this test is probably too expensive to have on in the
1093 normal build, but it useful for debugging */
1094 if (talloc_is_parent(new_ctx, ptr)) {
1095 talloc_log("WARNING: stealing into talloc child at %s\n", location);
1097 #endif
1099 return _talloc_steal_internal(new_ctx, ptr);
1103 this is like a talloc_steal(), but you must supply the old
1104 parent. This resolves the ambiguity in a talloc_steal() which is
1105 called on a context that has more than one parent (via references)
1107 The old parent can be either a reference or a parent
1109 _PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
1111 struct talloc_chunk *tc;
1112 struct talloc_reference_handle *h;
1114 if (unlikely(ptr == NULL)) {
1115 return NULL;
1118 if (old_parent == talloc_parent(ptr)) {
1119 return _talloc_steal_internal(new_parent, ptr);
1122 tc = talloc_chunk_from_ptr(ptr);
1123 for (h=tc->refs;h;h=h->next) {
1124 if (talloc_parent(h) == old_parent) {
1125 if (_talloc_steal_internal(new_parent, h) != h) {
1126 return NULL;
1128 return discard_const_p(void, ptr);
1132 /* it wasn't a parent */
1133 return NULL;
1137 remove a secondary reference to a pointer. This undo's what
1138 talloc_reference() has done. The context and pointer arguments
1139 must match those given to a talloc_reference()
1141 static inline int talloc_unreference(const void *context, const void *ptr)
1143 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1144 struct talloc_reference_handle *h;
1146 if (unlikely(context == NULL)) {
1147 context = null_context;
1150 for (h=tc->refs;h;h=h->next) {
1151 struct talloc_chunk *p = talloc_parent_chunk(h);
1152 if (p == NULL) {
1153 if (context == NULL) break;
1154 } else if (TC_PTR_FROM_CHUNK(p) == context) {
1155 break;
1158 if (h == NULL) {
1159 return -1;
1162 return _talloc_free_internal(h, __location__);
1166 remove a specific parent context from a pointer. This is a more
1167 controlled variant of talloc_free()
1169 _PUBLIC_ int talloc_unlink(const void *context, void *ptr)
1171 struct talloc_chunk *tc_p, *new_p, *tc_c;
1172 void *new_parent;
1174 if (ptr == NULL) {
1175 return -1;
1178 if (context == NULL) {
1179 context = null_context;
1182 if (talloc_unreference(context, ptr) == 0) {
1183 return 0;
1186 if (context != NULL) {
1187 tc_c = talloc_chunk_from_ptr(context);
1188 } else {
1189 tc_c = NULL;
1191 if (tc_c != talloc_parent_chunk(ptr)) {
1192 return -1;
1195 tc_p = talloc_chunk_from_ptr(ptr);
1197 if (tc_p->refs == NULL) {
1198 return _talloc_free_internal(ptr, __location__);
1201 new_p = talloc_parent_chunk(tc_p->refs);
1202 if (new_p) {
1203 new_parent = TC_PTR_FROM_CHUNK(new_p);
1204 } else {
1205 new_parent = NULL;
1208 if (talloc_unreference(new_parent, ptr) != 0) {
1209 return -1;
1212 _talloc_steal_internal(new_parent, ptr);
1214 return 0;
1218 add a name to an existing pointer - va_list version
1220 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1222 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
1224 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1225 tc->name = talloc_vasprintf(ptr, fmt, ap);
1226 if (likely(tc->name)) {
1227 _talloc_set_name_const(tc->name, ".name");
1229 return tc->name;
1233 add a name to an existing pointer
1235 _PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
1237 const char *name;
1238 va_list ap;
1239 va_start(ap, fmt);
1240 name = talloc_set_name_v(ptr, fmt, ap);
1241 va_end(ap);
1242 return name;
1247 create a named talloc pointer. Any talloc pointer can be named, and
1248 talloc_named() operates just like talloc() except that it allows you
1249 to name the pointer.
1251 _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
1253 va_list ap;
1254 void *ptr;
1255 const char *name;
1257 ptr = __talloc(context, size);
1258 if (unlikely(ptr == NULL)) return NULL;
1260 va_start(ap, fmt);
1261 name = talloc_set_name_v(ptr, fmt, ap);
1262 va_end(ap);
1264 if (unlikely(name == NULL)) {
1265 _talloc_free_internal(ptr, __location__);
1266 return NULL;
1269 return ptr;
1273 return the name of a talloc ptr, or "UNNAMED"
1275 _PUBLIC_ const char *talloc_get_name(const void *ptr)
1277 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1278 if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
1279 return ".reference";
1281 if (likely(tc->name)) {
1282 return tc->name;
1284 return "UNNAMED";
1289 check if a pointer has the given name. If it does, return the pointer,
1290 otherwise return NULL
1292 _PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
1294 const char *pname;
1295 if (unlikely(ptr == NULL)) return NULL;
1296 pname = talloc_get_name(ptr);
1297 if (likely(pname == name || strcmp(pname, name) == 0)) {
1298 return discard_const_p(void, ptr);
1300 return NULL;
1303 static void talloc_abort_type_mismatch(const char *location,
1304 const char *name,
1305 const char *expected)
1307 const char *reason;
1309 reason = talloc_asprintf(NULL,
1310 "%s: Type mismatch: name[%s] expected[%s]",
1311 location,
1312 name?name:"NULL",
1313 expected);
1314 if (!reason) {
1315 reason = "Type mismatch";
1318 talloc_abort(reason);
1321 _PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
1323 const char *pname;
1325 if (unlikely(ptr == NULL)) {
1326 talloc_abort_type_mismatch(location, NULL, name);
1327 return NULL;
1330 pname = talloc_get_name(ptr);
1331 if (likely(pname == name || strcmp(pname, name) == 0)) {
1332 return discard_const_p(void, ptr);
1335 talloc_abort_type_mismatch(location, pname, name);
1336 return NULL;
1340 this is for compatibility with older versions of talloc
1342 _PUBLIC_ void *talloc_init(const char *fmt, ...)
1344 va_list ap;
1345 void *ptr;
1346 const char *name;
1348 ptr = __talloc(NULL, 0);
1349 if (unlikely(ptr == NULL)) return NULL;
1351 va_start(ap, fmt);
1352 name = talloc_set_name_v(ptr, fmt, ap);
1353 va_end(ap);
1355 if (unlikely(name == NULL)) {
1356 _talloc_free_internal(ptr, __location__);
1357 return NULL;
1360 return ptr;
1363 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
1364 void *ptr,
1365 const char *location)
1367 while (tc->child) {
1368 /* we need to work out who will own an abandoned child
1369 if it cannot be freed. In priority order, the first
1370 choice is owner of any remaining reference to this
1371 pointer, the second choice is our parent, and the
1372 final choice is the null context. */
1373 void *child = TC_PTR_FROM_CHUNK(tc->child);
1374 const void *new_parent = null_context;
1375 if (unlikely(tc->child->refs)) {
1376 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1377 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1379 if (unlikely(_talloc_free_internal(child, location) == -1)) {
1380 if (new_parent == null_context) {
1381 struct talloc_chunk *p = talloc_parent_chunk(ptr);
1382 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1384 _talloc_steal_internal(new_parent, child);
1390 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1391 should probably not be used in new code. It's in here to keep the talloc
1392 code consistent across Samba 3 and 4.
1394 _PUBLIC_ void talloc_free_children(void *ptr)
1396 struct talloc_chunk *tc_name = NULL;
1397 struct talloc_chunk *tc;
1399 if (unlikely(ptr == NULL)) {
1400 return;
1403 tc = talloc_chunk_from_ptr(ptr);
1405 /* we do not want to free the context name if it is a child .. */
1406 if (likely(tc->child)) {
1407 for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
1408 if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
1410 if (tc_name) {
1411 _TLIST_REMOVE(tc->child, tc_name);
1412 if (tc->child) {
1413 tc->child->parent = tc;
1418 _talloc_free_children_internal(tc, ptr, __location__);
1420 /* .. so we put it back after all other children have been freed */
1421 if (tc_name) {
1422 if (tc->child) {
1423 tc->child->parent = NULL;
1425 tc_name->parent = tc;
1426 _TLIST_ADD(tc->child, tc_name);
1431 Allocate a bit of memory as a child of an existing pointer
1433 _PUBLIC_ void *_talloc(const void *context, size_t size)
1435 return __talloc(context, size);
1439 externally callable talloc_set_name_const()
1441 _PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
1443 _talloc_set_name_const(ptr, name);
1447 create a named talloc pointer. Any talloc pointer can be named, and
1448 talloc_named() operates just like talloc() except that it allows you
1449 to name the pointer.
1451 _PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
1453 return _talloc_named_const(context, size, name);
1457 free a talloc pointer. This also frees all child pointers of this
1458 pointer recursively
1460 return 0 if the memory is actually freed, otherwise -1. The memory
1461 will not be freed if the ref_count is > 1 or the destructor (if
1462 any) returns non-zero
1464 _PUBLIC_ int _talloc_free(void *ptr, const char *location)
1466 struct talloc_chunk *tc;
1468 if (unlikely(ptr == NULL)) {
1469 return -1;
1472 tc = talloc_chunk_from_ptr(ptr);
1474 if (unlikely(tc->refs != NULL)) {
1475 struct talloc_reference_handle *h;
1477 if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
1478 /* in this case we do know which parent should
1479 get this pointer, as there is really only
1480 one parent */
1481 return talloc_unlink(null_context, ptr);
1484 talloc_log("ERROR: talloc_free with references at %s\n",
1485 location);
1487 for (h=tc->refs; h; h=h->next) {
1488 talloc_log("\treference at %s\n",
1489 h->location);
1491 return -1;
1494 return _talloc_free_internal(ptr, location);
1500 A talloc version of realloc. The context argument is only used if
1501 ptr is NULL
1503 _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
1505 struct talloc_chunk *tc;
1506 void *new_ptr;
1507 bool malloced = false;
1508 union talloc_pool_chunk *pool_tc = NULL;
1510 /* size zero is equivalent to free() */
1511 if (unlikely(size == 0)) {
1512 talloc_unlink(context, ptr);
1513 return NULL;
1516 if (unlikely(size >= MAX_TALLOC_SIZE)) {
1517 return NULL;
1520 /* realloc(NULL) is equivalent to malloc() */
1521 if (ptr == NULL) {
1522 return _talloc_named_const(context, size, name);
1525 tc = talloc_chunk_from_ptr(ptr);
1527 /* don't allow realloc on referenced pointers */
1528 if (unlikely(tc->refs)) {
1529 return NULL;
1532 /* don't let anybody try to realloc a talloc_pool */
1533 if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
1534 return NULL;
1537 if (tc->limit && (size - tc->size > 0)) {
1538 if (!talloc_memlimit_check(tc->limit, (size - tc->size))) {
1539 errno = ENOMEM;
1540 return NULL;
1544 /* handle realloc inside a talloc_pool */
1545 if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
1546 pool_tc = (union talloc_pool_chunk *)tc->pool;
1549 #if (ALWAYS_REALLOC == 0)
1550 /* don't shrink if we have less than 1k to gain */
1551 if (size < tc->size && tc->limit == NULL) {
1552 if (pool_tc) {
1553 void *next_tc = tc_next_chunk(tc);
1554 TC_INVALIDATE_SHRINK_CHUNK(tc, size);
1555 tc->size = size;
1556 if (next_tc == pool_tc->hdr.c.pool) {
1557 /* note: tc->size has changed, so this works */
1558 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1560 return ptr;
1561 } else if ((tc->size - size) < 1024) {
1563 * if we call TC_INVALIDATE_SHRINK_CHUNK() here
1564 * we would need to call TC_UNDEFINE_GROW_CHUNK()
1565 * after each realloc call, which slows down
1566 * testing a lot :-(.
1568 * That is why we only mark memory as undefined here.
1570 TC_UNDEFINE_SHRINK_CHUNK(tc, size);
1572 /* do not shrink if we have less than 1k to gain */
1573 tc->size = size;
1574 return ptr;
1576 } else if (tc->size == size) {
1578 * do not change the pointer if it is exactly
1579 * the same size.
1581 return ptr;
1583 #endif
1585 /* by resetting magic we catch users of the old memory */
1586 tc->flags |= TALLOC_FLAG_FREE;
1588 #if ALWAYS_REALLOC
1589 if (pool_tc) {
1590 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1591 pool_tc->hdr.object_count--;
1593 if (new_ptr == NULL) {
1594 new_ptr = malloc(TC_HDR_SIZE+size);
1595 malloced = true;
1598 if (new_ptr) {
1599 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1600 TC_INVALIDATE_FULL_CHUNK(tc);
1602 } else {
1603 new_ptr = malloc(size + TC_HDR_SIZE);
1604 if (new_ptr) {
1605 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1606 free(tc);
1609 #else
1610 if (pool_tc) {
1611 void *next_tc = tc_next_chunk(tc);
1612 size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size);
1613 size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
1614 size_t space_needed;
1615 size_t space_left;
1616 unsigned int chunk_count = pool_tc->hdr.object_count;
1618 if (!(pool_tc->hdr.c.flags & TALLOC_FLAG_FREE)) {
1619 chunk_count -= 1;
1622 if (chunk_count == 1) {
1624 * optimize for the case where 'tc' is the only
1625 * chunk in the pool.
1627 char *start = tc_pool_first_chunk(pool_tc);
1628 space_needed = new_chunk_size;
1629 space_left = (char *)tc_pool_end(pool_tc) - start;
1631 if (space_left >= space_needed) {
1632 size_t old_used = TC_HDR_SIZE + tc->size;
1633 size_t new_used = TC_HDR_SIZE + size;
1634 new_ptr = start;
1635 memmove(new_ptr, tc, old_used);
1637 tc = (struct talloc_chunk *)new_ptr;
1638 TC_UNDEFINE_GROW_CHUNK(tc, size);
1641 * first we do not align the pool pointer
1642 * because we want to invalidate the padding
1643 * too.
1645 pool_tc->hdr.c.pool = new_used + (char *)new_ptr;
1646 tc_invalidate_pool(pool_tc);
1648 /* now the aligned pointer */
1649 pool_tc->hdr.c.pool = new_chunk_size + (char *)new_ptr;
1650 goto got_new_ptr;
1653 next_tc = NULL;
1656 if (new_chunk_size == old_chunk_size) {
1657 TC_UNDEFINE_GROW_CHUNK(tc, size);
1658 tc->flags &= ~TALLOC_FLAG_FREE;
1659 if (!talloc_memlimit_update(tc->limit,
1660 tc->size, size)) {
1661 talloc_abort("cur_size memlimit counter not"
1662 " correct!");
1663 errno = EINVAL;
1664 return NULL;
1667 tc->size = size;
1668 return ptr;
1671 if (next_tc == pool_tc->hdr.c.pool) {
1673 * optimize for the case where 'tc' is the last
1674 * chunk in the pool.
1676 space_needed = new_chunk_size - old_chunk_size;
1677 space_left = tc_pool_space_left(pool_tc);
1679 if (space_left >= space_needed) {
1680 TC_UNDEFINE_GROW_CHUNK(tc, size);
1681 tc->flags &= ~TALLOC_FLAG_FREE;
1682 if (!talloc_memlimit_update(tc->limit,
1683 tc->size, size)) {
1684 talloc_abort("cur_size memlimit "
1685 "counter not correct!");
1686 errno = EINVAL;
1687 return NULL;
1689 tc->size = size;
1690 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1691 return ptr;
1695 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1697 if (new_ptr == NULL) {
1698 new_ptr = malloc(TC_HDR_SIZE+size);
1699 malloced = true;
1702 if (new_ptr) {
1703 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1705 _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
1708 else {
1709 new_ptr = realloc(tc, size + TC_HDR_SIZE);
1711 got_new_ptr:
1712 #endif
1713 if (unlikely(!new_ptr)) {
1714 tc->flags &= ~TALLOC_FLAG_FREE;
1715 return NULL;
1718 tc = (struct talloc_chunk *)new_ptr;
1719 tc->flags &= ~TALLOC_FLAG_FREE;
1720 if (malloced) {
1721 tc->flags &= ~TALLOC_FLAG_POOLMEM;
1723 if (tc->parent) {
1724 tc->parent->child = tc;
1726 if (tc->child) {
1727 tc->child->parent = tc;
1730 if (tc->prev) {
1731 tc->prev->next = tc;
1733 if (tc->next) {
1734 tc->next->prev = tc;
1737 if (!talloc_memlimit_update(tc->limit, tc->size, size)) {
1738 talloc_abort("cur_size memlimit counter not correct!");
1739 errno = EINVAL;
1740 return NULL;
1742 tc->size = size;
1743 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
1745 return TC_PTR_FROM_CHUNK(tc);
1749 a wrapper around talloc_steal() for situations where you are moving a pointer
1750 between two structures, and want the old pointer to be set to NULL
1752 _PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
1754 const void **pptr = discard_const_p(const void *,_pptr);
1755 void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
1756 (*pptr) = NULL;
1757 return ret;
1760 enum talloc_mem_count_type {
1761 TOTAL_MEM_SIZE,
1762 TOTAL_MEM_BLOCKS,
1763 TOTAL_MEM_LIMIT,
1766 static size_t _talloc_total_mem_internal(const void *ptr,
1767 enum talloc_mem_count_type type,
1768 struct talloc_memlimit *old_limit,
1769 struct talloc_memlimit *new_limit)
1771 size_t total = 0;
1772 struct talloc_chunk *c, *tc;
1774 if (ptr == NULL) {
1775 ptr = null_context;
1777 if (ptr == NULL) {
1778 return 0;
1781 tc = talloc_chunk_from_ptr(ptr);
1783 if (old_limit || new_limit) {
1784 if (tc->limit && tc->limit->upper == old_limit) {
1785 tc->limit->upper = new_limit;
1789 /* optimize in the memlimits case */
1790 if (type == TOTAL_MEM_LIMIT &&
1791 tc->limit != NULL &&
1792 tc->limit != old_limit &&
1793 tc->limit->parent == tc) {
1794 return tc->limit->cur_size;
1797 if (tc->flags & TALLOC_FLAG_LOOP) {
1798 return 0;
1801 tc->flags |= TALLOC_FLAG_LOOP;
1803 if (old_limit || new_limit) {
1804 if (old_limit == tc->limit) {
1805 tc->limit = new_limit;
1809 switch (type) {
1810 case TOTAL_MEM_SIZE:
1811 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1812 total = tc->size;
1814 break;
1815 case TOTAL_MEM_BLOCKS:
1816 total++;
1817 break;
1818 case TOTAL_MEM_LIMIT:
1819 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1820 total = tc->size + TC_HDR_SIZE;
1822 break;
1824 for (c = tc->child; c; c = c->next) {
1825 total += _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c), type,
1826 old_limit, new_limit);
1829 tc->flags &= ~TALLOC_FLAG_LOOP;
1831 return total;
1835 return the total size of a talloc pool (subtree)
1837 _PUBLIC_ size_t talloc_total_size(const void *ptr)
1839 return _talloc_total_mem_internal(ptr, TOTAL_MEM_SIZE, NULL, NULL);
1843 return the total number of blocks in a talloc pool (subtree)
1845 _PUBLIC_ size_t talloc_total_blocks(const void *ptr)
1847 return _talloc_total_mem_internal(ptr, TOTAL_MEM_BLOCKS, NULL, NULL);
1851 return the number of external references to a pointer
1853 _PUBLIC_ size_t talloc_reference_count(const void *ptr)
1855 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1856 struct talloc_reference_handle *h;
1857 size_t ret = 0;
1859 for (h=tc->refs;h;h=h->next) {
1860 ret++;
1862 return ret;
1866 report on memory usage by all children of a pointer, giving a full tree view
1868 _PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1869 void (*callback)(const void *ptr,
1870 int depth, int max_depth,
1871 int is_ref,
1872 void *private_data),
1873 void *private_data)
1875 struct talloc_chunk *c, *tc;
1877 if (ptr == NULL) {
1878 ptr = null_context;
1880 if (ptr == NULL) return;
1882 tc = talloc_chunk_from_ptr(ptr);
1884 if (tc->flags & TALLOC_FLAG_LOOP) {
1885 return;
1888 callback(ptr, depth, max_depth, 0, private_data);
1890 if (max_depth >= 0 && depth >= max_depth) {
1891 return;
1894 tc->flags |= TALLOC_FLAG_LOOP;
1895 for (c=tc->child;c;c=c->next) {
1896 if (c->name == TALLOC_MAGIC_REFERENCE) {
1897 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1898 callback(h->ptr, depth + 1, max_depth, 1, private_data);
1899 } else {
1900 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1903 tc->flags &= ~TALLOC_FLAG_LOOP;
1906 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1908 const char *name = talloc_get_name(ptr);
1909 struct talloc_chunk *tc;
1910 FILE *f = (FILE *)_f;
1912 if (is_ref) {
1913 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1914 return;
1917 tc = talloc_chunk_from_ptr(ptr);
1918 if (tc->limit && tc->limit->parent == tc) {
1919 fprintf(f, "%*s%-30s is a memlimit context"
1920 " (max_size = %lu bytes, cur_size = %lu bytes)\n",
1921 depth*4, "",
1922 name,
1923 (unsigned long)tc->limit->max_size,
1924 (unsigned long)tc->limit->cur_size);
1927 if (depth == 0) {
1928 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1929 (max_depth < 0 ? "full " :""), name,
1930 (unsigned long)talloc_total_size(ptr),
1931 (unsigned long)talloc_total_blocks(ptr));
1932 return;
1935 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1936 depth*4, "",
1937 name,
1938 (unsigned long)talloc_total_size(ptr),
1939 (unsigned long)talloc_total_blocks(ptr),
1940 (int)talloc_reference_count(ptr), ptr);
1942 #if 0
1943 fprintf(f, "content: ");
1944 if (talloc_total_size(ptr)) {
1945 int tot = talloc_total_size(ptr);
1946 int i;
1948 for (i = 0; i < tot; i++) {
1949 if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1950 fprintf(f, "%c", ((char *)ptr)[i]);
1951 } else {
1952 fprintf(f, "~%02x", ((char *)ptr)[i]);
1956 fprintf(f, "\n");
1957 #endif
1961 report on memory usage by all children of a pointer, giving a full tree view
1963 _PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1965 if (f) {
1966 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1967 fflush(f);
1972 report on memory usage by all children of a pointer, giving a full tree view
1974 _PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
1976 talloc_report_depth_file(ptr, 0, -1, f);
1980 report on memory usage by all children of a pointer
1982 _PUBLIC_ void talloc_report(const void *ptr, FILE *f)
1984 talloc_report_depth_file(ptr, 0, 1, f);
1988 report on any memory hanging off the null context
1990 static void talloc_report_null(void)
1992 if (talloc_total_size(null_context) != 0) {
1993 talloc_report(null_context, stderr);
1998 report on any memory hanging off the null context
2000 static void talloc_report_null_full(void)
2002 if (talloc_total_size(null_context) != 0) {
2003 talloc_report_full(null_context, stderr);
2008 enable tracking of the NULL context
2010 _PUBLIC_ void talloc_enable_null_tracking(void)
2012 if (null_context == NULL) {
2013 null_context = _talloc_named_const(NULL, 0, "null_context");
2014 if (autofree_context != NULL) {
2015 talloc_reparent(NULL, null_context, autofree_context);
2021 enable tracking of the NULL context, not moving the autofree context
2022 into the NULL context. This is needed for the talloc testsuite
2024 _PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
2026 if (null_context == NULL) {
2027 null_context = _talloc_named_const(NULL, 0, "null_context");
2032 disable tracking of the NULL context
2034 _PUBLIC_ void talloc_disable_null_tracking(void)
2036 if (null_context != NULL) {
2037 /* we have to move any children onto the real NULL
2038 context */
2039 struct talloc_chunk *tc, *tc2;
2040 tc = talloc_chunk_from_ptr(null_context);
2041 for (tc2 = tc->child; tc2; tc2=tc2->next) {
2042 if (tc2->parent == tc) tc2->parent = NULL;
2043 if (tc2->prev == tc) tc2->prev = NULL;
2045 for (tc2 = tc->next; tc2; tc2=tc2->next) {
2046 if (tc2->parent == tc) tc2->parent = NULL;
2047 if (tc2->prev == tc) tc2->prev = NULL;
2049 tc->child = NULL;
2050 tc->next = NULL;
2052 talloc_free(null_context);
2053 null_context = NULL;
2057 enable leak reporting on exit
2059 _PUBLIC_ void talloc_enable_leak_report(void)
2061 talloc_enable_null_tracking();
2062 atexit(talloc_report_null);
2066 enable full leak reporting on exit
2068 _PUBLIC_ void talloc_enable_leak_report_full(void)
2070 talloc_enable_null_tracking();
2071 atexit(talloc_report_null_full);
2075 talloc and zero memory.
2077 _PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
2079 void *p = _talloc_named_const(ctx, size, name);
2081 if (p) {
2082 memset(p, '\0', size);
2085 return p;
2089 memdup with a talloc.
2091 _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
2093 void *newp = _talloc_named_const(t, size, name);
2095 if (likely(newp)) {
2096 memcpy(newp, p, size);
2099 return newp;
2102 static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
2104 char *ret;
2106 ret = (char *)__talloc(t, len + 1);
2107 if (unlikely(!ret)) return NULL;
2109 memcpy(ret, p, len);
2110 ret[len] = 0;
2112 _talloc_set_name_const(ret, ret);
2113 return ret;
2117 strdup with a talloc
2119 _PUBLIC_ char *talloc_strdup(const void *t, const char *p)
2121 if (unlikely(!p)) return NULL;
2122 return __talloc_strlendup(t, p, strlen(p));
2126 strndup with a talloc
2128 _PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
2130 if (unlikely(!p)) return NULL;
2131 return __talloc_strlendup(t, p, strnlen(p, n));
2134 static inline char *__talloc_strlendup_append(char *s, size_t slen,
2135 const char *a, size_t alen)
2137 char *ret;
2139 ret = talloc_realloc(NULL, s, char, slen + alen + 1);
2140 if (unlikely(!ret)) return NULL;
2142 /* append the string and the trailing \0 */
2143 memcpy(&ret[slen], a, alen);
2144 ret[slen+alen] = 0;
2146 _talloc_set_name_const(ret, ret);
2147 return ret;
2151 * Appends at the end of the string.
2153 _PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
2155 if (unlikely(!s)) {
2156 return talloc_strdup(NULL, a);
2159 if (unlikely(!a)) {
2160 return s;
2163 return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
2167 * Appends at the end of the talloc'ed buffer,
2168 * not the end of the string.
2170 _PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
2172 size_t slen;
2174 if (unlikely(!s)) {
2175 return talloc_strdup(NULL, a);
2178 if (unlikely(!a)) {
2179 return s;
2182 slen = talloc_get_size(s);
2183 if (likely(slen > 0)) {
2184 slen--;
2187 return __talloc_strlendup_append(s, slen, a, strlen(a));
2191 * Appends at the end of the string.
2193 _PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
2195 if (unlikely(!s)) {
2196 return talloc_strndup(NULL, a, n);
2199 if (unlikely(!a)) {
2200 return s;
2203 return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
2207 * Appends at the end of the talloc'ed buffer,
2208 * not the end of the string.
2210 _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
2212 size_t slen;
2214 if (unlikely(!s)) {
2215 return talloc_strndup(NULL, a, n);
2218 if (unlikely(!a)) {
2219 return s;
2222 slen = talloc_get_size(s);
2223 if (likely(slen > 0)) {
2224 slen--;
2227 return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
2230 #ifndef HAVE_VA_COPY
2231 #ifdef HAVE___VA_COPY
2232 #define va_copy(dest, src) __va_copy(dest, src)
2233 #else
2234 #define va_copy(dest, src) (dest) = (src)
2235 #endif
2236 #endif
2238 _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
2240 int len;
2241 char *ret;
2242 va_list ap2;
2243 char c;
2245 /* this call looks strange, but it makes it work on older solaris boxes */
2246 va_copy(ap2, ap);
2247 len = vsnprintf(&c, 1, fmt, ap2);
2248 va_end(ap2);
2249 if (unlikely(len < 0)) {
2250 return NULL;
2253 ret = (char *)__talloc(t, len+1);
2254 if (unlikely(!ret)) return NULL;
2256 va_copy(ap2, ap);
2257 vsnprintf(ret, len+1, fmt, ap2);
2258 va_end(ap2);
2260 _talloc_set_name_const(ret, ret);
2261 return ret;
2266 Perform string formatting, and return a pointer to newly allocated
2267 memory holding the result, inside a memory pool.
2269 _PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
2271 va_list ap;
2272 char *ret;
2274 va_start(ap, fmt);
2275 ret = talloc_vasprintf(t, fmt, ap);
2276 va_end(ap);
2277 return ret;
2280 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2281 const char *fmt, va_list ap)
2282 PRINTF_ATTRIBUTE(3,0);
2284 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2285 const char *fmt, va_list ap)
2287 ssize_t alen;
2288 va_list ap2;
2289 char c;
2291 va_copy(ap2, ap);
2292 alen = vsnprintf(&c, 1, fmt, ap2);
2293 va_end(ap2);
2295 if (alen <= 0) {
2296 /* Either the vsnprintf failed or the format resulted in
2297 * no characters being formatted. In the former case, we
2298 * ought to return NULL, in the latter we ought to return
2299 * the original string. Most current callers of this
2300 * function expect it to never return NULL.
2302 return s;
2305 s = talloc_realloc(NULL, s, char, slen + alen + 1);
2306 if (!s) return NULL;
2308 va_copy(ap2, ap);
2309 vsnprintf(s + slen, alen + 1, fmt, ap2);
2310 va_end(ap2);
2312 _talloc_set_name_const(s, s);
2313 return s;
2317 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2318 * and return @p s, which may have moved. Good for gradually
2319 * accumulating output into a string buffer. Appends at the end
2320 * of the string.
2322 _PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
2324 if (unlikely(!s)) {
2325 return talloc_vasprintf(NULL, fmt, ap);
2328 return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
2332 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2333 * and return @p s, which may have moved. Always appends at the
2334 * end of the talloc'ed buffer, not the end of the string.
2336 _PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
2338 size_t slen;
2340 if (unlikely(!s)) {
2341 return talloc_vasprintf(NULL, fmt, ap);
2344 slen = talloc_get_size(s);
2345 if (likely(slen > 0)) {
2346 slen--;
2349 return __talloc_vaslenprintf_append(s, slen, fmt, ap);
2353 Realloc @p s to append the formatted result of @p fmt and return @p
2354 s, which may have moved. Good for gradually accumulating output
2355 into a string buffer.
2357 _PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
2359 va_list ap;
2361 va_start(ap, fmt);
2362 s = talloc_vasprintf_append(s, fmt, ap);
2363 va_end(ap);
2364 return s;
2368 Realloc @p s to append the formatted result of @p fmt and return @p
2369 s, which may have moved. Good for gradually accumulating output
2370 into a buffer.
2372 _PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
2374 va_list ap;
2376 va_start(ap, fmt);
2377 s = talloc_vasprintf_append_buffer(s, fmt, ap);
2378 va_end(ap);
2379 return s;
2383 alloc an array, checking for integer overflow in the array size
2385 _PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2387 if (count >= MAX_TALLOC_SIZE/el_size) {
2388 return NULL;
2390 return _talloc_named_const(ctx, el_size * count, name);
2394 alloc an zero array, checking for integer overflow in the array size
2396 _PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2398 if (count >= MAX_TALLOC_SIZE/el_size) {
2399 return NULL;
2401 return _talloc_zero(ctx, el_size * count, name);
2405 realloc an array, checking for integer overflow in the array size
2407 _PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
2409 if (count >= MAX_TALLOC_SIZE/el_size) {
2410 return NULL;
2412 return _talloc_realloc(ctx, ptr, el_size * count, name);
2416 a function version of talloc_realloc(), so it can be passed as a function pointer
2417 to libraries that want a realloc function (a realloc function encapsulates
2418 all the basic capabilities of an allocation library, which is why this is useful)
2420 _PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
2422 return _talloc_realloc(context, ptr, size, NULL);
2426 static int talloc_autofree_destructor(void *ptr)
2428 autofree_context = NULL;
2429 return 0;
2432 static void talloc_autofree(void)
2434 talloc_free(autofree_context);
2438 return a context which will be auto-freed on exit
2439 this is useful for reducing the noise in leak reports
2441 _PUBLIC_ void *talloc_autofree_context(void)
2443 if (autofree_context == NULL) {
2444 autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
2445 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
2446 atexit(talloc_autofree);
2448 return autofree_context;
2451 _PUBLIC_ size_t talloc_get_size(const void *context)
2453 struct talloc_chunk *tc;
2455 if (context == NULL) {
2456 context = null_context;
2458 if (context == NULL) {
2459 return 0;
2462 tc = talloc_chunk_from_ptr(context);
2464 return tc->size;
2468 find a parent of this context that has the given name, if any
2470 _PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
2472 struct talloc_chunk *tc;
2474 if (context == NULL) {
2475 return NULL;
2478 tc = talloc_chunk_from_ptr(context);
2479 while (tc) {
2480 if (tc->name && strcmp(tc->name, name) == 0) {
2481 return TC_PTR_FROM_CHUNK(tc);
2483 while (tc && tc->prev) tc = tc->prev;
2484 if (tc) {
2485 tc = tc->parent;
2488 return NULL;
2492 show the parentage of a context
2494 _PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
2496 struct talloc_chunk *tc;
2498 if (context == NULL) {
2499 fprintf(file, "talloc no parents for NULL\n");
2500 return;
2503 tc = talloc_chunk_from_ptr(context);
2504 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
2505 while (tc) {
2506 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
2507 while (tc && tc->prev) tc = tc->prev;
2508 if (tc) {
2509 tc = tc->parent;
2512 fflush(file);
2516 return 1 if ptr is a parent of context
2518 static int _talloc_is_parent(const void *context, const void *ptr, int depth)
2520 struct talloc_chunk *tc;
2522 if (context == NULL) {
2523 return 0;
2526 tc = talloc_chunk_from_ptr(context);
2527 while (tc && depth > 0) {
2528 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
2529 while (tc && tc->prev) tc = tc->prev;
2530 if (tc) {
2531 tc = tc->parent;
2532 depth--;
2535 return 0;
2539 return 1 if ptr is a parent of context
2541 _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
2543 return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
2547 return the total size of memory used by this context and all children
2549 static size_t _talloc_total_limit_size(const void *ptr,
2550 struct talloc_memlimit *old_limit,
2551 struct talloc_memlimit *new_limit)
2553 return _talloc_total_mem_internal(ptr, TOTAL_MEM_LIMIT,
2554 old_limit, new_limit);
2557 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size)
2559 struct talloc_memlimit *l;
2561 for (l = limit; l != NULL; l = l->upper) {
2562 if (l->max_size != 0 &&
2563 ((l->max_size <= l->cur_size) ||
2564 (l->max_size - l->cur_size < TC_HDR_SIZE+size))) {
2565 return false;
2569 return true;
2573 Update memory limits when freeing a talloc_chunk.
2575 static void talloc_memlimit_update_on_free(struct talloc_chunk *tc)
2577 if (!tc->limit) {
2578 return;
2582 * Pool entries don't count. Only the pools
2583 * themselves are counted as part of the memory
2584 * limits.
2586 if (tc->flags & TALLOC_FLAG_POOLMEM) {
2587 return;
2591 * If we are part of a memory limited context hierarchy
2592 * we need to subtract the memory used from the counters
2595 talloc_memlimit_shrink(tc->limit, tc->size+TC_HDR_SIZE);
2597 if (tc->limit->parent == tc) {
2598 free(tc->limit);
2601 tc->limit = NULL;
2605 Increase memory limit accounting after a malloc/realloc.
2607 static void talloc_memlimit_grow(struct talloc_memlimit *limit,
2608 size_t size)
2610 struct talloc_memlimit *l;
2612 for (l = limit; l != NULL; l = l->upper) {
2613 size_t new_cur_size = l->cur_size + size;
2614 if (new_cur_size < l->cur_size) {
2615 talloc_abort("logic error in talloc_memlimit_grow\n");
2616 return;
2618 l->cur_size = new_cur_size;
2623 Decrease memory limit accounting after a free/realloc.
2625 static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
2626 size_t size)
2628 struct talloc_memlimit *l;
2630 for (l = limit; l != NULL; l = l->upper) {
2631 if (l->cur_size < size) {
2632 talloc_abort("logic error in talloc_memlimit_shrink\n");
2633 return;
2635 l->cur_size = l->cur_size - size;
2639 static bool talloc_memlimit_update(struct talloc_memlimit *limit,
2640 size_t old_size, size_t new_size)
2642 struct talloc_memlimit *l;
2643 ssize_t d;
2645 if (old_size == 0) {
2646 d = new_size + TC_HDR_SIZE;
2647 } else {
2648 d = new_size - old_size;
2650 for (l = limit; l != NULL; l = l->upper) {
2651 ssize_t new_cur_size = l->cur_size + d;
2652 if (new_cur_size < 0) {
2653 return false;
2655 l->cur_size = new_cur_size;
2658 return true;
2661 _PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size)
2663 struct talloc_chunk *tc = talloc_chunk_from_ptr(ctx);
2664 struct talloc_memlimit *orig_limit;
2665 struct talloc_memlimit *limit = NULL;
2667 if (tc->limit && tc->limit->parent == tc) {
2668 tc->limit->max_size = max_size;
2669 return 0;
2671 orig_limit = tc->limit;
2673 limit = malloc(sizeof(struct talloc_memlimit));
2674 if (limit == NULL) {
2675 return 1;
2677 limit->parent = tc;
2678 limit->max_size = max_size;
2679 limit->cur_size = _talloc_total_limit_size(ctx, tc->limit, limit);
2681 if (orig_limit) {
2682 limit->upper = orig_limit;
2683 } else {
2684 limit->upper = NULL;
2687 return 0;