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