Change __talloc() to only call talloc_memlimit_check()/talloc_memlimit_grow() on...
[Samba.git] / lib / talloc / talloc.c
blobcee7d23ef7cfb382d03c23df42fab0f0248aa7b0
1 /*
2 Samba Unix SMB/CIFS implementation.
4 Samba trivial allocation library - new interface
6 NOTE: Please read talloc_guide.txt for full documentation
8 Copyright (C) Andrew Tridgell 2004
9 Copyright (C) Stefan Metzmacher 2006
11 ** NOTE! The following LGPL license applies to the talloc
12 ** library. This does NOT imply that all of Samba is released
13 ** under the LGPL
15 This library is free software; you can redistribute it and/or
16 modify it under the terms of the GNU Lesser General Public
17 License as published by the Free Software Foundation; either
18 version 3 of the License, or (at your option) any later version.
20 This library is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Lesser General Public License for more details.
25 You should have received a copy of the GNU Lesser General Public
26 License along with this library; if not, see <http://www.gnu.org/licenses/>.
30 inspired by http://swapped.cc/halloc/
33 #include "replace.h"
34 #include "talloc.h"
36 #ifdef TALLOC_BUILD_VERSION_MAJOR
37 #if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR)
38 #error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR"
39 #endif
40 #endif
42 #ifdef TALLOC_BUILD_VERSION_MINOR
43 #if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR)
44 #error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR"
45 #endif
46 #endif
48 /* Special macros that are no-ops except when run under Valgrind on
49 * x86. They've moved a little bit from valgrind 1.0.4 to 1.9.4 */
50 #ifdef HAVE_VALGRIND_MEMCHECK_H
51 /* memcheck.h includes valgrind.h */
52 #include <valgrind/memcheck.h>
53 #elif defined(HAVE_VALGRIND_H)
54 #include <valgrind.h>
55 #endif
57 /* use this to force every realloc to change the pointer, to stress test
58 code that might not cope */
59 #define ALWAYS_REALLOC 0
62 #define MAX_TALLOC_SIZE 0x10000000
63 #define TALLOC_MAGIC_BASE 0xe814ec70
64 #define TALLOC_MAGIC ( \
65 TALLOC_MAGIC_BASE + \
66 (TALLOC_VERSION_MAJOR << 12) + \
67 (TALLOC_VERSION_MINOR << 4) \
70 #define TALLOC_FLAG_FREE 0x01
71 #define TALLOC_FLAG_LOOP 0x02
72 #define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */
73 #define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */
75 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
77 /* by default we abort when given a bad pointer (such as when talloc_free() is called
78 on a pointer that came from malloc() */
79 #ifndef TALLOC_ABORT
80 #define TALLOC_ABORT(reason) abort()
81 #endif
83 #ifndef discard_const_p
84 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
85 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
86 #else
87 # define discard_const_p(type, ptr) ((type *)(ptr))
88 #endif
89 #endif
91 /* these macros gain us a few percent of speed on gcc */
92 #if (__GNUC__ >= 3)
93 /* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
94 as its first argument */
95 #ifndef likely
96 #define likely(x) __builtin_expect(!!(x), 1)
97 #endif
98 #ifndef unlikely
99 #define unlikely(x) __builtin_expect(!!(x), 0)
100 #endif
101 #else
102 #ifndef likely
103 #define likely(x) (x)
104 #endif
105 #ifndef unlikely
106 #define unlikely(x) (x)
107 #endif
108 #endif
110 /* this null_context is only used if talloc_enable_leak_report() or
111 talloc_enable_leak_report_full() is called, otherwise it remains
112 NULL
114 static void *null_context;
115 static void *autofree_context;
117 /* used to enable fill of memory on free, which can be useful for
118 * catching use after free errors when valgrind is too slow
120 static struct {
121 bool initialised;
122 bool enabled;
123 uint8_t fill_value;
124 } talloc_fill;
126 #define TALLOC_FILL_ENV "TALLOC_FREE_FILL"
129 * do not wipe the header, to allow the
130 * double-free logic to still work
132 #define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \
133 if (unlikely(talloc_fill.enabled)) { \
134 size_t _flen = (_tc)->size; \
135 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
136 memset(_fptr, talloc_fill.fill_value, _flen); \
138 } while (0)
140 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
141 /* Mark the whole chunk as not accessable */
142 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \
143 size_t _flen = TC_HDR_SIZE + (_tc)->size; \
144 char *_fptr = (char *)(_tc); \
145 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
146 } while(0)
147 #else
148 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0)
149 #endif
151 #define TC_INVALIDATE_FULL_CHUNK(_tc) do { \
152 TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \
153 TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \
154 } while (0)
156 #define TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
157 if (unlikely(talloc_fill.enabled)) { \
158 size_t _flen = (_tc)->size - (_new_size); \
159 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
160 _fptr += (_new_size); \
161 memset(_fptr, talloc_fill.fill_value, _flen); \
163 } while (0)
165 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
166 /* Mark the unused bytes not accessable */
167 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
168 size_t _flen = (_tc)->size - (_new_size); \
169 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
170 _fptr += (_new_size); \
171 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
172 } while (0)
173 #else
174 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
175 #endif
177 #define TC_INVALIDATE_SHRINK_CHUNK(_tc, _new_size) do { \
178 TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size); \
179 TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
180 } while (0)
182 #define TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
183 if (unlikely(talloc_fill.enabled)) { \
184 size_t _flen = (_tc)->size - (_new_size); \
185 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
186 _fptr += (_new_size); \
187 memset(_fptr, talloc_fill.fill_value, _flen); \
189 } while (0)
191 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
192 /* Mark the unused bytes as undefined */
193 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
194 size_t _flen = (_tc)->size - (_new_size); \
195 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
196 _fptr += (_new_size); \
197 VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
198 } while (0)
199 #else
200 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
201 #endif
203 #define TC_UNDEFINE_SHRINK_CHUNK(_tc, _new_size) do { \
204 TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size); \
205 TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
206 } while (0)
208 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
209 /* Mark the new bytes as undefined */
210 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { \
211 size_t _old_used = TC_HDR_SIZE + (_tc)->size; \
212 size_t _new_used = TC_HDR_SIZE + (_new_size); \
213 size_t _flen = _new_used - _old_used; \
214 char *_fptr = _old_used + (char *)(_tc); \
215 VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
216 } while (0)
217 #else
218 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
219 #endif
221 #define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \
222 TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \
223 } while (0)
225 struct talloc_reference_handle {
226 struct talloc_reference_handle *next, *prev;
227 void *ptr;
228 const char *location;
231 struct talloc_memlimit {
232 struct talloc_chunk *parent;
233 struct talloc_memlimit *upper;
234 size_t max_size;
235 size_t cur_size;
238 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size);
239 static bool talloc_memlimit_update(struct talloc_memlimit *limit,
240 size_t old_size, size_t new_size);
241 static void talloc_memlimit_grow(struct talloc_memlimit *limit,
242 size_t size);
243 static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
244 size_t size);
245 static void talloc_memlimit_update_on_free(struct talloc_chunk *tc);
247 typedef int (*talloc_destructor_t)(void *);
249 struct talloc_chunk {
250 struct talloc_chunk *next, *prev;
251 struct talloc_chunk *parent, *child;
252 struct talloc_reference_handle *refs;
253 talloc_destructor_t destructor;
254 const char *name;
255 size_t size;
256 unsigned flags;
259 * limit semantics:
260 * if 'limit' is set it means all *new* children of the context will
261 * be limited to a total aggregate size ox max_size for memory
262 * allocations.
263 * cur_size is used to keep track of the current use
265 struct talloc_memlimit *limit;
268 * "pool" has dual use:
270 * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
271 * marks the end of the currently allocated area.
273 * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
274 * is a pointer to the struct talloc_chunk of the pool that it was
275 * allocated from. This way children can quickly find the pool to chew
276 * from.
278 void *pool;
281 /* 16 byte alignment seems to keep everyone happy */
282 #define TC_ALIGN16(s) (((s)+15)&~15)
283 #define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
284 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
286 _PUBLIC_ int talloc_version_major(void)
288 return TALLOC_VERSION_MAJOR;
291 _PUBLIC_ int talloc_version_minor(void)
293 return TALLOC_VERSION_MINOR;
296 static void (*talloc_log_fn)(const char *message);
298 _PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
300 talloc_log_fn = log_fn;
303 static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
304 static void talloc_log(const char *fmt, ...)
306 va_list ap;
307 char *message;
309 if (!talloc_log_fn) {
310 return;
313 va_start(ap, fmt);
314 message = talloc_vasprintf(NULL, fmt, ap);
315 va_end(ap);
317 talloc_log_fn(message);
318 talloc_free(message);
321 static void talloc_log_stderr(const char *message)
323 fprintf(stderr, "%s", message);
326 _PUBLIC_ void talloc_set_log_stderr(void)
328 talloc_set_log_fn(talloc_log_stderr);
331 static void (*talloc_abort_fn)(const char *reason);
333 _PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
335 talloc_abort_fn = abort_fn;
338 static void talloc_abort(const char *reason)
340 talloc_log("%s\n", reason);
342 if (!talloc_abort_fn) {
343 TALLOC_ABORT(reason);
346 talloc_abort_fn(reason);
349 static void talloc_abort_magic(unsigned magic)
351 unsigned striped = magic - TALLOC_MAGIC_BASE;
352 unsigned major = (striped & 0xFFFFF000) >> 12;
353 unsigned minor = (striped & 0x00000FF0) >> 4;
354 talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
355 magic, major, minor,
356 TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR);
357 talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
360 static void talloc_abort_access_after_free(void)
362 talloc_abort("Bad talloc magic value - access after free");
365 static void talloc_abort_unknown_value(void)
367 talloc_abort("Bad talloc magic value - unknown value");
370 /* panic if we get a bad magic value */
371 static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
373 const char *pp = (const char *)ptr;
374 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
375 if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
376 if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) {
377 talloc_abort_magic(tc->flags & (~0xF));
378 return NULL;
381 if (tc->flags & TALLOC_FLAG_FREE) {
382 talloc_log("talloc: access after free error - first free may be at %s\n", tc->name);
383 talloc_abort_access_after_free();
384 return NULL;
385 } else {
386 talloc_abort_unknown_value();
387 return NULL;
390 return tc;
393 /* hook into the front of the list */
394 #define _TLIST_ADD(list, p) \
395 do { \
396 if (!(list)) { \
397 (list) = (p); \
398 (p)->next = (p)->prev = NULL; \
399 } else { \
400 (list)->prev = (p); \
401 (p)->next = (list); \
402 (p)->prev = NULL; \
403 (list) = (p); \
405 } while (0)
407 /* remove an element from a list - element doesn't have to be in list. */
408 #define _TLIST_REMOVE(list, p) \
409 do { \
410 if ((p) == (list)) { \
411 (list) = (p)->next; \
412 if (list) (list)->prev = NULL; \
413 } else { \
414 if ((p)->prev) (p)->prev->next = (p)->next; \
415 if ((p)->next) (p)->next->prev = (p)->prev; \
417 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
418 } while (0)
422 return the parent chunk of a pointer
424 static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
426 struct talloc_chunk *tc;
428 if (unlikely(ptr == NULL)) {
429 return NULL;
432 tc = talloc_chunk_from_ptr(ptr);
433 while (tc->prev) tc=tc->prev;
435 return tc->parent;
438 _PUBLIC_ void *talloc_parent(const void *ptr)
440 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
441 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
445 find parents name
447 _PUBLIC_ const char *talloc_parent_name(const void *ptr)
449 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
450 return tc? tc->name : NULL;
454 A pool carries an in-pool object count count in the first 16 bytes.
455 bytes. This is done to support talloc_steal() to a parent outside of the
456 pool. The count includes the pool itself, so a talloc_free() on a pool will
457 only destroy the pool if the count has dropped to zero. A talloc_free() of a
458 pool member will reduce the count, and eventually also call free(3) on the
459 pool memory.
461 The object count is not put into "struct talloc_chunk" because it is only
462 relevant for talloc pools and the alignment to 16 bytes would increase the
463 memory footprint of each talloc chunk by those 16 bytes.
466 union talloc_pool_chunk {
467 /* This lets object_count nestle into 16-byte padding of talloc_chunk,
468 * on 32-bit platforms. */
469 struct tc_pool_hdr {
470 struct talloc_chunk c;
471 unsigned int object_count;
472 } hdr;
473 /* This makes it always 16 byte aligned. */
474 char pad[TC_ALIGN16(sizeof(struct tc_pool_hdr))];
477 static void *tc_pool_end(union talloc_pool_chunk *pool_tc)
479 return (char *)pool_tc + TC_HDR_SIZE + pool_tc->hdr.c.size;
482 static size_t tc_pool_space_left(union talloc_pool_chunk *pool_tc)
484 return (char *)tc_pool_end(pool_tc) - (char *)pool_tc->hdr.c.pool;
487 static void *tc_pool_first_chunk(union talloc_pool_chunk *pool_tc)
489 return pool_tc + 1;
492 /* If tc is inside a pool, this gives the next neighbour. */
493 static void *tc_next_chunk(struct talloc_chunk *tc)
495 return (char *)tc + TC_ALIGN16(TC_HDR_SIZE + tc->size);
498 /* Mark the whole remaining pool as not accessable */
499 static void tc_invalidate_pool(union talloc_pool_chunk *pool_tc)
501 size_t flen = tc_pool_space_left(pool_tc);
503 if (unlikely(talloc_fill.enabled)) {
504 memset(pool_tc->hdr.c.pool, talloc_fill.fill_value, flen);
507 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
508 VALGRIND_MAKE_MEM_NOACCESS(pool_tc->hdr.c.pool, flen);
509 #endif
513 Allocate from a pool
516 static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
517 size_t size)
519 union talloc_pool_chunk *pool_ctx = NULL;
520 size_t space_left;
521 struct talloc_chunk *result;
522 size_t chunk_size;
524 if (parent == NULL) {
525 return NULL;
528 if (parent->flags & TALLOC_FLAG_POOL) {
529 pool_ctx = (union talloc_pool_chunk *)parent;
531 else if (parent->flags & TALLOC_FLAG_POOLMEM) {
532 pool_ctx = (union talloc_pool_chunk *)parent->pool;
535 if (pool_ctx == NULL) {
536 return NULL;
539 space_left = tc_pool_space_left(pool_ctx);
542 * Align size to 16 bytes
544 chunk_size = TC_ALIGN16(size);
546 if (space_left < chunk_size) {
547 return NULL;
550 result = (struct talloc_chunk *)pool_ctx->hdr.c.pool;
552 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
553 VALGRIND_MAKE_MEM_UNDEFINED(result, size);
554 #endif
556 pool_ctx->hdr.c.pool = (void *)((char *)result + chunk_size);
558 result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
559 result->pool = pool_ctx;
561 pool_ctx->hdr.object_count++;
563 return result;
567 Allocate a bit of memory as a child of an existing pointer
569 static inline void *__talloc(const void *context, size_t size)
571 struct talloc_chunk *tc = NULL;
572 struct talloc_memlimit *limit = NULL;
574 if (unlikely(context == NULL)) {
575 context = null_context;
578 if (unlikely(size >= MAX_TALLOC_SIZE)) {
579 return NULL;
582 if (context != NULL) {
583 struct talloc_chunk *ptc = talloc_chunk_from_ptr(context);
585 if (ptc->limit != NULL) {
586 limit = ptc->limit;
589 tc = talloc_alloc_pool(ptc, TC_HDR_SIZE+size);
592 if (tc == NULL) {
594 * Only do the memlimit check/update on actual allocation.
596 if (!talloc_memlimit_check(limit, TC_HDR_SIZE + size)) {
597 errno = ENOMEM;
598 return NULL;
601 tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
602 if (unlikely(tc == NULL)) return NULL;
603 tc->flags = TALLOC_MAGIC;
604 tc->pool = NULL;
606 talloc_memlimit_grow(limit, TC_HDR_SIZE + size);
609 tc->limit = limit;
610 tc->size = size;
611 tc->destructor = NULL;
612 tc->child = NULL;
613 tc->name = NULL;
614 tc->refs = NULL;
616 if (likely(context)) {
617 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
619 if (parent->child) {
620 parent->child->parent = NULL;
621 tc->next = parent->child;
622 tc->next->prev = tc;
623 } else {
624 tc->next = NULL;
626 tc->parent = parent;
627 tc->prev = NULL;
628 parent->child = tc;
629 } else {
630 tc->next = tc->prev = tc->parent = NULL;
633 return TC_PTR_FROM_CHUNK(tc);
637 * Create a talloc pool
640 _PUBLIC_ void *talloc_pool(const void *context, size_t size)
642 union talloc_pool_chunk *pool_tc;
643 void *result = __talloc(context, sizeof(*pool_tc) - TC_HDR_SIZE + size);
645 if (unlikely(result == NULL)) {
646 return NULL;
649 pool_tc = (union talloc_pool_chunk *)talloc_chunk_from_ptr(result);
650 if (unlikely(pool_tc->hdr.c.flags & TALLOC_FLAG_POOLMEM)) {
651 /* We don't handle this correctly, so fail. */
652 talloc_log("talloc: cannot allocate pool off another pool %s\n",
653 talloc_get_name(context));
654 talloc_free(result);
655 return NULL;
657 pool_tc->hdr.c.flags |= TALLOC_FLAG_POOL;
658 pool_tc->hdr.c.pool = tc_pool_first_chunk(pool_tc);
660 pool_tc->hdr.object_count = 1;
662 tc_invalidate_pool(pool_tc);
664 return result;
668 setup a destructor to be called on free of a pointer
669 the destructor should return 0 on success, or -1 on failure.
670 if the destructor fails then the free is failed, and the memory can
671 be continued to be used
673 _PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
675 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
676 tc->destructor = destructor;
680 increase the reference count on a piece of memory.
682 _PUBLIC_ int talloc_increase_ref_count(const void *ptr)
684 if (unlikely(!talloc_reference(null_context, ptr))) {
685 return -1;
687 return 0;
691 helper for talloc_reference()
693 this is referenced by a function pointer and should not be inline
695 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
697 struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
698 _TLIST_REMOVE(ptr_tc->refs, handle);
699 return 0;
703 more efficient way to add a name to a pointer - the name must point to a
704 true string constant
706 static inline void _talloc_set_name_const(const void *ptr, const char *name)
708 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
709 tc->name = name;
713 internal talloc_named_const()
715 static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
717 void *ptr;
719 ptr = __talloc(context, size);
720 if (unlikely(ptr == NULL)) {
721 return NULL;
724 _talloc_set_name_const(ptr, name);
726 return ptr;
730 make a secondary reference to a pointer, hanging off the given context.
731 the pointer remains valid until both the original caller and this given
732 context are freed.
734 the major use for this is when two different structures need to reference the
735 same underlying data, and you want to be able to free the two instances separately,
736 and in either order
738 _PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
740 struct talloc_chunk *tc;
741 struct talloc_reference_handle *handle;
742 if (unlikely(ptr == NULL)) return NULL;
744 tc = talloc_chunk_from_ptr(ptr);
745 handle = (struct talloc_reference_handle *)_talloc_named_const(context,
746 sizeof(struct talloc_reference_handle),
747 TALLOC_MAGIC_REFERENCE);
748 if (unlikely(handle == NULL)) return NULL;
750 /* note that we hang the destructor off the handle, not the
751 main context as that allows the caller to still setup their
752 own destructor on the context if they want to */
753 talloc_set_destructor(handle, talloc_reference_destructor);
754 handle->ptr = discard_const_p(void, ptr);
755 handle->location = location;
756 _TLIST_ADD(tc->refs, handle);
757 return handle->ptr;
760 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
762 static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
763 const char *location)
765 union talloc_pool_chunk *pool;
766 void *next_tc;
768 pool = (union talloc_pool_chunk *)tc->pool;
769 next_tc = tc_next_chunk(tc);
771 tc->flags |= TALLOC_FLAG_FREE;
773 /* we mark the freed memory with where we called the free
774 * from. This means on a double free error we can report where
775 * the first free came from
777 tc->name = location;
779 TC_INVALIDATE_FULL_CHUNK(tc);
781 if (unlikely(pool->hdr.object_count == 0)) {
782 talloc_abort("Pool object count zero!");
783 return;
786 pool->hdr.object_count--;
788 if (unlikely(pool->hdr.object_count == 1
789 && !(pool->hdr.c.flags & TALLOC_FLAG_FREE))) {
791 * if there is just one object left in the pool
792 * and pool->flags does not have TALLOC_FLAG_FREE,
793 * it means this is the pool itself and
794 * the rest is available for new objects
795 * again.
797 pool->hdr.c.pool = tc_pool_first_chunk(pool);
798 tc_invalidate_pool(pool);
799 return;
802 if (unlikely(pool->hdr.object_count == 0)) {
804 * we mark the freed memory with where we called the free
805 * from. This means on a double free error we can report where
806 * the first free came from
808 pool->hdr.c.name = location;
810 TC_INVALIDATE_FULL_CHUNK(&pool->hdr.c);
811 free(pool);
812 return;
815 if (pool->hdr.c.pool == next_tc) {
817 * if pool->pool still points to end of
818 * 'tc' (which is stored in the 'next_tc' variable),
819 * we can reclaim the memory of 'tc'.
821 pool->hdr.c.pool = tc;
822 return;
826 * Do nothing. The memory is just "wasted", waiting for the pool
827 * itself to be freed.
831 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
832 void *ptr,
833 const char *location);
836 internal talloc_free call
838 static inline int _talloc_free_internal(void *ptr, const char *location)
840 struct talloc_chunk *tc;
842 if (unlikely(ptr == NULL)) {
843 return -1;
846 /* possibly initialised the talloc fill value */
847 if (unlikely(!talloc_fill.initialised)) {
848 const char *fill = getenv(TALLOC_FILL_ENV);
849 if (fill != NULL) {
850 talloc_fill.enabled = true;
851 talloc_fill.fill_value = strtoul(fill, NULL, 0);
853 talloc_fill.initialised = true;
856 tc = talloc_chunk_from_ptr(ptr);
858 if (unlikely(tc->refs)) {
859 int is_child;
860 /* check if this is a reference from a child or
861 * grandchild back to it's parent or grandparent
863 * in that case we need to remove the reference and
864 * call another instance of talloc_free() on the current
865 * pointer.
867 is_child = talloc_is_parent(tc->refs, ptr);
868 _talloc_free_internal(tc->refs, location);
869 if (is_child) {
870 return _talloc_free_internal(ptr, location);
872 return -1;
875 if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
876 /* we have a free loop - stop looping */
877 return 0;
880 if (unlikely(tc->destructor)) {
881 talloc_destructor_t d = tc->destructor;
882 if (d == (talloc_destructor_t)-1) {
883 return -1;
885 tc->destructor = (talloc_destructor_t)-1;
886 if (d(ptr) == -1) {
887 tc->destructor = d;
888 return -1;
890 tc->destructor = NULL;
893 if (tc->parent) {
894 _TLIST_REMOVE(tc->parent->child, tc);
895 if (tc->parent->child) {
896 tc->parent->child->parent = tc->parent;
898 } else {
899 if (tc->prev) tc->prev->next = tc->next;
900 if (tc->next) tc->next->prev = tc->prev;
901 tc->prev = tc->next = NULL;
904 tc->flags |= TALLOC_FLAG_LOOP;
906 _talloc_free_children_internal(tc, ptr, location);
908 tc->flags |= TALLOC_FLAG_FREE;
911 * If we are part of a memory limited context hierarchy
912 * we need to subtract the memory used from the counters
914 if (tc->limit) {
915 struct talloc_memlimit *l;
917 for (l = tc->limit; l != NULL; l = l->upper) {
918 if (l->cur_size >= tc->size+TC_HDR_SIZE) {
919 l->cur_size -= tc->size+TC_HDR_SIZE;
920 } else {
921 talloc_abort("cur_size memlimit counter not correct!");
922 return 0;
926 if (tc->limit->parent == tc) {
927 free(tc->limit);
930 tc->limit = NULL;
933 /* we mark the freed memory with where we called the free
934 * from. This means on a double free error we can report where
935 * the first free came from
937 tc->name = location;
939 if (tc->flags & TALLOC_FLAG_POOL) {
940 union talloc_pool_chunk *pool = (union talloc_pool_chunk *)tc;
942 if (unlikely(pool->hdr.object_count == 0)) {
943 talloc_abort("Pool object count zero!");
944 return 0;
947 pool->hdr.object_count--;
949 if (likely(pool->hdr.object_count != 0)) {
950 return 0;
953 TC_INVALIDATE_FULL_CHUNK(tc);
954 free(tc);
955 return 0;
958 if (tc->flags & TALLOC_FLAG_POOLMEM) {
959 _talloc_free_poolmem(tc, location);
960 return 0;
963 TC_INVALIDATE_FULL_CHUNK(tc);
964 free(tc);
965 return 0;
968 static size_t _talloc_total_limit_size(const void *ptr,
969 struct talloc_memlimit *old_limit,
970 struct talloc_memlimit *new_limit);
973 move a lump of memory from one talloc context to another return the
974 ptr on success, or NULL if it could not be transferred.
975 passing NULL as ptr will always return NULL with no side effects.
977 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr)
979 struct talloc_chunk *tc, *new_tc;
980 size_t ctx_size = 0;
982 if (unlikely(!ptr)) {
983 return NULL;
986 if (unlikely(new_ctx == NULL)) {
987 new_ctx = null_context;
990 tc = talloc_chunk_from_ptr(ptr);
992 if (tc->limit != NULL) {
994 ctx_size = _talloc_total_limit_size(ptr, NULL, NULL);
996 if (!talloc_memlimit_update(tc->limit->upper, ctx_size, 0)) {
997 talloc_abort("cur_size memlimit counter not correct!");
998 errno = EINVAL;
999 return NULL;
1002 if (tc->limit->parent == tc) {
1003 tc->limit->upper = NULL;
1004 } else {
1005 tc->limit = NULL;
1009 if (unlikely(new_ctx == NULL)) {
1010 if (tc->parent) {
1011 _TLIST_REMOVE(tc->parent->child, tc);
1012 if (tc->parent->child) {
1013 tc->parent->child->parent = tc->parent;
1015 } else {
1016 if (tc->prev) tc->prev->next = tc->next;
1017 if (tc->next) tc->next->prev = tc->prev;
1020 tc->parent = tc->next = tc->prev = NULL;
1021 return discard_const_p(void, ptr);
1024 new_tc = talloc_chunk_from_ptr(new_ctx);
1026 if (unlikely(tc == new_tc || tc->parent == new_tc)) {
1027 return discard_const_p(void, ptr);
1030 if (tc->parent) {
1031 _TLIST_REMOVE(tc->parent->child, tc);
1032 if (tc->parent->child) {
1033 tc->parent->child->parent = tc->parent;
1035 } else {
1036 if (tc->prev) tc->prev->next = tc->next;
1037 if (tc->next) tc->next->prev = tc->prev;
1038 tc->prev = tc->next = NULL;
1041 tc->parent = new_tc;
1042 if (new_tc->child) new_tc->child->parent = NULL;
1043 _TLIST_ADD(new_tc->child, tc);
1045 if (tc->limit || new_tc->limit) {
1046 ctx_size = _talloc_total_limit_size(ptr, tc->limit,
1047 new_tc->limit);
1050 if (new_tc->limit) {
1051 struct talloc_memlimit *l;
1053 for (l = new_tc->limit; l != NULL; l = l->upper) {
1054 l->cur_size += ctx_size;
1058 return discard_const_p(void, ptr);
1062 move a lump of memory from one talloc context to another return the
1063 ptr on success, or NULL if it could not be transferred.
1064 passing NULL as ptr will always return NULL with no side effects.
1066 _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
1068 struct talloc_chunk *tc;
1070 if (unlikely(ptr == NULL)) {
1071 return NULL;
1074 tc = talloc_chunk_from_ptr(ptr);
1076 if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
1077 struct talloc_reference_handle *h;
1079 talloc_log("WARNING: talloc_steal with references at %s\n",
1080 location);
1082 for (h=tc->refs; h; h=h->next) {
1083 talloc_log("\treference at %s\n",
1084 h->location);
1088 #if 0
1089 /* this test is probably too expensive to have on in the
1090 normal build, but it useful for debugging */
1091 if (talloc_is_parent(new_ctx, ptr)) {
1092 talloc_log("WARNING: stealing into talloc child at %s\n", location);
1094 #endif
1096 return _talloc_steal_internal(new_ctx, ptr);
1100 this is like a talloc_steal(), but you must supply the old
1101 parent. This resolves the ambiguity in a talloc_steal() which is
1102 called on a context that has more than one parent (via references)
1104 The old parent can be either a reference or a parent
1106 _PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
1108 struct talloc_chunk *tc;
1109 struct talloc_reference_handle *h;
1111 if (unlikely(ptr == NULL)) {
1112 return NULL;
1115 if (old_parent == talloc_parent(ptr)) {
1116 return _talloc_steal_internal(new_parent, ptr);
1119 tc = talloc_chunk_from_ptr(ptr);
1120 for (h=tc->refs;h;h=h->next) {
1121 if (talloc_parent(h) == old_parent) {
1122 if (_talloc_steal_internal(new_parent, h) != h) {
1123 return NULL;
1125 return discard_const_p(void, ptr);
1129 /* it wasn't a parent */
1130 return NULL;
1134 remove a secondary reference to a pointer. This undo's what
1135 talloc_reference() has done. The context and pointer arguments
1136 must match those given to a talloc_reference()
1138 static inline int talloc_unreference(const void *context, const void *ptr)
1140 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1141 struct talloc_reference_handle *h;
1143 if (unlikely(context == NULL)) {
1144 context = null_context;
1147 for (h=tc->refs;h;h=h->next) {
1148 struct talloc_chunk *p = talloc_parent_chunk(h);
1149 if (p == NULL) {
1150 if (context == NULL) break;
1151 } else if (TC_PTR_FROM_CHUNK(p) == context) {
1152 break;
1155 if (h == NULL) {
1156 return -1;
1159 return _talloc_free_internal(h, __location__);
1163 remove a specific parent context from a pointer. This is a more
1164 controlled variant of talloc_free()
1166 _PUBLIC_ int talloc_unlink(const void *context, void *ptr)
1168 struct talloc_chunk *tc_p, *new_p, *tc_c;
1169 void *new_parent;
1171 if (ptr == NULL) {
1172 return -1;
1175 if (context == NULL) {
1176 context = null_context;
1179 if (talloc_unreference(context, ptr) == 0) {
1180 return 0;
1183 if (context != NULL) {
1184 tc_c = talloc_chunk_from_ptr(context);
1185 } else {
1186 tc_c = NULL;
1188 if (tc_c != talloc_parent_chunk(ptr)) {
1189 return -1;
1192 tc_p = talloc_chunk_from_ptr(ptr);
1194 if (tc_p->refs == NULL) {
1195 return _talloc_free_internal(ptr, __location__);
1198 new_p = talloc_parent_chunk(tc_p->refs);
1199 if (new_p) {
1200 new_parent = TC_PTR_FROM_CHUNK(new_p);
1201 } else {
1202 new_parent = NULL;
1205 if (talloc_unreference(new_parent, ptr) != 0) {
1206 return -1;
1209 _talloc_steal_internal(new_parent, ptr);
1211 return 0;
1215 add a name to an existing pointer - va_list version
1217 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1219 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
1221 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1222 tc->name = talloc_vasprintf(ptr, fmt, ap);
1223 if (likely(tc->name)) {
1224 _talloc_set_name_const(tc->name, ".name");
1226 return tc->name;
1230 add a name to an existing pointer
1232 _PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
1234 const char *name;
1235 va_list ap;
1236 va_start(ap, fmt);
1237 name = talloc_set_name_v(ptr, fmt, ap);
1238 va_end(ap);
1239 return name;
1244 create a named talloc pointer. Any talloc pointer can be named, and
1245 talloc_named() operates just like talloc() except that it allows you
1246 to name the pointer.
1248 _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
1250 va_list ap;
1251 void *ptr;
1252 const char *name;
1254 ptr = __talloc(context, size);
1255 if (unlikely(ptr == NULL)) return NULL;
1257 va_start(ap, fmt);
1258 name = talloc_set_name_v(ptr, fmt, ap);
1259 va_end(ap);
1261 if (unlikely(name == NULL)) {
1262 _talloc_free_internal(ptr, __location__);
1263 return NULL;
1266 return ptr;
1270 return the name of a talloc ptr, or "UNNAMED"
1272 _PUBLIC_ const char *talloc_get_name(const void *ptr)
1274 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1275 if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
1276 return ".reference";
1278 if (likely(tc->name)) {
1279 return tc->name;
1281 return "UNNAMED";
1286 check if a pointer has the given name. If it does, return the pointer,
1287 otherwise return NULL
1289 _PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
1291 const char *pname;
1292 if (unlikely(ptr == NULL)) return NULL;
1293 pname = talloc_get_name(ptr);
1294 if (likely(pname == name || strcmp(pname, name) == 0)) {
1295 return discard_const_p(void, ptr);
1297 return NULL;
1300 static void talloc_abort_type_mismatch(const char *location,
1301 const char *name,
1302 const char *expected)
1304 const char *reason;
1306 reason = talloc_asprintf(NULL,
1307 "%s: Type mismatch: name[%s] expected[%s]",
1308 location,
1309 name?name:"NULL",
1310 expected);
1311 if (!reason) {
1312 reason = "Type mismatch";
1315 talloc_abort(reason);
1318 _PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
1320 const char *pname;
1322 if (unlikely(ptr == NULL)) {
1323 talloc_abort_type_mismatch(location, NULL, name);
1324 return NULL;
1327 pname = talloc_get_name(ptr);
1328 if (likely(pname == name || strcmp(pname, name) == 0)) {
1329 return discard_const_p(void, ptr);
1332 talloc_abort_type_mismatch(location, pname, name);
1333 return NULL;
1337 this is for compatibility with older versions of talloc
1339 _PUBLIC_ void *talloc_init(const char *fmt, ...)
1341 va_list ap;
1342 void *ptr;
1343 const char *name;
1345 ptr = __talloc(NULL, 0);
1346 if (unlikely(ptr == NULL)) return NULL;
1348 va_start(ap, fmt);
1349 name = talloc_set_name_v(ptr, fmt, ap);
1350 va_end(ap);
1352 if (unlikely(name == NULL)) {
1353 _talloc_free_internal(ptr, __location__);
1354 return NULL;
1357 return ptr;
1360 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
1361 void *ptr,
1362 const char *location)
1364 while (tc->child) {
1365 /* we need to work out who will own an abandoned child
1366 if it cannot be freed. In priority order, the first
1367 choice is owner of any remaining reference to this
1368 pointer, the second choice is our parent, and the
1369 final choice is the null context. */
1370 void *child = TC_PTR_FROM_CHUNK(tc->child);
1371 const void *new_parent = null_context;
1372 if (unlikely(tc->child->refs)) {
1373 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1374 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1376 if (unlikely(_talloc_free_internal(child, location) == -1)) {
1377 if (new_parent == null_context) {
1378 struct talloc_chunk *p = talloc_parent_chunk(ptr);
1379 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1381 _talloc_steal_internal(new_parent, child);
1387 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1388 should probably not be used in new code. It's in here to keep the talloc
1389 code consistent across Samba 3 and 4.
1391 _PUBLIC_ void talloc_free_children(void *ptr)
1393 struct talloc_chunk *tc_name = NULL;
1394 struct talloc_chunk *tc;
1396 if (unlikely(ptr == NULL)) {
1397 return;
1400 tc = talloc_chunk_from_ptr(ptr);
1402 /* we do not want to free the context name if it is a child .. */
1403 if (likely(tc->child)) {
1404 for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
1405 if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
1407 if (tc_name) {
1408 _TLIST_REMOVE(tc->child, tc_name);
1409 if (tc->child) {
1410 tc->child->parent = tc;
1415 _talloc_free_children_internal(tc, ptr, __location__);
1417 /* .. so we put it back after all other children have been freed */
1418 if (tc_name) {
1419 if (tc->child) {
1420 tc->child->parent = NULL;
1422 tc_name->parent = tc;
1423 _TLIST_ADD(tc->child, tc_name);
1428 Allocate a bit of memory as a child of an existing pointer
1430 _PUBLIC_ void *_talloc(const void *context, size_t size)
1432 return __talloc(context, size);
1436 externally callable talloc_set_name_const()
1438 _PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
1440 _talloc_set_name_const(ptr, name);
1444 create a named talloc pointer. Any talloc pointer can be named, and
1445 talloc_named() operates just like talloc() except that it allows you
1446 to name the pointer.
1448 _PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
1450 return _talloc_named_const(context, size, name);
1454 free a talloc pointer. This also frees all child pointers of this
1455 pointer recursively
1457 return 0 if the memory is actually freed, otherwise -1. The memory
1458 will not be freed if the ref_count is > 1 or the destructor (if
1459 any) returns non-zero
1461 _PUBLIC_ int _talloc_free(void *ptr, const char *location)
1463 struct talloc_chunk *tc;
1465 if (unlikely(ptr == NULL)) {
1466 return -1;
1469 tc = talloc_chunk_from_ptr(ptr);
1471 if (unlikely(tc->refs != NULL)) {
1472 struct talloc_reference_handle *h;
1474 if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
1475 /* in this case we do know which parent should
1476 get this pointer, as there is really only
1477 one parent */
1478 return talloc_unlink(null_context, ptr);
1481 talloc_log("ERROR: talloc_free with references at %s\n",
1482 location);
1484 for (h=tc->refs; h; h=h->next) {
1485 talloc_log("\treference at %s\n",
1486 h->location);
1488 return -1;
1491 return _talloc_free_internal(ptr, location);
1497 A talloc version of realloc. The context argument is only used if
1498 ptr is NULL
1500 _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
1502 struct talloc_chunk *tc;
1503 void *new_ptr;
1504 bool malloced = false;
1505 union talloc_pool_chunk *pool_tc = NULL;
1507 /* size zero is equivalent to free() */
1508 if (unlikely(size == 0)) {
1509 talloc_unlink(context, ptr);
1510 return NULL;
1513 if (unlikely(size >= MAX_TALLOC_SIZE)) {
1514 return NULL;
1517 /* realloc(NULL) is equivalent to malloc() */
1518 if (ptr == NULL) {
1519 return _talloc_named_const(context, size, name);
1522 tc = talloc_chunk_from_ptr(ptr);
1524 /* don't allow realloc on referenced pointers */
1525 if (unlikely(tc->refs)) {
1526 return NULL;
1529 /* don't let anybody try to realloc a talloc_pool */
1530 if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
1531 return NULL;
1534 if (tc->limit && (size - tc->size > 0)) {
1535 if (!talloc_memlimit_check(tc->limit, (size - tc->size))) {
1536 errno = ENOMEM;
1537 return NULL;
1541 /* handle realloc inside a talloc_pool */
1542 if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
1543 pool_tc = (union talloc_pool_chunk *)tc->pool;
1546 #if (ALWAYS_REALLOC == 0)
1547 /* don't shrink if we have less than 1k to gain */
1548 if (size < tc->size && tc->limit == NULL) {
1549 if (pool_tc) {
1550 void *next_tc = tc_next_chunk(tc);
1551 TC_INVALIDATE_SHRINK_CHUNK(tc, size);
1552 tc->size = size;
1553 if (next_tc == pool_tc->hdr.c.pool) {
1554 /* note: tc->size has changed, so this works */
1555 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1557 return ptr;
1558 } else if ((tc->size - size) < 1024) {
1560 * if we call TC_INVALIDATE_SHRINK_CHUNK() here
1561 * we would need to call TC_UNDEFINE_GROW_CHUNK()
1562 * after each realloc call, which slows down
1563 * testing a lot :-(.
1565 * That is why we only mark memory as undefined here.
1567 TC_UNDEFINE_SHRINK_CHUNK(tc, size);
1569 /* do not shrink if we have less than 1k to gain */
1570 tc->size = size;
1571 return ptr;
1573 } else if (tc->size == size) {
1575 * do not change the pointer if it is exactly
1576 * the same size.
1578 return ptr;
1580 #endif
1582 /* by resetting magic we catch users of the old memory */
1583 tc->flags |= TALLOC_FLAG_FREE;
1585 #if ALWAYS_REALLOC
1586 if (pool_tc) {
1587 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1588 pool_tc->hdr.object_count--;
1590 if (new_ptr == NULL) {
1591 new_ptr = malloc(TC_HDR_SIZE+size);
1592 malloced = true;
1595 if (new_ptr) {
1596 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1597 TC_INVALIDATE_FULL_CHUNK(tc);
1599 } else {
1600 new_ptr = malloc(size + TC_HDR_SIZE);
1601 if (new_ptr) {
1602 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1603 free(tc);
1606 #else
1607 if (pool_tc) {
1608 void *next_tc = tc_next_chunk(tc);
1609 size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size);
1610 size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
1611 size_t space_needed;
1612 size_t space_left;
1613 unsigned int chunk_count = pool_tc->hdr.object_count;
1615 if (!(pool_tc->hdr.c.flags & TALLOC_FLAG_FREE)) {
1616 chunk_count -= 1;
1619 if (chunk_count == 1) {
1621 * optimize for the case where 'tc' is the only
1622 * chunk in the pool.
1624 char *start = tc_pool_first_chunk(pool_tc);
1625 space_needed = new_chunk_size;
1626 space_left = (char *)tc_pool_end(pool_tc) - start;
1628 if (space_left >= space_needed) {
1629 size_t old_used = TC_HDR_SIZE + tc->size;
1630 size_t new_used = TC_HDR_SIZE + size;
1631 new_ptr = start;
1632 memmove(new_ptr, tc, old_used);
1634 tc = (struct talloc_chunk *)new_ptr;
1635 TC_UNDEFINE_GROW_CHUNK(tc, size);
1638 * first we do not align the pool pointer
1639 * because we want to invalidate the padding
1640 * too.
1642 pool_tc->hdr.c.pool = new_used + (char *)new_ptr;
1643 tc_invalidate_pool(pool_tc);
1645 /* now the aligned pointer */
1646 pool_tc->hdr.c.pool = new_chunk_size + (char *)new_ptr;
1647 goto got_new_ptr;
1650 next_tc = NULL;
1653 if (new_chunk_size == old_chunk_size) {
1654 TC_UNDEFINE_GROW_CHUNK(tc, size);
1655 tc->flags &= ~TALLOC_FLAG_FREE;
1656 if (!talloc_memlimit_update(tc->limit,
1657 tc->size, size)) {
1658 talloc_abort("cur_size memlimit counter not"
1659 " correct!");
1660 errno = EINVAL;
1661 return NULL;
1664 tc->size = size;
1665 return ptr;
1668 if (next_tc == pool_tc->hdr.c.pool) {
1670 * optimize for the case where 'tc' is the last
1671 * chunk in the pool.
1673 space_needed = new_chunk_size - old_chunk_size;
1674 space_left = tc_pool_space_left(pool_tc);
1676 if (space_left >= space_needed) {
1677 TC_UNDEFINE_GROW_CHUNK(tc, size);
1678 tc->flags &= ~TALLOC_FLAG_FREE;
1679 if (!talloc_memlimit_update(tc->limit,
1680 tc->size, size)) {
1681 talloc_abort("cur_size memlimit "
1682 "counter not correct!");
1683 errno = EINVAL;
1684 return NULL;
1686 tc->size = size;
1687 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1688 return ptr;
1692 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1694 if (new_ptr == NULL) {
1695 new_ptr = malloc(TC_HDR_SIZE+size);
1696 malloced = true;
1699 if (new_ptr) {
1700 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1702 _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
1705 else {
1706 new_ptr = realloc(tc, size + TC_HDR_SIZE);
1708 got_new_ptr:
1709 #endif
1710 if (unlikely(!new_ptr)) {
1711 tc->flags &= ~TALLOC_FLAG_FREE;
1712 return NULL;
1715 tc = (struct talloc_chunk *)new_ptr;
1716 tc->flags &= ~TALLOC_FLAG_FREE;
1717 if (malloced) {
1718 tc->flags &= ~TALLOC_FLAG_POOLMEM;
1720 if (tc->parent) {
1721 tc->parent->child = tc;
1723 if (tc->child) {
1724 tc->child->parent = tc;
1727 if (tc->prev) {
1728 tc->prev->next = tc;
1730 if (tc->next) {
1731 tc->next->prev = tc;
1734 if (!talloc_memlimit_update(tc->limit, tc->size, size)) {
1735 talloc_abort("cur_size memlimit counter not correct!");
1736 errno = EINVAL;
1737 return NULL;
1739 tc->size = size;
1740 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
1742 return TC_PTR_FROM_CHUNK(tc);
1746 a wrapper around talloc_steal() for situations where you are moving a pointer
1747 between two structures, and want the old pointer to be set to NULL
1749 _PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
1751 const void **pptr = discard_const_p(const void *,_pptr);
1752 void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
1753 (*pptr) = NULL;
1754 return ret;
1757 enum talloc_mem_count_type {
1758 TOTAL_MEM_SIZE,
1759 TOTAL_MEM_BLOCKS,
1760 TOTAL_MEM_LIMIT,
1763 static size_t _talloc_total_mem_internal(const void *ptr,
1764 enum talloc_mem_count_type type,
1765 struct talloc_memlimit *old_limit,
1766 struct talloc_memlimit *new_limit)
1768 size_t total = 0;
1769 struct talloc_chunk *c, *tc;
1771 if (ptr == NULL) {
1772 ptr = null_context;
1774 if (ptr == NULL) {
1775 return 0;
1778 tc = talloc_chunk_from_ptr(ptr);
1780 if (old_limit || new_limit) {
1781 if (tc->limit && tc->limit->upper == old_limit) {
1782 tc->limit->upper = new_limit;
1786 /* optimize in the memlimits case */
1787 if (type == TOTAL_MEM_LIMIT &&
1788 tc->limit != NULL &&
1789 tc->limit != old_limit &&
1790 tc->limit->parent == tc) {
1791 return tc->limit->cur_size;
1794 if (tc->flags & TALLOC_FLAG_LOOP) {
1795 return 0;
1798 tc->flags |= TALLOC_FLAG_LOOP;
1800 if (old_limit || new_limit) {
1801 if (old_limit == tc->limit) {
1802 tc->limit = new_limit;
1806 switch (type) {
1807 case TOTAL_MEM_SIZE:
1808 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1809 total = tc->size;
1811 break;
1812 case TOTAL_MEM_BLOCKS:
1813 total++;
1814 break;
1815 case TOTAL_MEM_LIMIT:
1816 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1818 * Don't count memory allocated from a pool
1819 * when calculating limits. Only count the
1820 * pool itself.
1822 if (!(tc->flags & TALLOC_FLAG_POOLMEM)) {
1823 total = tc->size + TC_HDR_SIZE;
1826 break;
1828 for (c = tc->child; c; c = c->next) {
1829 total += _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c), type,
1830 old_limit, new_limit);
1833 tc->flags &= ~TALLOC_FLAG_LOOP;
1835 return total;
1839 return the total size of a talloc pool (subtree)
1841 _PUBLIC_ size_t talloc_total_size(const void *ptr)
1843 return _talloc_total_mem_internal(ptr, TOTAL_MEM_SIZE, NULL, NULL);
1847 return the total number of blocks in a talloc pool (subtree)
1849 _PUBLIC_ size_t talloc_total_blocks(const void *ptr)
1851 return _talloc_total_mem_internal(ptr, TOTAL_MEM_BLOCKS, NULL, NULL);
1855 return the number of external references to a pointer
1857 _PUBLIC_ size_t talloc_reference_count(const void *ptr)
1859 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1860 struct talloc_reference_handle *h;
1861 size_t ret = 0;
1863 for (h=tc->refs;h;h=h->next) {
1864 ret++;
1866 return ret;
1870 report on memory usage by all children of a pointer, giving a full tree view
1872 _PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1873 void (*callback)(const void *ptr,
1874 int depth, int max_depth,
1875 int is_ref,
1876 void *private_data),
1877 void *private_data)
1879 struct talloc_chunk *c, *tc;
1881 if (ptr == NULL) {
1882 ptr = null_context;
1884 if (ptr == NULL) return;
1886 tc = talloc_chunk_from_ptr(ptr);
1888 if (tc->flags & TALLOC_FLAG_LOOP) {
1889 return;
1892 callback(ptr, depth, max_depth, 0, private_data);
1894 if (max_depth >= 0 && depth >= max_depth) {
1895 return;
1898 tc->flags |= TALLOC_FLAG_LOOP;
1899 for (c=tc->child;c;c=c->next) {
1900 if (c->name == TALLOC_MAGIC_REFERENCE) {
1901 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1902 callback(h->ptr, depth + 1, max_depth, 1, private_data);
1903 } else {
1904 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1907 tc->flags &= ~TALLOC_FLAG_LOOP;
1910 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1912 const char *name = talloc_get_name(ptr);
1913 struct talloc_chunk *tc;
1914 FILE *f = (FILE *)_f;
1916 if (is_ref) {
1917 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1918 return;
1921 tc = talloc_chunk_from_ptr(ptr);
1922 if (tc->limit && tc->limit->parent == tc) {
1923 fprintf(f, "%*s%-30s is a memlimit context"
1924 " (max_size = %lu bytes, cur_size = %lu bytes)\n",
1925 depth*4, "",
1926 name,
1927 (unsigned long)tc->limit->max_size,
1928 (unsigned long)tc->limit->cur_size);
1931 if (depth == 0) {
1932 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1933 (max_depth < 0 ? "full " :""), name,
1934 (unsigned long)talloc_total_size(ptr),
1935 (unsigned long)talloc_total_blocks(ptr));
1936 return;
1939 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1940 depth*4, "",
1941 name,
1942 (unsigned long)talloc_total_size(ptr),
1943 (unsigned long)talloc_total_blocks(ptr),
1944 (int)talloc_reference_count(ptr), ptr);
1946 #if 0
1947 fprintf(f, "content: ");
1948 if (talloc_total_size(ptr)) {
1949 int tot = talloc_total_size(ptr);
1950 int i;
1952 for (i = 0; i < tot; i++) {
1953 if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1954 fprintf(f, "%c", ((char *)ptr)[i]);
1955 } else {
1956 fprintf(f, "~%02x", ((char *)ptr)[i]);
1960 fprintf(f, "\n");
1961 #endif
1965 report on memory usage by all children of a pointer, giving a full tree view
1967 _PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1969 if (f) {
1970 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1971 fflush(f);
1976 report on memory usage by all children of a pointer, giving a full tree view
1978 _PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
1980 talloc_report_depth_file(ptr, 0, -1, f);
1984 report on memory usage by all children of a pointer
1986 _PUBLIC_ void talloc_report(const void *ptr, FILE *f)
1988 talloc_report_depth_file(ptr, 0, 1, f);
1992 report on any memory hanging off the null context
1994 static void talloc_report_null(void)
1996 if (talloc_total_size(null_context) != 0) {
1997 talloc_report(null_context, stderr);
2002 report on any memory hanging off the null context
2004 static void talloc_report_null_full(void)
2006 if (talloc_total_size(null_context) != 0) {
2007 talloc_report_full(null_context, stderr);
2012 enable tracking of the NULL context
2014 _PUBLIC_ void talloc_enable_null_tracking(void)
2016 if (null_context == NULL) {
2017 null_context = _talloc_named_const(NULL, 0, "null_context");
2018 if (autofree_context != NULL) {
2019 talloc_reparent(NULL, null_context, autofree_context);
2025 enable tracking of the NULL context, not moving the autofree context
2026 into the NULL context. This is needed for the talloc testsuite
2028 _PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
2030 if (null_context == NULL) {
2031 null_context = _talloc_named_const(NULL, 0, "null_context");
2036 disable tracking of the NULL context
2038 _PUBLIC_ void talloc_disable_null_tracking(void)
2040 if (null_context != NULL) {
2041 /* we have to move any children onto the real NULL
2042 context */
2043 struct talloc_chunk *tc, *tc2;
2044 tc = talloc_chunk_from_ptr(null_context);
2045 for (tc2 = tc->child; tc2; tc2=tc2->next) {
2046 if (tc2->parent == tc) tc2->parent = NULL;
2047 if (tc2->prev == tc) tc2->prev = NULL;
2049 for (tc2 = tc->next; tc2; tc2=tc2->next) {
2050 if (tc2->parent == tc) tc2->parent = NULL;
2051 if (tc2->prev == tc) tc2->prev = NULL;
2053 tc->child = NULL;
2054 tc->next = NULL;
2056 talloc_free(null_context);
2057 null_context = NULL;
2061 enable leak reporting on exit
2063 _PUBLIC_ void talloc_enable_leak_report(void)
2065 talloc_enable_null_tracking();
2066 atexit(talloc_report_null);
2070 enable full leak reporting on exit
2072 _PUBLIC_ void talloc_enable_leak_report_full(void)
2074 talloc_enable_null_tracking();
2075 atexit(talloc_report_null_full);
2079 talloc and zero memory.
2081 _PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
2083 void *p = _talloc_named_const(ctx, size, name);
2085 if (p) {
2086 memset(p, '\0', size);
2089 return p;
2093 memdup with a talloc.
2095 _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
2097 void *newp = _talloc_named_const(t, size, name);
2099 if (likely(newp)) {
2100 memcpy(newp, p, size);
2103 return newp;
2106 static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
2108 char *ret;
2110 ret = (char *)__talloc(t, len + 1);
2111 if (unlikely(!ret)) return NULL;
2113 memcpy(ret, p, len);
2114 ret[len] = 0;
2116 _talloc_set_name_const(ret, ret);
2117 return ret;
2121 strdup with a talloc
2123 _PUBLIC_ char *talloc_strdup(const void *t, const char *p)
2125 if (unlikely(!p)) return NULL;
2126 return __talloc_strlendup(t, p, strlen(p));
2130 strndup with a talloc
2132 _PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
2134 if (unlikely(!p)) return NULL;
2135 return __talloc_strlendup(t, p, strnlen(p, n));
2138 static inline char *__talloc_strlendup_append(char *s, size_t slen,
2139 const char *a, size_t alen)
2141 char *ret;
2143 ret = talloc_realloc(NULL, s, char, slen + alen + 1);
2144 if (unlikely(!ret)) return NULL;
2146 /* append the string and the trailing \0 */
2147 memcpy(&ret[slen], a, alen);
2148 ret[slen+alen] = 0;
2150 _talloc_set_name_const(ret, ret);
2151 return ret;
2155 * Appends at the end of the string.
2157 _PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
2159 if (unlikely(!s)) {
2160 return talloc_strdup(NULL, a);
2163 if (unlikely(!a)) {
2164 return s;
2167 return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
2171 * Appends at the end of the talloc'ed buffer,
2172 * not the end of the string.
2174 _PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
2176 size_t slen;
2178 if (unlikely(!s)) {
2179 return talloc_strdup(NULL, a);
2182 if (unlikely(!a)) {
2183 return s;
2186 slen = talloc_get_size(s);
2187 if (likely(slen > 0)) {
2188 slen--;
2191 return __talloc_strlendup_append(s, slen, a, strlen(a));
2195 * Appends at the end of the string.
2197 _PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
2199 if (unlikely(!s)) {
2200 return talloc_strndup(NULL, a, n);
2203 if (unlikely(!a)) {
2204 return s;
2207 return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
2211 * Appends at the end of the talloc'ed buffer,
2212 * not the end of the string.
2214 _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
2216 size_t slen;
2218 if (unlikely(!s)) {
2219 return talloc_strndup(NULL, a, n);
2222 if (unlikely(!a)) {
2223 return s;
2226 slen = talloc_get_size(s);
2227 if (likely(slen > 0)) {
2228 slen--;
2231 return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
2234 #ifndef HAVE_VA_COPY
2235 #ifdef HAVE___VA_COPY
2236 #define va_copy(dest, src) __va_copy(dest, src)
2237 #else
2238 #define va_copy(dest, src) (dest) = (src)
2239 #endif
2240 #endif
2242 _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
2244 int len;
2245 char *ret;
2246 va_list ap2;
2247 char c;
2249 /* this call looks strange, but it makes it work on older solaris boxes */
2250 va_copy(ap2, ap);
2251 len = vsnprintf(&c, 1, fmt, ap2);
2252 va_end(ap2);
2253 if (unlikely(len < 0)) {
2254 return NULL;
2257 ret = (char *)__talloc(t, len+1);
2258 if (unlikely(!ret)) return NULL;
2260 va_copy(ap2, ap);
2261 vsnprintf(ret, len+1, fmt, ap2);
2262 va_end(ap2);
2264 _talloc_set_name_const(ret, ret);
2265 return ret;
2270 Perform string formatting, and return a pointer to newly allocated
2271 memory holding the result, inside a memory pool.
2273 _PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
2275 va_list ap;
2276 char *ret;
2278 va_start(ap, fmt);
2279 ret = talloc_vasprintf(t, fmt, ap);
2280 va_end(ap);
2281 return ret;
2284 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2285 const char *fmt, va_list ap)
2286 PRINTF_ATTRIBUTE(3,0);
2288 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2289 const char *fmt, va_list ap)
2291 ssize_t alen;
2292 va_list ap2;
2293 char c;
2295 va_copy(ap2, ap);
2296 alen = vsnprintf(&c, 1, fmt, ap2);
2297 va_end(ap2);
2299 if (alen <= 0) {
2300 /* Either the vsnprintf failed or the format resulted in
2301 * no characters being formatted. In the former case, we
2302 * ought to return NULL, in the latter we ought to return
2303 * the original string. Most current callers of this
2304 * function expect it to never return NULL.
2306 return s;
2309 s = talloc_realloc(NULL, s, char, slen + alen + 1);
2310 if (!s) return NULL;
2312 va_copy(ap2, ap);
2313 vsnprintf(s + slen, alen + 1, fmt, ap2);
2314 va_end(ap2);
2316 _talloc_set_name_const(s, s);
2317 return s;
2321 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2322 * and return @p s, which may have moved. Good for gradually
2323 * accumulating output into a string buffer. Appends at the end
2324 * of the string.
2326 _PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
2328 if (unlikely(!s)) {
2329 return talloc_vasprintf(NULL, fmt, ap);
2332 return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
2336 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2337 * and return @p s, which may have moved. Always appends at the
2338 * end of the talloc'ed buffer, not the end of the string.
2340 _PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
2342 size_t slen;
2344 if (unlikely(!s)) {
2345 return talloc_vasprintf(NULL, fmt, ap);
2348 slen = talloc_get_size(s);
2349 if (likely(slen > 0)) {
2350 slen--;
2353 return __talloc_vaslenprintf_append(s, slen, fmt, ap);
2357 Realloc @p s to append the formatted result of @p fmt and return @p
2358 s, which may have moved. Good for gradually accumulating output
2359 into a string buffer.
2361 _PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
2363 va_list ap;
2365 va_start(ap, fmt);
2366 s = talloc_vasprintf_append(s, fmt, ap);
2367 va_end(ap);
2368 return s;
2372 Realloc @p s to append the formatted result of @p fmt and return @p
2373 s, which may have moved. Good for gradually accumulating output
2374 into a buffer.
2376 _PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
2378 va_list ap;
2380 va_start(ap, fmt);
2381 s = talloc_vasprintf_append_buffer(s, fmt, ap);
2382 va_end(ap);
2383 return s;
2387 alloc an array, checking for integer overflow in the array size
2389 _PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2391 if (count >= MAX_TALLOC_SIZE/el_size) {
2392 return NULL;
2394 return _talloc_named_const(ctx, el_size * count, name);
2398 alloc an zero array, checking for integer overflow in the array size
2400 _PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2402 if (count >= MAX_TALLOC_SIZE/el_size) {
2403 return NULL;
2405 return _talloc_zero(ctx, el_size * count, name);
2409 realloc an array, checking for integer overflow in the array size
2411 _PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
2413 if (count >= MAX_TALLOC_SIZE/el_size) {
2414 return NULL;
2416 return _talloc_realloc(ctx, ptr, el_size * count, name);
2420 a function version of talloc_realloc(), so it can be passed as a function pointer
2421 to libraries that want a realloc function (a realloc function encapsulates
2422 all the basic capabilities of an allocation library, which is why this is useful)
2424 _PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
2426 return _talloc_realloc(context, ptr, size, NULL);
2430 static int talloc_autofree_destructor(void *ptr)
2432 autofree_context = NULL;
2433 return 0;
2436 static void talloc_autofree(void)
2438 talloc_free(autofree_context);
2442 return a context which will be auto-freed on exit
2443 this is useful for reducing the noise in leak reports
2445 _PUBLIC_ void *talloc_autofree_context(void)
2447 if (autofree_context == NULL) {
2448 autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
2449 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
2450 atexit(talloc_autofree);
2452 return autofree_context;
2455 _PUBLIC_ size_t talloc_get_size(const void *context)
2457 struct talloc_chunk *tc;
2459 if (context == NULL) {
2460 context = null_context;
2462 if (context == NULL) {
2463 return 0;
2466 tc = talloc_chunk_from_ptr(context);
2468 return tc->size;
2472 find a parent of this context that has the given name, if any
2474 _PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
2476 struct talloc_chunk *tc;
2478 if (context == NULL) {
2479 return NULL;
2482 tc = talloc_chunk_from_ptr(context);
2483 while (tc) {
2484 if (tc->name && strcmp(tc->name, name) == 0) {
2485 return TC_PTR_FROM_CHUNK(tc);
2487 while (tc && tc->prev) tc = tc->prev;
2488 if (tc) {
2489 tc = tc->parent;
2492 return NULL;
2496 show the parentage of a context
2498 _PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
2500 struct talloc_chunk *tc;
2502 if (context == NULL) {
2503 fprintf(file, "talloc no parents for NULL\n");
2504 return;
2507 tc = talloc_chunk_from_ptr(context);
2508 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
2509 while (tc) {
2510 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
2511 while (tc && tc->prev) tc = tc->prev;
2512 if (tc) {
2513 tc = tc->parent;
2516 fflush(file);
2520 return 1 if ptr is a parent of context
2522 static int _talloc_is_parent(const void *context, const void *ptr, int depth)
2524 struct talloc_chunk *tc;
2526 if (context == NULL) {
2527 return 0;
2530 tc = talloc_chunk_from_ptr(context);
2531 while (tc && depth > 0) {
2532 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
2533 while (tc && tc->prev) tc = tc->prev;
2534 if (tc) {
2535 tc = tc->parent;
2536 depth--;
2539 return 0;
2543 return 1 if ptr is a parent of context
2545 _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
2547 return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
2551 return the total size of memory used by this context and all children
2553 static size_t _talloc_total_limit_size(const void *ptr,
2554 struct talloc_memlimit *old_limit,
2555 struct talloc_memlimit *new_limit)
2557 return _talloc_total_mem_internal(ptr, TOTAL_MEM_LIMIT,
2558 old_limit, new_limit);
2561 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size)
2563 struct talloc_memlimit *l;
2565 for (l = limit; l != NULL; l = l->upper) {
2566 if (l->max_size != 0 &&
2567 ((l->max_size <= l->cur_size) ||
2568 (l->max_size - l->cur_size < size))) {
2569 return false;
2573 return true;
2577 Update memory limits when freeing a talloc_chunk.
2579 static void talloc_memlimit_update_on_free(struct talloc_chunk *tc)
2581 if (!tc->limit) {
2582 return;
2586 * Pool entries don't count. Only the pools
2587 * themselves are counted as part of the memory
2588 * limits.
2590 if (tc->flags & TALLOC_FLAG_POOLMEM) {
2591 return;
2595 * If we are part of a memory limited context hierarchy
2596 * we need to subtract the memory used from the counters
2599 talloc_memlimit_shrink(tc->limit, tc->size+TC_HDR_SIZE);
2601 if (tc->limit->parent == tc) {
2602 free(tc->limit);
2605 tc->limit = NULL;
2609 Increase memory limit accounting after a malloc/realloc.
2611 static void talloc_memlimit_grow(struct talloc_memlimit *limit,
2612 size_t size)
2614 struct talloc_memlimit *l;
2616 for (l = limit; l != NULL; l = l->upper) {
2617 size_t new_cur_size = l->cur_size + size;
2618 if (new_cur_size < l->cur_size) {
2619 talloc_abort("logic error in talloc_memlimit_grow\n");
2620 return;
2622 l->cur_size = new_cur_size;
2627 Decrease memory limit accounting after a free/realloc.
2629 static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
2630 size_t size)
2632 struct talloc_memlimit *l;
2634 for (l = limit; l != NULL; l = l->upper) {
2635 if (l->cur_size < size) {
2636 talloc_abort("logic error in talloc_memlimit_shrink\n");
2637 return;
2639 l->cur_size = l->cur_size - size;
2643 static bool talloc_memlimit_update(struct talloc_memlimit *limit,
2644 size_t old_size, size_t new_size)
2646 struct talloc_memlimit *l;
2647 ssize_t d;
2649 if (old_size == 0) {
2650 d = new_size + TC_HDR_SIZE;
2651 } else {
2652 d = new_size - old_size;
2654 for (l = limit; l != NULL; l = l->upper) {
2655 ssize_t new_cur_size = l->cur_size + d;
2656 if (new_cur_size < 0) {
2657 return false;
2659 l->cur_size = new_cur_size;
2662 return true;
2665 _PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size)
2667 struct talloc_chunk *tc = talloc_chunk_from_ptr(ctx);
2668 struct talloc_memlimit *orig_limit;
2669 struct talloc_memlimit *limit = NULL;
2671 if (tc->limit && tc->limit->parent == tc) {
2672 tc->limit->max_size = max_size;
2673 return 0;
2675 orig_limit = tc->limit;
2677 limit = malloc(sizeof(struct talloc_memlimit));
2678 if (limit == NULL) {
2679 return 1;
2681 limit->parent = tc;
2682 limit->max_size = max_size;
2683 limit->cur_size = _talloc_total_limit_size(ctx, tc->limit, limit);
2685 if (orig_limit) {
2686 limit->upper = orig_limit;
2687 } else {
2688 limit->upper = NULL;
2691 return 0;