Remove talloc_memlimit_update(). No longer used.
[Samba/wip.git] / lib / talloc / talloc.c
blob677ec0f13fda4884f7da3340cf3b74d10603ad6a
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 void talloc_memlimit_grow(struct talloc_memlimit *limit,
240 size_t size);
241 static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
242 size_t size);
243 static void talloc_memlimit_update_on_free(struct talloc_chunk *tc);
245 typedef int (*talloc_destructor_t)(void *);
247 struct talloc_chunk {
248 struct talloc_chunk *next, *prev;
249 struct talloc_chunk *parent, *child;
250 struct talloc_reference_handle *refs;
251 talloc_destructor_t destructor;
252 const char *name;
253 size_t size;
254 unsigned flags;
257 * limit semantics:
258 * if 'limit' is set it means all *new* children of the context will
259 * be limited to a total aggregate size ox max_size for memory
260 * allocations.
261 * cur_size is used to keep track of the current use
263 struct talloc_memlimit *limit;
266 * "pool" has dual use:
268 * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
269 * marks the end of the currently allocated area.
271 * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
272 * is a pointer to the struct talloc_chunk of the pool that it was
273 * allocated from. This way children can quickly find the pool to chew
274 * from.
276 void *pool;
279 /* 16 byte alignment seems to keep everyone happy */
280 #define TC_ALIGN16(s) (((s)+15)&~15)
281 #define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
282 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
284 _PUBLIC_ int talloc_version_major(void)
286 return TALLOC_VERSION_MAJOR;
289 _PUBLIC_ int talloc_version_minor(void)
291 return TALLOC_VERSION_MINOR;
294 static void (*talloc_log_fn)(const char *message);
296 _PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
298 talloc_log_fn = log_fn;
301 static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
302 static void talloc_log(const char *fmt, ...)
304 va_list ap;
305 char *message;
307 if (!talloc_log_fn) {
308 return;
311 va_start(ap, fmt);
312 message = talloc_vasprintf(NULL, fmt, ap);
313 va_end(ap);
315 talloc_log_fn(message);
316 talloc_free(message);
319 static void talloc_log_stderr(const char *message)
321 fprintf(stderr, "%s", message);
324 _PUBLIC_ void talloc_set_log_stderr(void)
326 talloc_set_log_fn(talloc_log_stderr);
329 static void (*talloc_abort_fn)(const char *reason);
331 _PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
333 talloc_abort_fn = abort_fn;
336 static void talloc_abort(const char *reason)
338 talloc_log("%s\n", reason);
340 if (!talloc_abort_fn) {
341 TALLOC_ABORT(reason);
344 talloc_abort_fn(reason);
347 static void talloc_abort_magic(unsigned magic)
349 unsigned striped = magic - TALLOC_MAGIC_BASE;
350 unsigned major = (striped & 0xFFFFF000) >> 12;
351 unsigned minor = (striped & 0x00000FF0) >> 4;
352 talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
353 magic, major, minor,
354 TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR);
355 talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
358 static void talloc_abort_access_after_free(void)
360 talloc_abort("Bad talloc magic value - access after free");
363 static void talloc_abort_unknown_value(void)
365 talloc_abort("Bad talloc magic value - unknown value");
368 /* panic if we get a bad magic value */
369 static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
371 const char *pp = (const char *)ptr;
372 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
373 if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
374 if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) {
375 talloc_abort_magic(tc->flags & (~0xF));
376 return NULL;
379 if (tc->flags & TALLOC_FLAG_FREE) {
380 talloc_log("talloc: access after free error - first free may be at %s\n", tc->name);
381 talloc_abort_access_after_free();
382 return NULL;
383 } else {
384 talloc_abort_unknown_value();
385 return NULL;
388 return tc;
391 /* hook into the front of the list */
392 #define _TLIST_ADD(list, p) \
393 do { \
394 if (!(list)) { \
395 (list) = (p); \
396 (p)->next = (p)->prev = NULL; \
397 } else { \
398 (list)->prev = (p); \
399 (p)->next = (list); \
400 (p)->prev = NULL; \
401 (list) = (p); \
403 } while (0)
405 /* remove an element from a list - element doesn't have to be in list. */
406 #define _TLIST_REMOVE(list, p) \
407 do { \
408 if ((p) == (list)) { \
409 (list) = (p)->next; \
410 if (list) (list)->prev = NULL; \
411 } else { \
412 if ((p)->prev) (p)->prev->next = (p)->next; \
413 if ((p)->next) (p)->next->prev = (p)->prev; \
415 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
416 } while (0)
420 return the parent chunk of a pointer
422 static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
424 struct talloc_chunk *tc;
426 if (unlikely(ptr == NULL)) {
427 return NULL;
430 tc = talloc_chunk_from_ptr(ptr);
431 while (tc->prev) tc=tc->prev;
433 return tc->parent;
436 _PUBLIC_ void *talloc_parent(const void *ptr)
438 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
439 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
443 find parents name
445 _PUBLIC_ const char *talloc_parent_name(const void *ptr)
447 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
448 return tc? tc->name : NULL;
452 A pool carries an in-pool object count count in the first 16 bytes.
453 bytes. This is done to support talloc_steal() to a parent outside of the
454 pool. The count includes the pool itself, so a talloc_free() on a pool will
455 only destroy the pool if the count has dropped to zero. A talloc_free() of a
456 pool member will reduce the count, and eventually also call free(3) on the
457 pool memory.
459 The object count is not put into "struct talloc_chunk" because it is only
460 relevant for talloc pools and the alignment to 16 bytes would increase the
461 memory footprint of each talloc chunk by those 16 bytes.
464 union talloc_pool_chunk {
465 /* This lets object_count nestle into 16-byte padding of talloc_chunk,
466 * on 32-bit platforms. */
467 struct tc_pool_hdr {
468 struct talloc_chunk c;
469 unsigned int object_count;
470 } hdr;
471 /* This makes it always 16 byte aligned. */
472 char pad[TC_ALIGN16(sizeof(struct tc_pool_hdr))];
475 static void *tc_pool_end(union talloc_pool_chunk *pool_tc)
477 return (char *)pool_tc + TC_HDR_SIZE + pool_tc->hdr.c.size;
480 static size_t tc_pool_space_left(union talloc_pool_chunk *pool_tc)
482 return (char *)tc_pool_end(pool_tc) - (char *)pool_tc->hdr.c.pool;
485 static void *tc_pool_first_chunk(union talloc_pool_chunk *pool_tc)
487 return pool_tc + 1;
490 /* If tc is inside a pool, this gives the next neighbour. */
491 static void *tc_next_chunk(struct talloc_chunk *tc)
493 return (char *)tc + TC_ALIGN16(TC_HDR_SIZE + tc->size);
496 /* Mark the whole remaining pool as not accessable */
497 static void tc_invalidate_pool(union talloc_pool_chunk *pool_tc)
499 size_t flen = tc_pool_space_left(pool_tc);
501 if (unlikely(talloc_fill.enabled)) {
502 memset(pool_tc->hdr.c.pool, talloc_fill.fill_value, flen);
505 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
506 VALGRIND_MAKE_MEM_NOACCESS(pool_tc->hdr.c.pool, flen);
507 #endif
511 Allocate from a pool
514 static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
515 size_t size)
517 union talloc_pool_chunk *pool_ctx = NULL;
518 size_t space_left;
519 struct talloc_chunk *result;
520 size_t chunk_size;
522 if (parent == NULL) {
523 return NULL;
526 if (parent->flags & TALLOC_FLAG_POOL) {
527 pool_ctx = (union talloc_pool_chunk *)parent;
529 else if (parent->flags & TALLOC_FLAG_POOLMEM) {
530 pool_ctx = (union talloc_pool_chunk *)parent->pool;
533 if (pool_ctx == NULL) {
534 return NULL;
537 space_left = tc_pool_space_left(pool_ctx);
540 * Align size to 16 bytes
542 chunk_size = TC_ALIGN16(size);
544 if (space_left < chunk_size) {
545 return NULL;
548 result = (struct talloc_chunk *)pool_ctx->hdr.c.pool;
550 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
551 VALGRIND_MAKE_MEM_UNDEFINED(result, size);
552 #endif
554 pool_ctx->hdr.c.pool = (void *)((char *)result + chunk_size);
556 result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
557 result->pool = pool_ctx;
559 pool_ctx->hdr.object_count++;
561 return result;
565 Allocate a bit of memory as a child of an existing pointer
567 static inline void *__talloc(const void *context, size_t size)
569 struct talloc_chunk *tc = NULL;
570 struct talloc_memlimit *limit = NULL;
572 if (unlikely(context == NULL)) {
573 context = null_context;
576 if (unlikely(size >= MAX_TALLOC_SIZE)) {
577 return NULL;
580 if (context != NULL) {
581 struct talloc_chunk *ptc = talloc_chunk_from_ptr(context);
583 if (ptc->limit != NULL) {
584 limit = ptc->limit;
587 tc = talloc_alloc_pool(ptc, TC_HDR_SIZE+size);
590 if (tc == NULL) {
592 * Only do the memlimit check/update on actual allocation.
594 if (!talloc_memlimit_check(limit, TC_HDR_SIZE + size)) {
595 errno = ENOMEM;
596 return NULL;
599 tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
600 if (unlikely(tc == NULL)) return NULL;
601 tc->flags = TALLOC_MAGIC;
602 tc->pool = NULL;
604 talloc_memlimit_grow(limit, TC_HDR_SIZE + size);
607 tc->limit = limit;
608 tc->size = size;
609 tc->destructor = NULL;
610 tc->child = NULL;
611 tc->name = NULL;
612 tc->refs = NULL;
614 if (likely(context)) {
615 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
617 if (parent->child) {
618 parent->child->parent = NULL;
619 tc->next = parent->child;
620 tc->next->prev = tc;
621 } else {
622 tc->next = NULL;
624 tc->parent = parent;
625 tc->prev = NULL;
626 parent->child = tc;
627 } else {
628 tc->next = tc->prev = tc->parent = NULL;
631 return TC_PTR_FROM_CHUNK(tc);
635 * Create a talloc pool
638 _PUBLIC_ void *talloc_pool(const void *context, size_t size)
640 union talloc_pool_chunk *pool_tc;
641 void *result = __talloc(context, sizeof(*pool_tc) - TC_HDR_SIZE + size);
643 if (unlikely(result == NULL)) {
644 return NULL;
647 pool_tc = (union talloc_pool_chunk *)talloc_chunk_from_ptr(result);
648 if (unlikely(pool_tc->hdr.c.flags & TALLOC_FLAG_POOLMEM)) {
649 /* We don't handle this correctly, so fail. */
650 talloc_log("talloc: cannot allocate pool off another pool %s\n",
651 talloc_get_name(context));
652 talloc_free(result);
653 return NULL;
655 pool_tc->hdr.c.flags |= TALLOC_FLAG_POOL;
656 pool_tc->hdr.c.pool = tc_pool_first_chunk(pool_tc);
658 pool_tc->hdr.object_count = 1;
660 tc_invalidate_pool(pool_tc);
662 return result;
666 setup a destructor to be called on free of a pointer
667 the destructor should return 0 on success, or -1 on failure.
668 if the destructor fails then the free is failed, and the memory can
669 be continued to be used
671 _PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
673 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
674 tc->destructor = destructor;
678 increase the reference count on a piece of memory.
680 _PUBLIC_ int talloc_increase_ref_count(const void *ptr)
682 if (unlikely(!talloc_reference(null_context, ptr))) {
683 return -1;
685 return 0;
689 helper for talloc_reference()
691 this is referenced by a function pointer and should not be inline
693 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
695 struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
696 _TLIST_REMOVE(ptr_tc->refs, handle);
697 return 0;
701 more efficient way to add a name to a pointer - the name must point to a
702 true string constant
704 static inline void _talloc_set_name_const(const void *ptr, const char *name)
706 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
707 tc->name = name;
711 internal talloc_named_const()
713 static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
715 void *ptr;
717 ptr = __talloc(context, size);
718 if (unlikely(ptr == NULL)) {
719 return NULL;
722 _talloc_set_name_const(ptr, name);
724 return ptr;
728 make a secondary reference to a pointer, hanging off the given context.
729 the pointer remains valid until both the original caller and this given
730 context are freed.
732 the major use for this is when two different structures need to reference the
733 same underlying data, and you want to be able to free the two instances separately,
734 and in either order
736 _PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
738 struct talloc_chunk *tc;
739 struct talloc_reference_handle *handle;
740 if (unlikely(ptr == NULL)) return NULL;
742 tc = talloc_chunk_from_ptr(ptr);
743 handle = (struct talloc_reference_handle *)_talloc_named_const(context,
744 sizeof(struct talloc_reference_handle),
745 TALLOC_MAGIC_REFERENCE);
746 if (unlikely(handle == NULL)) return NULL;
748 /* note that we hang the destructor off the handle, not the
749 main context as that allows the caller to still setup their
750 own destructor on the context if they want to */
751 talloc_set_destructor(handle, talloc_reference_destructor);
752 handle->ptr = discard_const_p(void, ptr);
753 handle->location = location;
754 _TLIST_ADD(tc->refs, handle);
755 return handle->ptr;
758 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
760 static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
761 const char *location)
763 union talloc_pool_chunk *pool;
764 void *next_tc;
766 pool = (union talloc_pool_chunk *)tc->pool;
767 next_tc = tc_next_chunk(tc);
769 tc->flags |= TALLOC_FLAG_FREE;
771 /* we mark the freed memory with where we called the free
772 * from. This means on a double free error we can report where
773 * the first free came from
775 tc->name = location;
777 TC_INVALIDATE_FULL_CHUNK(tc);
779 if (unlikely(pool->hdr.object_count == 0)) {
780 talloc_abort("Pool object count zero!");
781 return;
784 pool->hdr.object_count--;
786 if (unlikely(pool->hdr.object_count == 1
787 && !(pool->hdr.c.flags & TALLOC_FLAG_FREE))) {
789 * if there is just one object left in the pool
790 * and pool->flags does not have TALLOC_FLAG_FREE,
791 * it means this is the pool itself and
792 * the rest is available for new objects
793 * again.
795 pool->hdr.c.pool = tc_pool_first_chunk(pool);
796 tc_invalidate_pool(pool);
797 return;
800 if (unlikely(pool->hdr.object_count == 0)) {
802 * we mark the freed memory with where we called the free
803 * from. This means on a double free error we can report where
804 * the first free came from
806 pool->hdr.c.name = location;
808 talloc_memlimit_update_on_free(&pool->hdr.c);
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;
910 /* we mark the freed memory with where we called the free
911 * from. This means on a double free error we can report where
912 * the first free came from
914 tc->name = location;
916 if (tc->flags & TALLOC_FLAG_POOL) {
917 union talloc_pool_chunk *pool = (union talloc_pool_chunk *)tc;
919 if (unlikely(pool->hdr.object_count == 0)) {
920 talloc_abort("Pool object count zero!");
921 return 0;
924 pool->hdr.object_count--;
926 if (likely(pool->hdr.object_count != 0)) {
927 return 0;
930 talloc_memlimit_update_on_free(tc);
932 TC_INVALIDATE_FULL_CHUNK(tc);
933 free(tc);
934 return 0;
937 if (tc->flags & TALLOC_FLAG_POOLMEM) {
938 _talloc_free_poolmem(tc, location);
939 return 0;
942 talloc_memlimit_update_on_free(tc);
944 TC_INVALIDATE_FULL_CHUNK(tc);
945 free(tc);
946 return 0;
949 static size_t _talloc_total_limit_size(const void *ptr,
950 struct talloc_memlimit *old_limit,
951 struct talloc_memlimit *new_limit);
954 move a lump of memory from one talloc context to another return the
955 ptr on success, or NULL if it could not be transferred.
956 passing NULL as ptr will always return NULL with no side effects.
958 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr)
960 struct talloc_chunk *tc, *new_tc;
961 size_t ctx_size = 0;
963 if (unlikely(!ptr)) {
964 return NULL;
967 if (unlikely(new_ctx == NULL)) {
968 new_ctx = null_context;
971 tc = talloc_chunk_from_ptr(ptr);
973 if (tc->limit != NULL) {
975 ctx_size = _talloc_total_limit_size(ptr, NULL, NULL);
977 /* Decrement the memory limit from the source .. */
978 talloc_memlimit_shrink(tc->limit->upper, ctx_size);
980 if (tc->limit->parent == tc) {
981 tc->limit->upper = NULL;
982 } else {
983 tc->limit = NULL;
987 if (unlikely(new_ctx == NULL)) {
988 if (tc->parent) {
989 _TLIST_REMOVE(tc->parent->child, tc);
990 if (tc->parent->child) {
991 tc->parent->child->parent = tc->parent;
993 } else {
994 if (tc->prev) tc->prev->next = tc->next;
995 if (tc->next) tc->next->prev = tc->prev;
998 tc->parent = tc->next = tc->prev = NULL;
999 return discard_const_p(void, ptr);
1002 new_tc = talloc_chunk_from_ptr(new_ctx);
1004 if (unlikely(tc == new_tc || tc->parent == new_tc)) {
1005 return discard_const_p(void, ptr);
1008 if (tc->parent) {
1009 _TLIST_REMOVE(tc->parent->child, tc);
1010 if (tc->parent->child) {
1011 tc->parent->child->parent = tc->parent;
1013 } else {
1014 if (tc->prev) tc->prev->next = tc->next;
1015 if (tc->next) tc->next->prev = tc->prev;
1016 tc->prev = tc->next = NULL;
1019 tc->parent = new_tc;
1020 if (new_tc->child) new_tc->child->parent = NULL;
1021 _TLIST_ADD(new_tc->child, tc);
1023 if (tc->limit || new_tc->limit) {
1024 ctx_size = _talloc_total_limit_size(ptr, tc->limit,
1025 new_tc->limit);
1026 /* .. and increment it in the destination. */
1027 if (new_tc->limit) {
1028 talloc_memlimit_grow(new_tc->limit, ctx_size);
1032 return discard_const_p(void, ptr);
1036 move a lump of memory from one talloc context to another return the
1037 ptr on success, or NULL if it could not be transferred.
1038 passing NULL as ptr will always return NULL with no side effects.
1040 _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
1042 struct talloc_chunk *tc;
1044 if (unlikely(ptr == NULL)) {
1045 return NULL;
1048 tc = talloc_chunk_from_ptr(ptr);
1050 if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
1051 struct talloc_reference_handle *h;
1053 talloc_log("WARNING: talloc_steal with references at %s\n",
1054 location);
1056 for (h=tc->refs; h; h=h->next) {
1057 talloc_log("\treference at %s\n",
1058 h->location);
1062 #if 0
1063 /* this test is probably too expensive to have on in the
1064 normal build, but it useful for debugging */
1065 if (talloc_is_parent(new_ctx, ptr)) {
1066 talloc_log("WARNING: stealing into talloc child at %s\n", location);
1068 #endif
1070 return _talloc_steal_internal(new_ctx, ptr);
1074 this is like a talloc_steal(), but you must supply the old
1075 parent. This resolves the ambiguity in a talloc_steal() which is
1076 called on a context that has more than one parent (via references)
1078 The old parent can be either a reference or a parent
1080 _PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
1082 struct talloc_chunk *tc;
1083 struct talloc_reference_handle *h;
1085 if (unlikely(ptr == NULL)) {
1086 return NULL;
1089 if (old_parent == talloc_parent(ptr)) {
1090 return _talloc_steal_internal(new_parent, ptr);
1093 tc = talloc_chunk_from_ptr(ptr);
1094 for (h=tc->refs;h;h=h->next) {
1095 if (talloc_parent(h) == old_parent) {
1096 if (_talloc_steal_internal(new_parent, h) != h) {
1097 return NULL;
1099 return discard_const_p(void, ptr);
1103 /* it wasn't a parent */
1104 return NULL;
1108 remove a secondary reference to a pointer. This undo's what
1109 talloc_reference() has done. The context and pointer arguments
1110 must match those given to a talloc_reference()
1112 static inline int talloc_unreference(const void *context, const void *ptr)
1114 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1115 struct talloc_reference_handle *h;
1117 if (unlikely(context == NULL)) {
1118 context = null_context;
1121 for (h=tc->refs;h;h=h->next) {
1122 struct talloc_chunk *p = talloc_parent_chunk(h);
1123 if (p == NULL) {
1124 if (context == NULL) break;
1125 } else if (TC_PTR_FROM_CHUNK(p) == context) {
1126 break;
1129 if (h == NULL) {
1130 return -1;
1133 return _talloc_free_internal(h, __location__);
1137 remove a specific parent context from a pointer. This is a more
1138 controlled variant of talloc_free()
1140 _PUBLIC_ int talloc_unlink(const void *context, void *ptr)
1142 struct talloc_chunk *tc_p, *new_p, *tc_c;
1143 void *new_parent;
1145 if (ptr == NULL) {
1146 return -1;
1149 if (context == NULL) {
1150 context = null_context;
1153 if (talloc_unreference(context, ptr) == 0) {
1154 return 0;
1157 if (context != NULL) {
1158 tc_c = talloc_chunk_from_ptr(context);
1159 } else {
1160 tc_c = NULL;
1162 if (tc_c != talloc_parent_chunk(ptr)) {
1163 return -1;
1166 tc_p = talloc_chunk_from_ptr(ptr);
1168 if (tc_p->refs == NULL) {
1169 return _talloc_free_internal(ptr, __location__);
1172 new_p = talloc_parent_chunk(tc_p->refs);
1173 if (new_p) {
1174 new_parent = TC_PTR_FROM_CHUNK(new_p);
1175 } else {
1176 new_parent = NULL;
1179 if (talloc_unreference(new_parent, ptr) != 0) {
1180 return -1;
1183 _talloc_steal_internal(new_parent, ptr);
1185 return 0;
1189 add a name to an existing pointer - va_list version
1191 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1193 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
1195 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1196 tc->name = talloc_vasprintf(ptr, fmt, ap);
1197 if (likely(tc->name)) {
1198 _talloc_set_name_const(tc->name, ".name");
1200 return tc->name;
1204 add a name to an existing pointer
1206 _PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
1208 const char *name;
1209 va_list ap;
1210 va_start(ap, fmt);
1211 name = talloc_set_name_v(ptr, fmt, ap);
1212 va_end(ap);
1213 return name;
1218 create a named talloc pointer. Any talloc pointer can be named, and
1219 talloc_named() operates just like talloc() except that it allows you
1220 to name the pointer.
1222 _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
1224 va_list ap;
1225 void *ptr;
1226 const char *name;
1228 ptr = __talloc(context, size);
1229 if (unlikely(ptr == NULL)) return NULL;
1231 va_start(ap, fmt);
1232 name = talloc_set_name_v(ptr, fmt, ap);
1233 va_end(ap);
1235 if (unlikely(name == NULL)) {
1236 _talloc_free_internal(ptr, __location__);
1237 return NULL;
1240 return ptr;
1244 return the name of a talloc ptr, or "UNNAMED"
1246 _PUBLIC_ const char *talloc_get_name(const void *ptr)
1248 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1249 if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
1250 return ".reference";
1252 if (likely(tc->name)) {
1253 return tc->name;
1255 return "UNNAMED";
1260 check if a pointer has the given name. If it does, return the pointer,
1261 otherwise return NULL
1263 _PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
1265 const char *pname;
1266 if (unlikely(ptr == NULL)) return NULL;
1267 pname = talloc_get_name(ptr);
1268 if (likely(pname == name || strcmp(pname, name) == 0)) {
1269 return discard_const_p(void, ptr);
1271 return NULL;
1274 static void talloc_abort_type_mismatch(const char *location,
1275 const char *name,
1276 const char *expected)
1278 const char *reason;
1280 reason = talloc_asprintf(NULL,
1281 "%s: Type mismatch: name[%s] expected[%s]",
1282 location,
1283 name?name:"NULL",
1284 expected);
1285 if (!reason) {
1286 reason = "Type mismatch";
1289 talloc_abort(reason);
1292 _PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
1294 const char *pname;
1296 if (unlikely(ptr == NULL)) {
1297 talloc_abort_type_mismatch(location, NULL, name);
1298 return NULL;
1301 pname = talloc_get_name(ptr);
1302 if (likely(pname == name || strcmp(pname, name) == 0)) {
1303 return discard_const_p(void, ptr);
1306 talloc_abort_type_mismatch(location, pname, name);
1307 return NULL;
1311 this is for compatibility with older versions of talloc
1313 _PUBLIC_ void *talloc_init(const char *fmt, ...)
1315 va_list ap;
1316 void *ptr;
1317 const char *name;
1319 ptr = __talloc(NULL, 0);
1320 if (unlikely(ptr == NULL)) return NULL;
1322 va_start(ap, fmt);
1323 name = talloc_set_name_v(ptr, fmt, ap);
1324 va_end(ap);
1326 if (unlikely(name == NULL)) {
1327 _talloc_free_internal(ptr, __location__);
1328 return NULL;
1331 return ptr;
1334 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
1335 void *ptr,
1336 const char *location)
1338 while (tc->child) {
1339 /* we need to work out who will own an abandoned child
1340 if it cannot be freed. In priority order, the first
1341 choice is owner of any remaining reference to this
1342 pointer, the second choice is our parent, and the
1343 final choice is the null context. */
1344 void *child = TC_PTR_FROM_CHUNK(tc->child);
1345 const void *new_parent = null_context;
1346 if (unlikely(tc->child->refs)) {
1347 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1348 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1350 if (unlikely(_talloc_free_internal(child, location) == -1)) {
1351 if (new_parent == null_context) {
1352 struct talloc_chunk *p = talloc_parent_chunk(ptr);
1353 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1355 _talloc_steal_internal(new_parent, child);
1361 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1362 should probably not be used in new code. It's in here to keep the talloc
1363 code consistent across Samba 3 and 4.
1365 _PUBLIC_ void talloc_free_children(void *ptr)
1367 struct talloc_chunk *tc_name = NULL;
1368 struct talloc_chunk *tc;
1370 if (unlikely(ptr == NULL)) {
1371 return;
1374 tc = talloc_chunk_from_ptr(ptr);
1376 /* we do not want to free the context name if it is a child .. */
1377 if (likely(tc->child)) {
1378 for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
1379 if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
1381 if (tc_name) {
1382 _TLIST_REMOVE(tc->child, tc_name);
1383 if (tc->child) {
1384 tc->child->parent = tc;
1389 _talloc_free_children_internal(tc, ptr, __location__);
1391 /* .. so we put it back after all other children have been freed */
1392 if (tc_name) {
1393 if (tc->child) {
1394 tc->child->parent = NULL;
1396 tc_name->parent = tc;
1397 _TLIST_ADD(tc->child, tc_name);
1402 Allocate a bit of memory as a child of an existing pointer
1404 _PUBLIC_ void *_talloc(const void *context, size_t size)
1406 return __talloc(context, size);
1410 externally callable talloc_set_name_const()
1412 _PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
1414 _talloc_set_name_const(ptr, name);
1418 create a named talloc pointer. Any talloc pointer can be named, and
1419 talloc_named() operates just like talloc() except that it allows you
1420 to name the pointer.
1422 _PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
1424 return _talloc_named_const(context, size, name);
1428 free a talloc pointer. This also frees all child pointers of this
1429 pointer recursively
1431 return 0 if the memory is actually freed, otherwise -1. The memory
1432 will not be freed if the ref_count is > 1 or the destructor (if
1433 any) returns non-zero
1435 _PUBLIC_ int _talloc_free(void *ptr, const char *location)
1437 struct talloc_chunk *tc;
1439 if (unlikely(ptr == NULL)) {
1440 return -1;
1443 tc = talloc_chunk_from_ptr(ptr);
1445 if (unlikely(tc->refs != NULL)) {
1446 struct talloc_reference_handle *h;
1448 if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
1449 /* in this case we do know which parent should
1450 get this pointer, as there is really only
1451 one parent */
1452 return talloc_unlink(null_context, ptr);
1455 talloc_log("ERROR: talloc_free with references at %s\n",
1456 location);
1458 for (h=tc->refs; h; h=h->next) {
1459 talloc_log("\treference at %s\n",
1460 h->location);
1462 return -1;
1465 return _talloc_free_internal(ptr, location);
1471 A talloc version of realloc. The context argument is only used if
1472 ptr is NULL
1474 _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
1476 struct talloc_chunk *tc;
1477 void *new_ptr;
1478 bool malloced = false;
1479 union talloc_pool_chunk *pool_tc = NULL;
1480 size_t old_size = 0;
1481 size_t new_size = 0;
1483 /* size zero is equivalent to free() */
1484 if (unlikely(size == 0)) {
1485 talloc_unlink(context, ptr);
1486 return NULL;
1489 if (unlikely(size >= MAX_TALLOC_SIZE)) {
1490 return NULL;
1493 /* realloc(NULL) is equivalent to malloc() */
1494 if (ptr == NULL) {
1495 return _talloc_named_const(context, size, name);
1498 tc = talloc_chunk_from_ptr(ptr);
1500 /* don't allow realloc on referenced pointers */
1501 if (unlikely(tc->refs)) {
1502 return NULL;
1505 /* don't let anybody try to realloc a talloc_pool */
1506 if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
1507 return NULL;
1510 if (tc->limit && (size > tc->size)) {
1511 if (!talloc_memlimit_check(tc->limit, (size - tc->size))) {
1512 errno = ENOMEM;
1513 return NULL;
1517 /* handle realloc inside a talloc_pool */
1518 if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
1519 pool_tc = (union talloc_pool_chunk *)tc->pool;
1522 #if (ALWAYS_REALLOC == 0)
1523 /* don't shrink if we have less than 1k to gain */
1524 if (size < tc->size && tc->limit == NULL) {
1525 if (pool_tc) {
1526 void *next_tc = tc_next_chunk(tc);
1527 TC_INVALIDATE_SHRINK_CHUNK(tc, size);
1528 tc->size = size;
1529 if (next_tc == pool_tc->hdr.c.pool) {
1530 /* note: tc->size has changed, so this works */
1531 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1533 return ptr;
1534 } else if ((tc->size - size) < 1024) {
1536 * if we call TC_INVALIDATE_SHRINK_CHUNK() here
1537 * we would need to call TC_UNDEFINE_GROW_CHUNK()
1538 * after each realloc call, which slows down
1539 * testing a lot :-(.
1541 * That is why we only mark memory as undefined here.
1543 TC_UNDEFINE_SHRINK_CHUNK(tc, size);
1545 /* do not shrink if we have less than 1k to gain */
1546 tc->size = size;
1547 return ptr;
1549 } else if (tc->size == size) {
1551 * do not change the pointer if it is exactly
1552 * the same size.
1554 return ptr;
1556 #endif
1558 /* by resetting magic we catch users of the old memory */
1559 tc->flags |= TALLOC_FLAG_FREE;
1561 #if ALWAYS_REALLOC
1562 if (pool_tc) {
1563 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1564 pool_tc->hdr.object_count--;
1566 if (new_ptr == NULL) {
1567 new_ptr = malloc(TC_HDR_SIZE+size);
1568 malloced = true;
1569 new_size = size;
1572 if (new_ptr) {
1573 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1574 TC_INVALIDATE_FULL_CHUNK(tc);
1576 } else {
1577 /* We're doing malloc then free here, so record the difference. */
1578 old_size = tc->size;
1579 new_size = size;
1580 new_ptr = malloc(size + TC_HDR_SIZE);
1581 if (new_ptr) {
1582 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1583 free(tc);
1586 #else
1587 if (pool_tc) {
1588 void *next_tc = tc_next_chunk(tc);
1589 size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size);
1590 size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
1591 size_t space_needed;
1592 size_t space_left;
1593 unsigned int chunk_count = pool_tc->hdr.object_count;
1595 if (!(pool_tc->hdr.c.flags & TALLOC_FLAG_FREE)) {
1596 chunk_count -= 1;
1599 if (chunk_count == 1) {
1601 * optimize for the case where 'tc' is the only
1602 * chunk in the pool.
1604 char *start = tc_pool_first_chunk(pool_tc);
1605 space_needed = new_chunk_size;
1606 space_left = (char *)tc_pool_end(pool_tc) - start;
1608 if (space_left >= space_needed) {
1609 size_t old_used = TC_HDR_SIZE + tc->size;
1610 size_t new_used = TC_HDR_SIZE + size;
1611 new_ptr = start;
1612 memmove(new_ptr, tc, old_used);
1614 tc = (struct talloc_chunk *)new_ptr;
1615 TC_UNDEFINE_GROW_CHUNK(tc, size);
1618 * first we do not align the pool pointer
1619 * because we want to invalidate the padding
1620 * too.
1622 pool_tc->hdr.c.pool = new_used + (char *)new_ptr;
1623 tc_invalidate_pool(pool_tc);
1625 /* now the aligned pointer */
1626 pool_tc->hdr.c.pool = new_chunk_size + (char *)new_ptr;
1627 goto got_new_ptr;
1630 next_tc = NULL;
1633 if (new_chunk_size == old_chunk_size) {
1634 TC_UNDEFINE_GROW_CHUNK(tc, size);
1635 tc->flags &= ~TALLOC_FLAG_FREE;
1636 tc->size = size;
1637 return ptr;
1640 if (next_tc == pool_tc->hdr.c.pool) {
1642 * optimize for the case where 'tc' is the last
1643 * chunk in the pool.
1645 space_needed = new_chunk_size - old_chunk_size;
1646 space_left = tc_pool_space_left(pool_tc);
1648 if (space_left >= space_needed) {
1649 TC_UNDEFINE_GROW_CHUNK(tc, size);
1650 tc->flags &= ~TALLOC_FLAG_FREE;
1651 tc->size = size;
1652 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1653 return ptr;
1657 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1659 if (new_ptr == NULL) {
1660 new_ptr = malloc(TC_HDR_SIZE+size);
1661 malloced = true;
1662 new_size = size;
1665 if (new_ptr) {
1666 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1668 _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
1671 else {
1672 /* We're doing realloc here, so record the difference. */
1673 old_size = tc->size;
1674 new_size = size;
1675 new_ptr = realloc(tc, size + TC_HDR_SIZE);
1677 got_new_ptr:
1678 #endif
1679 if (unlikely(!new_ptr)) {
1680 tc->flags &= ~TALLOC_FLAG_FREE;
1681 return NULL;
1684 tc = (struct talloc_chunk *)new_ptr;
1685 tc->flags &= ~TALLOC_FLAG_FREE;
1686 if (malloced) {
1687 tc->flags &= ~TALLOC_FLAG_POOLMEM;
1689 if (tc->parent) {
1690 tc->parent->child = tc;
1692 if (tc->child) {
1693 tc->child->parent = tc;
1696 if (tc->prev) {
1697 tc->prev->next = tc;
1699 if (tc->next) {
1700 tc->next->prev = tc;
1703 if (new_size > old_size) {
1704 talloc_memlimit_grow(tc->limit, new_size - old_size);
1705 } else if (new_size < old_size) {
1706 talloc_memlimit_shrink(tc->limit, old_size - new_size);
1709 tc->size = size;
1710 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
1712 return TC_PTR_FROM_CHUNK(tc);
1716 a wrapper around talloc_steal() for situations where you are moving a pointer
1717 between two structures, and want the old pointer to be set to NULL
1719 _PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
1721 const void **pptr = discard_const_p(const void *,_pptr);
1722 void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
1723 (*pptr) = NULL;
1724 return ret;
1727 enum talloc_mem_count_type {
1728 TOTAL_MEM_SIZE,
1729 TOTAL_MEM_BLOCKS,
1730 TOTAL_MEM_LIMIT,
1733 static size_t _talloc_total_mem_internal(const void *ptr,
1734 enum talloc_mem_count_type type,
1735 struct talloc_memlimit *old_limit,
1736 struct talloc_memlimit *new_limit)
1738 size_t total = 0;
1739 struct talloc_chunk *c, *tc;
1741 if (ptr == NULL) {
1742 ptr = null_context;
1744 if (ptr == NULL) {
1745 return 0;
1748 tc = talloc_chunk_from_ptr(ptr);
1750 if (old_limit || new_limit) {
1751 if (tc->limit && tc->limit->upper == old_limit) {
1752 tc->limit->upper = new_limit;
1756 /* optimize in the memlimits case */
1757 if (type == TOTAL_MEM_LIMIT &&
1758 tc->limit != NULL &&
1759 tc->limit != old_limit &&
1760 tc->limit->parent == tc) {
1761 return tc->limit->cur_size;
1764 if (tc->flags & TALLOC_FLAG_LOOP) {
1765 return 0;
1768 tc->flags |= TALLOC_FLAG_LOOP;
1770 if (old_limit || new_limit) {
1771 if (old_limit == tc->limit) {
1772 tc->limit = new_limit;
1776 switch (type) {
1777 case TOTAL_MEM_SIZE:
1778 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1779 total = tc->size;
1781 break;
1782 case TOTAL_MEM_BLOCKS:
1783 total++;
1784 break;
1785 case TOTAL_MEM_LIMIT:
1786 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1788 * Don't count memory allocated from a pool
1789 * when calculating limits. Only count the
1790 * pool itself.
1792 if (!(tc->flags & TALLOC_FLAG_POOLMEM)) {
1793 total = tc->size + TC_HDR_SIZE;
1796 break;
1798 for (c = tc->child; c; c = c->next) {
1799 total += _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c), type,
1800 old_limit, new_limit);
1803 tc->flags &= ~TALLOC_FLAG_LOOP;
1805 return total;
1809 return the total size of a talloc pool (subtree)
1811 _PUBLIC_ size_t talloc_total_size(const void *ptr)
1813 return _talloc_total_mem_internal(ptr, TOTAL_MEM_SIZE, NULL, NULL);
1817 return the total number of blocks in a talloc pool (subtree)
1819 _PUBLIC_ size_t talloc_total_blocks(const void *ptr)
1821 return _talloc_total_mem_internal(ptr, TOTAL_MEM_BLOCKS, NULL, NULL);
1825 return the number of external references to a pointer
1827 _PUBLIC_ size_t talloc_reference_count(const void *ptr)
1829 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1830 struct talloc_reference_handle *h;
1831 size_t ret = 0;
1833 for (h=tc->refs;h;h=h->next) {
1834 ret++;
1836 return ret;
1840 report on memory usage by all children of a pointer, giving a full tree view
1842 _PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1843 void (*callback)(const void *ptr,
1844 int depth, int max_depth,
1845 int is_ref,
1846 void *private_data),
1847 void *private_data)
1849 struct talloc_chunk *c, *tc;
1851 if (ptr == NULL) {
1852 ptr = null_context;
1854 if (ptr == NULL) return;
1856 tc = talloc_chunk_from_ptr(ptr);
1858 if (tc->flags & TALLOC_FLAG_LOOP) {
1859 return;
1862 callback(ptr, depth, max_depth, 0, private_data);
1864 if (max_depth >= 0 && depth >= max_depth) {
1865 return;
1868 tc->flags |= TALLOC_FLAG_LOOP;
1869 for (c=tc->child;c;c=c->next) {
1870 if (c->name == TALLOC_MAGIC_REFERENCE) {
1871 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1872 callback(h->ptr, depth + 1, max_depth, 1, private_data);
1873 } else {
1874 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1877 tc->flags &= ~TALLOC_FLAG_LOOP;
1880 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1882 const char *name = talloc_get_name(ptr);
1883 struct talloc_chunk *tc;
1884 FILE *f = (FILE *)_f;
1886 if (is_ref) {
1887 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1888 return;
1891 tc = talloc_chunk_from_ptr(ptr);
1892 if (tc->limit && tc->limit->parent == tc) {
1893 fprintf(f, "%*s%-30s is a memlimit context"
1894 " (max_size = %lu bytes, cur_size = %lu bytes)\n",
1895 depth*4, "",
1896 name,
1897 (unsigned long)tc->limit->max_size,
1898 (unsigned long)tc->limit->cur_size);
1901 if (depth == 0) {
1902 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1903 (max_depth < 0 ? "full " :""), name,
1904 (unsigned long)talloc_total_size(ptr),
1905 (unsigned long)talloc_total_blocks(ptr));
1906 return;
1909 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1910 depth*4, "",
1911 name,
1912 (unsigned long)talloc_total_size(ptr),
1913 (unsigned long)talloc_total_blocks(ptr),
1914 (int)talloc_reference_count(ptr), ptr);
1916 #if 0
1917 fprintf(f, "content: ");
1918 if (talloc_total_size(ptr)) {
1919 int tot = talloc_total_size(ptr);
1920 int i;
1922 for (i = 0; i < tot; i++) {
1923 if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1924 fprintf(f, "%c", ((char *)ptr)[i]);
1925 } else {
1926 fprintf(f, "~%02x", ((char *)ptr)[i]);
1930 fprintf(f, "\n");
1931 #endif
1935 report on memory usage by all children of a pointer, giving a full tree view
1937 _PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1939 if (f) {
1940 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1941 fflush(f);
1946 report on memory usage by all children of a pointer, giving a full tree view
1948 _PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
1950 talloc_report_depth_file(ptr, 0, -1, f);
1954 report on memory usage by all children of a pointer
1956 _PUBLIC_ void talloc_report(const void *ptr, FILE *f)
1958 talloc_report_depth_file(ptr, 0, 1, f);
1962 report on any memory hanging off the null context
1964 static void talloc_report_null(void)
1966 if (talloc_total_size(null_context) != 0) {
1967 talloc_report(null_context, stderr);
1972 report on any memory hanging off the null context
1974 static void talloc_report_null_full(void)
1976 if (talloc_total_size(null_context) != 0) {
1977 talloc_report_full(null_context, stderr);
1982 enable tracking of the NULL context
1984 _PUBLIC_ void talloc_enable_null_tracking(void)
1986 if (null_context == NULL) {
1987 null_context = _talloc_named_const(NULL, 0, "null_context");
1988 if (autofree_context != NULL) {
1989 talloc_reparent(NULL, null_context, autofree_context);
1995 enable tracking of the NULL context, not moving the autofree context
1996 into the NULL context. This is needed for the talloc testsuite
1998 _PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
2000 if (null_context == NULL) {
2001 null_context = _talloc_named_const(NULL, 0, "null_context");
2006 disable tracking of the NULL context
2008 _PUBLIC_ void talloc_disable_null_tracking(void)
2010 if (null_context != NULL) {
2011 /* we have to move any children onto the real NULL
2012 context */
2013 struct talloc_chunk *tc, *tc2;
2014 tc = talloc_chunk_from_ptr(null_context);
2015 for (tc2 = tc->child; tc2; tc2=tc2->next) {
2016 if (tc2->parent == tc) tc2->parent = NULL;
2017 if (tc2->prev == tc) tc2->prev = NULL;
2019 for (tc2 = tc->next; tc2; tc2=tc2->next) {
2020 if (tc2->parent == tc) tc2->parent = NULL;
2021 if (tc2->prev == tc) tc2->prev = NULL;
2023 tc->child = NULL;
2024 tc->next = NULL;
2026 talloc_free(null_context);
2027 null_context = NULL;
2031 enable leak reporting on exit
2033 _PUBLIC_ void talloc_enable_leak_report(void)
2035 talloc_enable_null_tracking();
2036 atexit(talloc_report_null);
2040 enable full leak reporting on exit
2042 _PUBLIC_ void talloc_enable_leak_report_full(void)
2044 talloc_enable_null_tracking();
2045 atexit(talloc_report_null_full);
2049 talloc and zero memory.
2051 _PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
2053 void *p = _talloc_named_const(ctx, size, name);
2055 if (p) {
2056 memset(p, '\0', size);
2059 return p;
2063 memdup with a talloc.
2065 _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
2067 void *newp = _talloc_named_const(t, size, name);
2069 if (likely(newp)) {
2070 memcpy(newp, p, size);
2073 return newp;
2076 static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
2078 char *ret;
2080 ret = (char *)__talloc(t, len + 1);
2081 if (unlikely(!ret)) return NULL;
2083 memcpy(ret, p, len);
2084 ret[len] = 0;
2086 _talloc_set_name_const(ret, ret);
2087 return ret;
2091 strdup with a talloc
2093 _PUBLIC_ char *talloc_strdup(const void *t, const char *p)
2095 if (unlikely(!p)) return NULL;
2096 return __talloc_strlendup(t, p, strlen(p));
2100 strndup with a talloc
2102 _PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
2104 if (unlikely(!p)) return NULL;
2105 return __talloc_strlendup(t, p, strnlen(p, n));
2108 static inline char *__talloc_strlendup_append(char *s, size_t slen,
2109 const char *a, size_t alen)
2111 char *ret;
2113 ret = talloc_realloc(NULL, s, char, slen + alen + 1);
2114 if (unlikely(!ret)) return NULL;
2116 /* append the string and the trailing \0 */
2117 memcpy(&ret[slen], a, alen);
2118 ret[slen+alen] = 0;
2120 _talloc_set_name_const(ret, ret);
2121 return ret;
2125 * Appends at the end of the string.
2127 _PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
2129 if (unlikely(!s)) {
2130 return talloc_strdup(NULL, a);
2133 if (unlikely(!a)) {
2134 return s;
2137 return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
2141 * Appends at the end of the talloc'ed buffer,
2142 * not the end of the string.
2144 _PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
2146 size_t slen;
2148 if (unlikely(!s)) {
2149 return talloc_strdup(NULL, a);
2152 if (unlikely(!a)) {
2153 return s;
2156 slen = talloc_get_size(s);
2157 if (likely(slen > 0)) {
2158 slen--;
2161 return __talloc_strlendup_append(s, slen, a, strlen(a));
2165 * Appends at the end of the string.
2167 _PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
2169 if (unlikely(!s)) {
2170 return talloc_strndup(NULL, a, n);
2173 if (unlikely(!a)) {
2174 return s;
2177 return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
2181 * Appends at the end of the talloc'ed buffer,
2182 * not the end of the string.
2184 _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
2186 size_t slen;
2188 if (unlikely(!s)) {
2189 return talloc_strndup(NULL, a, n);
2192 if (unlikely(!a)) {
2193 return s;
2196 slen = talloc_get_size(s);
2197 if (likely(slen > 0)) {
2198 slen--;
2201 return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
2204 #ifndef HAVE_VA_COPY
2205 #ifdef HAVE___VA_COPY
2206 #define va_copy(dest, src) __va_copy(dest, src)
2207 #else
2208 #define va_copy(dest, src) (dest) = (src)
2209 #endif
2210 #endif
2212 _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
2214 int len;
2215 char *ret;
2216 va_list ap2;
2217 char c;
2219 /* this call looks strange, but it makes it work on older solaris boxes */
2220 va_copy(ap2, ap);
2221 len = vsnprintf(&c, 1, fmt, ap2);
2222 va_end(ap2);
2223 if (unlikely(len < 0)) {
2224 return NULL;
2227 ret = (char *)__talloc(t, len+1);
2228 if (unlikely(!ret)) return NULL;
2230 va_copy(ap2, ap);
2231 vsnprintf(ret, len+1, fmt, ap2);
2232 va_end(ap2);
2234 _talloc_set_name_const(ret, ret);
2235 return ret;
2240 Perform string formatting, and return a pointer to newly allocated
2241 memory holding the result, inside a memory pool.
2243 _PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
2245 va_list ap;
2246 char *ret;
2248 va_start(ap, fmt);
2249 ret = talloc_vasprintf(t, fmt, ap);
2250 va_end(ap);
2251 return ret;
2254 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2255 const char *fmt, va_list ap)
2256 PRINTF_ATTRIBUTE(3,0);
2258 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2259 const char *fmt, va_list ap)
2261 ssize_t alen;
2262 va_list ap2;
2263 char c;
2265 va_copy(ap2, ap);
2266 alen = vsnprintf(&c, 1, fmt, ap2);
2267 va_end(ap2);
2269 if (alen <= 0) {
2270 /* Either the vsnprintf failed or the format resulted in
2271 * no characters being formatted. In the former case, we
2272 * ought to return NULL, in the latter we ought to return
2273 * the original string. Most current callers of this
2274 * function expect it to never return NULL.
2276 return s;
2279 s = talloc_realloc(NULL, s, char, slen + alen + 1);
2280 if (!s) return NULL;
2282 va_copy(ap2, ap);
2283 vsnprintf(s + slen, alen + 1, fmt, ap2);
2284 va_end(ap2);
2286 _talloc_set_name_const(s, s);
2287 return s;
2291 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2292 * and return @p s, which may have moved. Good for gradually
2293 * accumulating output into a string buffer. Appends at the end
2294 * of the string.
2296 _PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
2298 if (unlikely(!s)) {
2299 return talloc_vasprintf(NULL, fmt, ap);
2302 return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
2306 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2307 * and return @p s, which may have moved. Always appends at the
2308 * end of the talloc'ed buffer, not the end of the string.
2310 _PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
2312 size_t slen;
2314 if (unlikely(!s)) {
2315 return talloc_vasprintf(NULL, fmt, ap);
2318 slen = talloc_get_size(s);
2319 if (likely(slen > 0)) {
2320 slen--;
2323 return __talloc_vaslenprintf_append(s, slen, fmt, ap);
2327 Realloc @p s to append the formatted result of @p fmt and return @p
2328 s, which may have moved. Good for gradually accumulating output
2329 into a string buffer.
2331 _PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
2333 va_list ap;
2335 va_start(ap, fmt);
2336 s = talloc_vasprintf_append(s, fmt, ap);
2337 va_end(ap);
2338 return s;
2342 Realloc @p s to append the formatted result of @p fmt and return @p
2343 s, which may have moved. Good for gradually accumulating output
2344 into a buffer.
2346 _PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
2348 va_list ap;
2350 va_start(ap, fmt);
2351 s = talloc_vasprintf_append_buffer(s, fmt, ap);
2352 va_end(ap);
2353 return s;
2357 alloc an array, checking for integer overflow in the array size
2359 _PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2361 if (count >= MAX_TALLOC_SIZE/el_size) {
2362 return NULL;
2364 return _talloc_named_const(ctx, el_size * count, name);
2368 alloc an zero array, checking for integer overflow in the array size
2370 _PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2372 if (count >= MAX_TALLOC_SIZE/el_size) {
2373 return NULL;
2375 return _talloc_zero(ctx, el_size * count, name);
2379 realloc an array, checking for integer overflow in the array size
2381 _PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
2383 if (count >= MAX_TALLOC_SIZE/el_size) {
2384 return NULL;
2386 return _talloc_realloc(ctx, ptr, el_size * count, name);
2390 a function version of talloc_realloc(), so it can be passed as a function pointer
2391 to libraries that want a realloc function (a realloc function encapsulates
2392 all the basic capabilities of an allocation library, which is why this is useful)
2394 _PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
2396 return _talloc_realloc(context, ptr, size, NULL);
2400 static int talloc_autofree_destructor(void *ptr)
2402 autofree_context = NULL;
2403 return 0;
2406 static void talloc_autofree(void)
2408 talloc_free(autofree_context);
2412 return a context which will be auto-freed on exit
2413 this is useful for reducing the noise in leak reports
2415 _PUBLIC_ void *talloc_autofree_context(void)
2417 if (autofree_context == NULL) {
2418 autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
2419 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
2420 atexit(talloc_autofree);
2422 return autofree_context;
2425 _PUBLIC_ size_t talloc_get_size(const void *context)
2427 struct talloc_chunk *tc;
2429 if (context == NULL) {
2430 context = null_context;
2432 if (context == NULL) {
2433 return 0;
2436 tc = talloc_chunk_from_ptr(context);
2438 return tc->size;
2442 find a parent of this context that has the given name, if any
2444 _PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
2446 struct talloc_chunk *tc;
2448 if (context == NULL) {
2449 return NULL;
2452 tc = talloc_chunk_from_ptr(context);
2453 while (tc) {
2454 if (tc->name && strcmp(tc->name, name) == 0) {
2455 return TC_PTR_FROM_CHUNK(tc);
2457 while (tc && tc->prev) tc = tc->prev;
2458 if (tc) {
2459 tc = tc->parent;
2462 return NULL;
2466 show the parentage of a context
2468 _PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
2470 struct talloc_chunk *tc;
2472 if (context == NULL) {
2473 fprintf(file, "talloc no parents for NULL\n");
2474 return;
2477 tc = talloc_chunk_from_ptr(context);
2478 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
2479 while (tc) {
2480 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
2481 while (tc && tc->prev) tc = tc->prev;
2482 if (tc) {
2483 tc = tc->parent;
2486 fflush(file);
2490 return 1 if ptr is a parent of context
2492 static int _talloc_is_parent(const void *context, const void *ptr, int depth)
2494 struct talloc_chunk *tc;
2496 if (context == NULL) {
2497 return 0;
2500 tc = talloc_chunk_from_ptr(context);
2501 while (tc && depth > 0) {
2502 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
2503 while (tc && tc->prev) tc = tc->prev;
2504 if (tc) {
2505 tc = tc->parent;
2506 depth--;
2509 return 0;
2513 return 1 if ptr is a parent of context
2515 _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
2517 return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
2521 return the total size of memory used by this context and all children
2523 static size_t _talloc_total_limit_size(const void *ptr,
2524 struct talloc_memlimit *old_limit,
2525 struct talloc_memlimit *new_limit)
2527 return _talloc_total_mem_internal(ptr, TOTAL_MEM_LIMIT,
2528 old_limit, new_limit);
2531 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size)
2533 struct talloc_memlimit *l;
2535 for (l = limit; l != NULL; l = l->upper) {
2536 if (l->max_size != 0 &&
2537 ((l->max_size <= l->cur_size) ||
2538 (l->max_size - l->cur_size < size))) {
2539 return false;
2543 return true;
2547 Update memory limits when freeing a talloc_chunk.
2549 static void talloc_memlimit_update_on_free(struct talloc_chunk *tc)
2551 if (!tc->limit) {
2552 return;
2556 * Pool entries don't count. Only the pools
2557 * themselves are counted as part of the memory
2558 * limits.
2560 if (tc->flags & TALLOC_FLAG_POOLMEM) {
2561 return;
2565 * If we are part of a memory limited context hierarchy
2566 * we need to subtract the memory used from the counters
2569 talloc_memlimit_shrink(tc->limit, tc->size+TC_HDR_SIZE);
2571 if (tc->limit->parent == tc) {
2572 free(tc->limit);
2575 tc->limit = NULL;
2579 Increase memory limit accounting after a malloc/realloc.
2581 static void talloc_memlimit_grow(struct talloc_memlimit *limit,
2582 size_t size)
2584 struct talloc_memlimit *l;
2586 for (l = limit; l != NULL; l = l->upper) {
2587 size_t new_cur_size = l->cur_size + size;
2588 if (new_cur_size < l->cur_size) {
2589 talloc_abort("logic error in talloc_memlimit_grow\n");
2590 return;
2592 l->cur_size = new_cur_size;
2597 Decrease memory limit accounting after a free/realloc.
2599 static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
2600 size_t size)
2602 struct talloc_memlimit *l;
2604 for (l = limit; l != NULL; l = l->upper) {
2605 if (l->cur_size < size) {
2606 talloc_abort("logic error in talloc_memlimit_shrink\n");
2607 return;
2609 l->cur_size = l->cur_size - size;
2613 _PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size)
2615 struct talloc_chunk *tc = talloc_chunk_from_ptr(ctx);
2616 struct talloc_memlimit *orig_limit;
2617 struct talloc_memlimit *limit = NULL;
2619 if (tc->limit && tc->limit->parent == tc) {
2620 tc->limit->max_size = max_size;
2621 return 0;
2623 orig_limit = tc->limit;
2625 limit = malloc(sizeof(struct talloc_memlimit));
2626 if (limit == NULL) {
2627 return 1;
2629 limit->parent = tc;
2630 limit->max_size = max_size;
2631 limit->cur_size = _talloc_total_limit_size(ctx, tc->limit, limit);
2633 if (orig_limit) {
2634 limit->upper = orig_limit;
2635 } else {
2636 limit->upper = NULL;
2639 return 0;