Update memory limits when we call free() on a pool.
[Samba.git] / lib / talloc / talloc.c
blobc45ac9327bc1f69c1f7238d8a8f6d4ebbd2ea920
1 /*
2 Samba Unix SMB/CIFS implementation.
4 Samba trivial allocation library - new interface
6 NOTE: Please read talloc_guide.txt for full documentation
8 Copyright (C) Andrew Tridgell 2004
9 Copyright (C) Stefan Metzmacher 2006
11 ** NOTE! The following LGPL license applies to the talloc
12 ** library. This does NOT imply that all of Samba is released
13 ** under the LGPL
15 This library is free software; you can redistribute it and/or
16 modify it under the terms of the GNU Lesser General Public
17 License as published by the Free Software Foundation; either
18 version 3 of the License, or (at your option) any later version.
20 This library is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Lesser General Public License for more details.
25 You should have received a copy of the GNU Lesser General Public
26 License along with this library; if not, see <http://www.gnu.org/licenses/>.
30 inspired by http://swapped.cc/halloc/
33 #include "replace.h"
34 #include "talloc.h"
36 #ifdef TALLOC_BUILD_VERSION_MAJOR
37 #if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR)
38 #error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR"
39 #endif
40 #endif
42 #ifdef TALLOC_BUILD_VERSION_MINOR
43 #if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR)
44 #error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR"
45 #endif
46 #endif
48 /* Special macros that are no-ops except when run under Valgrind on
49 * x86. They've moved a little bit from valgrind 1.0.4 to 1.9.4 */
50 #ifdef HAVE_VALGRIND_MEMCHECK_H
51 /* memcheck.h includes valgrind.h */
52 #include <valgrind/memcheck.h>
53 #elif defined(HAVE_VALGRIND_H)
54 #include <valgrind.h>
55 #endif
57 /* use this to force every realloc to change the pointer, to stress test
58 code that might not cope */
59 #define ALWAYS_REALLOC 0
62 #define MAX_TALLOC_SIZE 0x10000000
63 #define TALLOC_MAGIC_BASE 0xe814ec70
64 #define TALLOC_MAGIC ( \
65 TALLOC_MAGIC_BASE + \
66 (TALLOC_VERSION_MAJOR << 12) + \
67 (TALLOC_VERSION_MINOR << 4) \
70 #define TALLOC_FLAG_FREE 0x01
71 #define TALLOC_FLAG_LOOP 0x02
72 #define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */
73 #define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */
75 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
77 /* by default we abort when given a bad pointer (such as when talloc_free() is called
78 on a pointer that came from malloc() */
79 #ifndef TALLOC_ABORT
80 #define TALLOC_ABORT(reason) abort()
81 #endif
83 #ifndef discard_const_p
84 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
85 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
86 #else
87 # define discard_const_p(type, ptr) ((type *)(ptr))
88 #endif
89 #endif
91 /* these macros gain us a few percent of speed on gcc */
92 #if (__GNUC__ >= 3)
93 /* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
94 as its first argument */
95 #ifndef likely
96 #define likely(x) __builtin_expect(!!(x), 1)
97 #endif
98 #ifndef unlikely
99 #define unlikely(x) __builtin_expect(!!(x), 0)
100 #endif
101 #else
102 #ifndef likely
103 #define likely(x) (x)
104 #endif
105 #ifndef unlikely
106 #define unlikely(x) (x)
107 #endif
108 #endif
110 /* this null_context is only used if talloc_enable_leak_report() or
111 talloc_enable_leak_report_full() is called, otherwise it remains
112 NULL
114 static void *null_context;
115 static void *autofree_context;
117 /* used to enable fill of memory on free, which can be useful for
118 * catching use after free errors when valgrind is too slow
120 static struct {
121 bool initialised;
122 bool enabled;
123 uint8_t fill_value;
124 } talloc_fill;
126 #define TALLOC_FILL_ENV "TALLOC_FREE_FILL"
129 * do not wipe the header, to allow the
130 * double-free logic to still work
132 #define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \
133 if (unlikely(talloc_fill.enabled)) { \
134 size_t _flen = (_tc)->size; \
135 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
136 memset(_fptr, talloc_fill.fill_value, _flen); \
138 } while (0)
140 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
141 /* Mark the whole chunk as not accessable */
142 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \
143 size_t _flen = TC_HDR_SIZE + (_tc)->size; \
144 char *_fptr = (char *)(_tc); \
145 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
146 } while(0)
147 #else
148 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0)
149 #endif
151 #define TC_INVALIDATE_FULL_CHUNK(_tc) do { \
152 TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \
153 TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \
154 } while (0)
156 #define TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
157 if (unlikely(talloc_fill.enabled)) { \
158 size_t _flen = (_tc)->size - (_new_size); \
159 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
160 _fptr += (_new_size); \
161 memset(_fptr, talloc_fill.fill_value, _flen); \
163 } while (0)
165 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
166 /* Mark the unused bytes not accessable */
167 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
168 size_t _flen = (_tc)->size - (_new_size); \
169 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
170 _fptr += (_new_size); \
171 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
172 } while (0)
173 #else
174 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
175 #endif
177 #define TC_INVALIDATE_SHRINK_CHUNK(_tc, _new_size) do { \
178 TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size); \
179 TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
180 } while (0)
182 #define TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
183 if (unlikely(talloc_fill.enabled)) { \
184 size_t _flen = (_tc)->size - (_new_size); \
185 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
186 _fptr += (_new_size); \
187 memset(_fptr, talloc_fill.fill_value, _flen); \
189 } while (0)
191 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
192 /* Mark the unused bytes as undefined */
193 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
194 size_t _flen = (_tc)->size - (_new_size); \
195 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
196 _fptr += (_new_size); \
197 VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
198 } while (0)
199 #else
200 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
201 #endif
203 #define TC_UNDEFINE_SHRINK_CHUNK(_tc, _new_size) do { \
204 TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size); \
205 TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
206 } while (0)
208 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
209 /* Mark the new bytes as undefined */
210 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { \
211 size_t _old_used = TC_HDR_SIZE + (_tc)->size; \
212 size_t _new_used = TC_HDR_SIZE + (_new_size); \
213 size_t _flen = _new_used - _old_used; \
214 char *_fptr = _old_used + (char *)(_tc); \
215 VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
216 } while (0)
217 #else
218 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
219 #endif
221 #define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \
222 TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \
223 } while (0)
225 struct talloc_reference_handle {
226 struct talloc_reference_handle *next, *prev;
227 void *ptr;
228 const char *location;
231 struct talloc_memlimit {
232 struct talloc_chunk *parent;
233 struct talloc_memlimit *upper;
234 size_t max_size;
235 size_t cur_size;
238 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size);
239 static bool talloc_memlimit_update(struct talloc_memlimit *limit,
240 size_t old_size, size_t new_size);
241 static void talloc_memlimit_grow(struct talloc_memlimit *limit,
242 size_t size);
243 static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
244 size_t size);
245 static void talloc_memlimit_update_on_free(struct talloc_chunk *tc);
247 typedef int (*talloc_destructor_t)(void *);
249 struct talloc_chunk {
250 struct talloc_chunk *next, *prev;
251 struct talloc_chunk *parent, *child;
252 struct talloc_reference_handle *refs;
253 talloc_destructor_t destructor;
254 const char *name;
255 size_t size;
256 unsigned flags;
259 * limit semantics:
260 * if 'limit' is set it means all *new* children of the context will
261 * be limited to a total aggregate size ox max_size for memory
262 * allocations.
263 * cur_size is used to keep track of the current use
265 struct talloc_memlimit *limit;
268 * "pool" has dual use:
270 * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
271 * marks the end of the currently allocated area.
273 * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
274 * is a pointer to the struct talloc_chunk of the pool that it was
275 * allocated from. This way children can quickly find the pool to chew
276 * from.
278 void *pool;
281 /* 16 byte alignment seems to keep everyone happy */
282 #define TC_ALIGN16(s) (((s)+15)&~15)
283 #define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
284 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
286 _PUBLIC_ int talloc_version_major(void)
288 return TALLOC_VERSION_MAJOR;
291 _PUBLIC_ int talloc_version_minor(void)
293 return TALLOC_VERSION_MINOR;
296 static void (*talloc_log_fn)(const char *message);
298 _PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
300 talloc_log_fn = log_fn;
303 static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
304 static void talloc_log(const char *fmt, ...)
306 va_list ap;
307 char *message;
309 if (!talloc_log_fn) {
310 return;
313 va_start(ap, fmt);
314 message = talloc_vasprintf(NULL, fmt, ap);
315 va_end(ap);
317 talloc_log_fn(message);
318 talloc_free(message);
321 static void talloc_log_stderr(const char *message)
323 fprintf(stderr, "%s", message);
326 _PUBLIC_ void talloc_set_log_stderr(void)
328 talloc_set_log_fn(talloc_log_stderr);
331 static void (*talloc_abort_fn)(const char *reason);
333 _PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
335 talloc_abort_fn = abort_fn;
338 static void talloc_abort(const char *reason)
340 talloc_log("%s\n", reason);
342 if (!talloc_abort_fn) {
343 TALLOC_ABORT(reason);
346 talloc_abort_fn(reason);
349 static void talloc_abort_magic(unsigned magic)
351 unsigned striped = magic - TALLOC_MAGIC_BASE;
352 unsigned major = (striped & 0xFFFFF000) >> 12;
353 unsigned minor = (striped & 0x00000FF0) >> 4;
354 talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
355 magic, major, minor,
356 TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR);
357 talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
360 static void talloc_abort_access_after_free(void)
362 talloc_abort("Bad talloc magic value - access after free");
365 static void talloc_abort_unknown_value(void)
367 talloc_abort("Bad talloc magic value - unknown value");
370 /* panic if we get a bad magic value */
371 static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
373 const char *pp = (const char *)ptr;
374 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
375 if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
376 if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) {
377 talloc_abort_magic(tc->flags & (~0xF));
378 return NULL;
381 if (tc->flags & TALLOC_FLAG_FREE) {
382 talloc_log("talloc: access after free error - first free may be at %s\n", tc->name);
383 talloc_abort_access_after_free();
384 return NULL;
385 } else {
386 talloc_abort_unknown_value();
387 return NULL;
390 return tc;
393 /* hook into the front of the list */
394 #define _TLIST_ADD(list, p) \
395 do { \
396 if (!(list)) { \
397 (list) = (p); \
398 (p)->next = (p)->prev = NULL; \
399 } else { \
400 (list)->prev = (p); \
401 (p)->next = (list); \
402 (p)->prev = NULL; \
403 (list) = (p); \
405 } while (0)
407 /* remove an element from a list - element doesn't have to be in list. */
408 #define _TLIST_REMOVE(list, p) \
409 do { \
410 if ((p) == (list)) { \
411 (list) = (p)->next; \
412 if (list) (list)->prev = NULL; \
413 } else { \
414 if ((p)->prev) (p)->prev->next = (p)->next; \
415 if ((p)->next) (p)->next->prev = (p)->prev; \
417 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
418 } while (0)
422 return the parent chunk of a pointer
424 static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
426 struct talloc_chunk *tc;
428 if (unlikely(ptr == NULL)) {
429 return NULL;
432 tc = talloc_chunk_from_ptr(ptr);
433 while (tc->prev) tc=tc->prev;
435 return tc->parent;
438 _PUBLIC_ void *talloc_parent(const void *ptr)
440 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
441 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
445 find parents name
447 _PUBLIC_ const char *talloc_parent_name(const void *ptr)
449 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
450 return tc? tc->name : NULL;
454 A pool carries an in-pool object count count in the first 16 bytes.
455 bytes. This is done to support talloc_steal() to a parent outside of the
456 pool. The count includes the pool itself, so a talloc_free() on a pool will
457 only destroy the pool if the count has dropped to zero. A talloc_free() of a
458 pool member will reduce the count, and eventually also call free(3) on the
459 pool memory.
461 The object count is not put into "struct talloc_chunk" because it is only
462 relevant for talloc pools and the alignment to 16 bytes would increase the
463 memory footprint of each talloc chunk by those 16 bytes.
466 union talloc_pool_chunk {
467 /* This lets object_count nestle into 16-byte padding of talloc_chunk,
468 * on 32-bit platforms. */
469 struct tc_pool_hdr {
470 struct talloc_chunk c;
471 unsigned int object_count;
472 } hdr;
473 /* This makes it always 16 byte aligned. */
474 char pad[TC_ALIGN16(sizeof(struct tc_pool_hdr))];
477 static void *tc_pool_end(union talloc_pool_chunk *pool_tc)
479 return (char *)pool_tc + TC_HDR_SIZE + pool_tc->hdr.c.size;
482 static size_t tc_pool_space_left(union talloc_pool_chunk *pool_tc)
484 return (char *)tc_pool_end(pool_tc) - (char *)pool_tc->hdr.c.pool;
487 static void *tc_pool_first_chunk(union talloc_pool_chunk *pool_tc)
489 return pool_tc + 1;
492 /* If tc is inside a pool, this gives the next neighbour. */
493 static void *tc_next_chunk(struct talloc_chunk *tc)
495 return (char *)tc + TC_ALIGN16(TC_HDR_SIZE + tc->size);
498 /* Mark the whole remaining pool as not accessable */
499 static void tc_invalidate_pool(union talloc_pool_chunk *pool_tc)
501 size_t flen = tc_pool_space_left(pool_tc);
503 if (unlikely(talloc_fill.enabled)) {
504 memset(pool_tc->hdr.c.pool, talloc_fill.fill_value, flen);
507 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
508 VALGRIND_MAKE_MEM_NOACCESS(pool_tc->hdr.c.pool, flen);
509 #endif
513 Allocate from a pool
516 static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
517 size_t size)
519 union talloc_pool_chunk *pool_ctx = NULL;
520 size_t space_left;
521 struct talloc_chunk *result;
522 size_t chunk_size;
524 if (parent == NULL) {
525 return NULL;
528 if (parent->flags & TALLOC_FLAG_POOL) {
529 pool_ctx = (union talloc_pool_chunk *)parent;
531 else if (parent->flags & TALLOC_FLAG_POOLMEM) {
532 pool_ctx = (union talloc_pool_chunk *)parent->pool;
535 if (pool_ctx == NULL) {
536 return NULL;
539 space_left = tc_pool_space_left(pool_ctx);
542 * Align size to 16 bytes
544 chunk_size = TC_ALIGN16(size);
546 if (space_left < chunk_size) {
547 return NULL;
550 result = (struct talloc_chunk *)pool_ctx->hdr.c.pool;
552 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
553 VALGRIND_MAKE_MEM_UNDEFINED(result, size);
554 #endif
556 pool_ctx->hdr.c.pool = (void *)((char *)result + chunk_size);
558 result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
559 result->pool = pool_ctx;
561 pool_ctx->hdr.object_count++;
563 return result;
567 Allocate a bit of memory as a child of an existing pointer
569 static inline void *__talloc(const void *context, size_t size)
571 struct talloc_chunk *tc = NULL;
572 struct talloc_memlimit *limit = NULL;
574 if (unlikely(context == NULL)) {
575 context = null_context;
578 if (unlikely(size >= MAX_TALLOC_SIZE)) {
579 return NULL;
582 if (context != NULL) {
583 struct talloc_chunk *ptc = talloc_chunk_from_ptr(context);
585 if (ptc->limit != NULL) {
586 limit = ptc->limit;
589 tc = talloc_alloc_pool(ptc, TC_HDR_SIZE+size);
592 if (tc == NULL) {
594 * Only do the memlimit check/update on actual allocation.
596 if (!talloc_memlimit_check(limit, TC_HDR_SIZE + size)) {
597 errno = ENOMEM;
598 return NULL;
601 tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
602 if (unlikely(tc == NULL)) return NULL;
603 tc->flags = TALLOC_MAGIC;
604 tc->pool = NULL;
606 talloc_memlimit_grow(limit, TC_HDR_SIZE + size);
609 tc->limit = limit;
610 tc->size = size;
611 tc->destructor = NULL;
612 tc->child = NULL;
613 tc->name = NULL;
614 tc->refs = NULL;
616 if (likely(context)) {
617 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
619 if (parent->child) {
620 parent->child->parent = NULL;
621 tc->next = parent->child;
622 tc->next->prev = tc;
623 } else {
624 tc->next = NULL;
626 tc->parent = parent;
627 tc->prev = NULL;
628 parent->child = tc;
629 } else {
630 tc->next = tc->prev = tc->parent = NULL;
633 return TC_PTR_FROM_CHUNK(tc);
637 * Create a talloc pool
640 _PUBLIC_ void *talloc_pool(const void *context, size_t size)
642 union talloc_pool_chunk *pool_tc;
643 void *result = __talloc(context, sizeof(*pool_tc) - TC_HDR_SIZE + size);
645 if (unlikely(result == NULL)) {
646 return NULL;
649 pool_tc = (union talloc_pool_chunk *)talloc_chunk_from_ptr(result);
650 if (unlikely(pool_tc->hdr.c.flags & TALLOC_FLAG_POOLMEM)) {
651 /* We don't handle this correctly, so fail. */
652 talloc_log("talloc: cannot allocate pool off another pool %s\n",
653 talloc_get_name(context));
654 talloc_free(result);
655 return NULL;
657 pool_tc->hdr.c.flags |= TALLOC_FLAG_POOL;
658 pool_tc->hdr.c.pool = tc_pool_first_chunk(pool_tc);
660 pool_tc->hdr.object_count = 1;
662 tc_invalidate_pool(pool_tc);
664 return result;
668 setup a destructor to be called on free of a pointer
669 the destructor should return 0 on success, or -1 on failure.
670 if the destructor fails then the free is failed, and the memory can
671 be continued to be used
673 _PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
675 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
676 tc->destructor = destructor;
680 increase the reference count on a piece of memory.
682 _PUBLIC_ int talloc_increase_ref_count(const void *ptr)
684 if (unlikely(!talloc_reference(null_context, ptr))) {
685 return -1;
687 return 0;
691 helper for talloc_reference()
693 this is referenced by a function pointer and should not be inline
695 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
697 struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
698 _TLIST_REMOVE(ptr_tc->refs, handle);
699 return 0;
703 more efficient way to add a name to a pointer - the name must point to a
704 true string constant
706 static inline void _talloc_set_name_const(const void *ptr, const char *name)
708 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
709 tc->name = name;
713 internal talloc_named_const()
715 static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
717 void *ptr;
719 ptr = __talloc(context, size);
720 if (unlikely(ptr == NULL)) {
721 return NULL;
724 _talloc_set_name_const(ptr, name);
726 return ptr;
730 make a secondary reference to a pointer, hanging off the given context.
731 the pointer remains valid until both the original caller and this given
732 context are freed.
734 the major use for this is when two different structures need to reference the
735 same underlying data, and you want to be able to free the two instances separately,
736 and in either order
738 _PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
740 struct talloc_chunk *tc;
741 struct talloc_reference_handle *handle;
742 if (unlikely(ptr == NULL)) return NULL;
744 tc = talloc_chunk_from_ptr(ptr);
745 handle = (struct talloc_reference_handle *)_talloc_named_const(context,
746 sizeof(struct talloc_reference_handle),
747 TALLOC_MAGIC_REFERENCE);
748 if (unlikely(handle == NULL)) return NULL;
750 /* note that we hang the destructor off the handle, not the
751 main context as that allows the caller to still setup their
752 own destructor on the context if they want to */
753 talloc_set_destructor(handle, talloc_reference_destructor);
754 handle->ptr = discard_const_p(void, ptr);
755 handle->location = location;
756 _TLIST_ADD(tc->refs, handle);
757 return handle->ptr;
760 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
762 static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
763 const char *location)
765 union talloc_pool_chunk *pool;
766 void *next_tc;
768 pool = (union talloc_pool_chunk *)tc->pool;
769 next_tc = tc_next_chunk(tc);
771 tc->flags |= TALLOC_FLAG_FREE;
773 /* we mark the freed memory with where we called the free
774 * from. This means on a double free error we can report where
775 * the first free came from
777 tc->name = location;
779 TC_INVALIDATE_FULL_CHUNK(tc);
781 if (unlikely(pool->hdr.object_count == 0)) {
782 talloc_abort("Pool object count zero!");
783 return;
786 pool->hdr.object_count--;
788 if (unlikely(pool->hdr.object_count == 1
789 && !(pool->hdr.c.flags & TALLOC_FLAG_FREE))) {
791 * if there is just one object left in the pool
792 * and pool->flags does not have TALLOC_FLAG_FREE,
793 * it means this is the pool itself and
794 * the rest is available for new objects
795 * again.
797 pool->hdr.c.pool = tc_pool_first_chunk(pool);
798 tc_invalidate_pool(pool);
799 return;
802 if (unlikely(pool->hdr.object_count == 0)) {
804 * we mark the freed memory with where we called the free
805 * from. This means on a double free error we can report where
806 * the first free came from
808 pool->hdr.c.name = location;
810 talloc_memlimit_update_on_free(&pool->hdr.c);
812 TC_INVALIDATE_FULL_CHUNK(&pool->hdr.c);
813 free(pool);
814 return;
817 if (pool->hdr.c.pool == next_tc) {
819 * if pool->pool still points to end of
820 * 'tc' (which is stored in the 'next_tc' variable),
821 * we can reclaim the memory of 'tc'.
823 pool->hdr.c.pool = tc;
824 return;
828 * Do nothing. The memory is just "wasted", waiting for the pool
829 * itself to be freed.
833 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
834 void *ptr,
835 const char *location);
838 internal talloc_free call
840 static inline int _talloc_free_internal(void *ptr, const char *location)
842 struct talloc_chunk *tc;
844 if (unlikely(ptr == NULL)) {
845 return -1;
848 /* possibly initialised the talloc fill value */
849 if (unlikely(!talloc_fill.initialised)) {
850 const char *fill = getenv(TALLOC_FILL_ENV);
851 if (fill != NULL) {
852 talloc_fill.enabled = true;
853 talloc_fill.fill_value = strtoul(fill, NULL, 0);
855 talloc_fill.initialised = true;
858 tc = talloc_chunk_from_ptr(ptr);
860 if (unlikely(tc->refs)) {
861 int is_child;
862 /* check if this is a reference from a child or
863 * grandchild back to it's parent or grandparent
865 * in that case we need to remove the reference and
866 * call another instance of talloc_free() on the current
867 * pointer.
869 is_child = talloc_is_parent(tc->refs, ptr);
870 _talloc_free_internal(tc->refs, location);
871 if (is_child) {
872 return _talloc_free_internal(ptr, location);
874 return -1;
877 if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
878 /* we have a free loop - stop looping */
879 return 0;
882 if (unlikely(tc->destructor)) {
883 talloc_destructor_t d = tc->destructor;
884 if (d == (talloc_destructor_t)-1) {
885 return -1;
887 tc->destructor = (talloc_destructor_t)-1;
888 if (d(ptr) == -1) {
889 tc->destructor = d;
890 return -1;
892 tc->destructor = NULL;
895 if (tc->parent) {
896 _TLIST_REMOVE(tc->parent->child, tc);
897 if (tc->parent->child) {
898 tc->parent->child->parent = tc->parent;
900 } else {
901 if (tc->prev) tc->prev->next = tc->next;
902 if (tc->next) tc->next->prev = tc->prev;
903 tc->prev = tc->next = NULL;
906 tc->flags |= TALLOC_FLAG_LOOP;
908 _talloc_free_children_internal(tc, ptr, location);
910 tc->flags |= TALLOC_FLAG_FREE;
913 * If we are part of a memory limited context hierarchy
914 * we need to subtract the memory used from the counters
916 if (tc->limit) {
917 struct talloc_memlimit *l;
919 for (l = tc->limit; l != NULL; l = l->upper) {
920 if (l->cur_size >= tc->size+TC_HDR_SIZE) {
921 l->cur_size -= tc->size+TC_HDR_SIZE;
922 } else {
923 talloc_abort("cur_size memlimit counter not correct!");
924 return 0;
928 if (tc->limit->parent == tc) {
929 free(tc->limit);
932 tc->limit = NULL;
935 /* we mark the freed memory with where we called the free
936 * from. This means on a double free error we can report where
937 * the first free came from
939 tc->name = location;
941 if (tc->flags & TALLOC_FLAG_POOL) {
942 union talloc_pool_chunk *pool = (union talloc_pool_chunk *)tc;
944 if (unlikely(pool->hdr.object_count == 0)) {
945 talloc_abort("Pool object count zero!");
946 return 0;
949 pool->hdr.object_count--;
951 if (likely(pool->hdr.object_count != 0)) {
952 return 0;
955 TC_INVALIDATE_FULL_CHUNK(tc);
956 free(tc);
957 return 0;
960 if (tc->flags & TALLOC_FLAG_POOLMEM) {
961 _talloc_free_poolmem(tc, location);
962 return 0;
965 TC_INVALIDATE_FULL_CHUNK(tc);
966 free(tc);
967 return 0;
970 static size_t _talloc_total_limit_size(const void *ptr,
971 struct talloc_memlimit *old_limit,
972 struct talloc_memlimit *new_limit);
975 move a lump of memory from one talloc context to another return the
976 ptr on success, or NULL if it could not be transferred.
977 passing NULL as ptr will always return NULL with no side effects.
979 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr)
981 struct talloc_chunk *tc, *new_tc;
982 size_t ctx_size = 0;
984 if (unlikely(!ptr)) {
985 return NULL;
988 if (unlikely(new_ctx == NULL)) {
989 new_ctx = null_context;
992 tc = talloc_chunk_from_ptr(ptr);
994 if (tc->limit != NULL) {
996 ctx_size = _talloc_total_limit_size(ptr, NULL, NULL);
998 if (!talloc_memlimit_update(tc->limit->upper, ctx_size, 0)) {
999 talloc_abort("cur_size memlimit counter not correct!");
1000 errno = EINVAL;
1001 return NULL;
1004 if (tc->limit->parent == tc) {
1005 tc->limit->upper = NULL;
1006 } else {
1007 tc->limit = NULL;
1011 if (unlikely(new_ctx == NULL)) {
1012 if (tc->parent) {
1013 _TLIST_REMOVE(tc->parent->child, tc);
1014 if (tc->parent->child) {
1015 tc->parent->child->parent = tc->parent;
1017 } else {
1018 if (tc->prev) tc->prev->next = tc->next;
1019 if (tc->next) tc->next->prev = tc->prev;
1022 tc->parent = tc->next = tc->prev = NULL;
1023 return discard_const_p(void, ptr);
1026 new_tc = talloc_chunk_from_ptr(new_ctx);
1028 if (unlikely(tc == new_tc || tc->parent == new_tc)) {
1029 return discard_const_p(void, ptr);
1032 if (tc->parent) {
1033 _TLIST_REMOVE(tc->parent->child, tc);
1034 if (tc->parent->child) {
1035 tc->parent->child->parent = tc->parent;
1037 } else {
1038 if (tc->prev) tc->prev->next = tc->next;
1039 if (tc->next) tc->next->prev = tc->prev;
1040 tc->prev = tc->next = NULL;
1043 tc->parent = new_tc;
1044 if (new_tc->child) new_tc->child->parent = NULL;
1045 _TLIST_ADD(new_tc->child, tc);
1047 if (tc->limit || new_tc->limit) {
1048 ctx_size = _talloc_total_limit_size(ptr, tc->limit,
1049 new_tc->limit);
1052 if (new_tc->limit) {
1053 struct talloc_memlimit *l;
1055 for (l = new_tc->limit; l != NULL; l = l->upper) {
1056 l->cur_size += ctx_size;
1060 return discard_const_p(void, ptr);
1064 move a lump of memory from one talloc context to another return the
1065 ptr on success, or NULL if it could not be transferred.
1066 passing NULL as ptr will always return NULL with no side effects.
1068 _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
1070 struct talloc_chunk *tc;
1072 if (unlikely(ptr == NULL)) {
1073 return NULL;
1076 tc = talloc_chunk_from_ptr(ptr);
1078 if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
1079 struct talloc_reference_handle *h;
1081 talloc_log("WARNING: talloc_steal with references at %s\n",
1082 location);
1084 for (h=tc->refs; h; h=h->next) {
1085 talloc_log("\treference at %s\n",
1086 h->location);
1090 #if 0
1091 /* this test is probably too expensive to have on in the
1092 normal build, but it useful for debugging */
1093 if (talloc_is_parent(new_ctx, ptr)) {
1094 talloc_log("WARNING: stealing into talloc child at %s\n", location);
1096 #endif
1098 return _talloc_steal_internal(new_ctx, ptr);
1102 this is like a talloc_steal(), but you must supply the old
1103 parent. This resolves the ambiguity in a talloc_steal() which is
1104 called on a context that has more than one parent (via references)
1106 The old parent can be either a reference or a parent
1108 _PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
1110 struct talloc_chunk *tc;
1111 struct talloc_reference_handle *h;
1113 if (unlikely(ptr == NULL)) {
1114 return NULL;
1117 if (old_parent == talloc_parent(ptr)) {
1118 return _talloc_steal_internal(new_parent, ptr);
1121 tc = talloc_chunk_from_ptr(ptr);
1122 for (h=tc->refs;h;h=h->next) {
1123 if (talloc_parent(h) == old_parent) {
1124 if (_talloc_steal_internal(new_parent, h) != h) {
1125 return NULL;
1127 return discard_const_p(void, ptr);
1131 /* it wasn't a parent */
1132 return NULL;
1136 remove a secondary reference to a pointer. This undo's what
1137 talloc_reference() has done. The context and pointer arguments
1138 must match those given to a talloc_reference()
1140 static inline int talloc_unreference(const void *context, const void *ptr)
1142 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1143 struct talloc_reference_handle *h;
1145 if (unlikely(context == NULL)) {
1146 context = null_context;
1149 for (h=tc->refs;h;h=h->next) {
1150 struct talloc_chunk *p = talloc_parent_chunk(h);
1151 if (p == NULL) {
1152 if (context == NULL) break;
1153 } else if (TC_PTR_FROM_CHUNK(p) == context) {
1154 break;
1157 if (h == NULL) {
1158 return -1;
1161 return _talloc_free_internal(h, __location__);
1165 remove a specific parent context from a pointer. This is a more
1166 controlled variant of talloc_free()
1168 _PUBLIC_ int talloc_unlink(const void *context, void *ptr)
1170 struct talloc_chunk *tc_p, *new_p, *tc_c;
1171 void *new_parent;
1173 if (ptr == NULL) {
1174 return -1;
1177 if (context == NULL) {
1178 context = null_context;
1181 if (talloc_unreference(context, ptr) == 0) {
1182 return 0;
1185 if (context != NULL) {
1186 tc_c = talloc_chunk_from_ptr(context);
1187 } else {
1188 tc_c = NULL;
1190 if (tc_c != talloc_parent_chunk(ptr)) {
1191 return -1;
1194 tc_p = talloc_chunk_from_ptr(ptr);
1196 if (tc_p->refs == NULL) {
1197 return _talloc_free_internal(ptr, __location__);
1200 new_p = talloc_parent_chunk(tc_p->refs);
1201 if (new_p) {
1202 new_parent = TC_PTR_FROM_CHUNK(new_p);
1203 } else {
1204 new_parent = NULL;
1207 if (talloc_unreference(new_parent, ptr) != 0) {
1208 return -1;
1211 _talloc_steal_internal(new_parent, ptr);
1213 return 0;
1217 add a name to an existing pointer - va_list version
1219 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1221 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
1223 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1224 tc->name = talloc_vasprintf(ptr, fmt, ap);
1225 if (likely(tc->name)) {
1226 _talloc_set_name_const(tc->name, ".name");
1228 return tc->name;
1232 add a name to an existing pointer
1234 _PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
1236 const char *name;
1237 va_list ap;
1238 va_start(ap, fmt);
1239 name = talloc_set_name_v(ptr, fmt, ap);
1240 va_end(ap);
1241 return name;
1246 create a named talloc pointer. Any talloc pointer can be named, and
1247 talloc_named() operates just like talloc() except that it allows you
1248 to name the pointer.
1250 _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
1252 va_list ap;
1253 void *ptr;
1254 const char *name;
1256 ptr = __talloc(context, size);
1257 if (unlikely(ptr == NULL)) return NULL;
1259 va_start(ap, fmt);
1260 name = talloc_set_name_v(ptr, fmt, ap);
1261 va_end(ap);
1263 if (unlikely(name == NULL)) {
1264 _talloc_free_internal(ptr, __location__);
1265 return NULL;
1268 return ptr;
1272 return the name of a talloc ptr, or "UNNAMED"
1274 _PUBLIC_ const char *talloc_get_name(const void *ptr)
1276 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1277 if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
1278 return ".reference";
1280 if (likely(tc->name)) {
1281 return tc->name;
1283 return "UNNAMED";
1288 check if a pointer has the given name. If it does, return the pointer,
1289 otherwise return NULL
1291 _PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
1293 const char *pname;
1294 if (unlikely(ptr == NULL)) return NULL;
1295 pname = talloc_get_name(ptr);
1296 if (likely(pname == name || strcmp(pname, name) == 0)) {
1297 return discard_const_p(void, ptr);
1299 return NULL;
1302 static void talloc_abort_type_mismatch(const char *location,
1303 const char *name,
1304 const char *expected)
1306 const char *reason;
1308 reason = talloc_asprintf(NULL,
1309 "%s: Type mismatch: name[%s] expected[%s]",
1310 location,
1311 name?name:"NULL",
1312 expected);
1313 if (!reason) {
1314 reason = "Type mismatch";
1317 talloc_abort(reason);
1320 _PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
1322 const char *pname;
1324 if (unlikely(ptr == NULL)) {
1325 talloc_abort_type_mismatch(location, NULL, name);
1326 return NULL;
1329 pname = talloc_get_name(ptr);
1330 if (likely(pname == name || strcmp(pname, name) == 0)) {
1331 return discard_const_p(void, ptr);
1334 talloc_abort_type_mismatch(location, pname, name);
1335 return NULL;
1339 this is for compatibility with older versions of talloc
1341 _PUBLIC_ void *talloc_init(const char *fmt, ...)
1343 va_list ap;
1344 void *ptr;
1345 const char *name;
1347 ptr = __talloc(NULL, 0);
1348 if (unlikely(ptr == NULL)) return NULL;
1350 va_start(ap, fmt);
1351 name = talloc_set_name_v(ptr, fmt, ap);
1352 va_end(ap);
1354 if (unlikely(name == NULL)) {
1355 _talloc_free_internal(ptr, __location__);
1356 return NULL;
1359 return ptr;
1362 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
1363 void *ptr,
1364 const char *location)
1366 while (tc->child) {
1367 /* we need to work out who will own an abandoned child
1368 if it cannot be freed. In priority order, the first
1369 choice is owner of any remaining reference to this
1370 pointer, the second choice is our parent, and the
1371 final choice is the null context. */
1372 void *child = TC_PTR_FROM_CHUNK(tc->child);
1373 const void *new_parent = null_context;
1374 if (unlikely(tc->child->refs)) {
1375 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1376 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1378 if (unlikely(_talloc_free_internal(child, location) == -1)) {
1379 if (new_parent == null_context) {
1380 struct talloc_chunk *p = talloc_parent_chunk(ptr);
1381 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1383 _talloc_steal_internal(new_parent, child);
1389 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1390 should probably not be used in new code. It's in here to keep the talloc
1391 code consistent across Samba 3 and 4.
1393 _PUBLIC_ void talloc_free_children(void *ptr)
1395 struct talloc_chunk *tc_name = NULL;
1396 struct talloc_chunk *tc;
1398 if (unlikely(ptr == NULL)) {
1399 return;
1402 tc = talloc_chunk_from_ptr(ptr);
1404 /* we do not want to free the context name if it is a child .. */
1405 if (likely(tc->child)) {
1406 for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
1407 if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
1409 if (tc_name) {
1410 _TLIST_REMOVE(tc->child, tc_name);
1411 if (tc->child) {
1412 tc->child->parent = tc;
1417 _talloc_free_children_internal(tc, ptr, __location__);
1419 /* .. so we put it back after all other children have been freed */
1420 if (tc_name) {
1421 if (tc->child) {
1422 tc->child->parent = NULL;
1424 tc_name->parent = tc;
1425 _TLIST_ADD(tc->child, tc_name);
1430 Allocate a bit of memory as a child of an existing pointer
1432 _PUBLIC_ void *_talloc(const void *context, size_t size)
1434 return __talloc(context, size);
1438 externally callable talloc_set_name_const()
1440 _PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
1442 _talloc_set_name_const(ptr, name);
1446 create a named talloc pointer. Any talloc pointer can be named, and
1447 talloc_named() operates just like talloc() except that it allows you
1448 to name the pointer.
1450 _PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
1452 return _talloc_named_const(context, size, name);
1456 free a talloc pointer. This also frees all child pointers of this
1457 pointer recursively
1459 return 0 if the memory is actually freed, otherwise -1. The memory
1460 will not be freed if the ref_count is > 1 or the destructor (if
1461 any) returns non-zero
1463 _PUBLIC_ int _talloc_free(void *ptr, const char *location)
1465 struct talloc_chunk *tc;
1467 if (unlikely(ptr == NULL)) {
1468 return -1;
1471 tc = talloc_chunk_from_ptr(ptr);
1473 if (unlikely(tc->refs != NULL)) {
1474 struct talloc_reference_handle *h;
1476 if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
1477 /* in this case we do know which parent should
1478 get this pointer, as there is really only
1479 one parent */
1480 return talloc_unlink(null_context, ptr);
1483 talloc_log("ERROR: talloc_free with references at %s\n",
1484 location);
1486 for (h=tc->refs; h; h=h->next) {
1487 talloc_log("\treference at %s\n",
1488 h->location);
1490 return -1;
1493 return _talloc_free_internal(ptr, location);
1499 A talloc version of realloc. The context argument is only used if
1500 ptr is NULL
1502 _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
1504 struct talloc_chunk *tc;
1505 void *new_ptr;
1506 bool malloced = false;
1507 union talloc_pool_chunk *pool_tc = NULL;
1509 /* size zero is equivalent to free() */
1510 if (unlikely(size == 0)) {
1511 talloc_unlink(context, ptr);
1512 return NULL;
1515 if (unlikely(size >= MAX_TALLOC_SIZE)) {
1516 return NULL;
1519 /* realloc(NULL) is equivalent to malloc() */
1520 if (ptr == NULL) {
1521 return _talloc_named_const(context, size, name);
1524 tc = talloc_chunk_from_ptr(ptr);
1526 /* don't allow realloc on referenced pointers */
1527 if (unlikely(tc->refs)) {
1528 return NULL;
1531 /* don't let anybody try to realloc a talloc_pool */
1532 if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
1533 return NULL;
1536 if (tc->limit && (size - tc->size > 0)) {
1537 if (!talloc_memlimit_check(tc->limit, (size - tc->size))) {
1538 errno = ENOMEM;
1539 return NULL;
1543 /* handle realloc inside a talloc_pool */
1544 if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
1545 pool_tc = (union talloc_pool_chunk *)tc->pool;
1548 #if (ALWAYS_REALLOC == 0)
1549 /* don't shrink if we have less than 1k to gain */
1550 if (size < tc->size && tc->limit == NULL) {
1551 if (pool_tc) {
1552 void *next_tc = tc_next_chunk(tc);
1553 TC_INVALIDATE_SHRINK_CHUNK(tc, size);
1554 tc->size = size;
1555 if (next_tc == pool_tc->hdr.c.pool) {
1556 /* note: tc->size has changed, so this works */
1557 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1559 return ptr;
1560 } else if ((tc->size - size) < 1024) {
1562 * if we call TC_INVALIDATE_SHRINK_CHUNK() here
1563 * we would need to call TC_UNDEFINE_GROW_CHUNK()
1564 * after each realloc call, which slows down
1565 * testing a lot :-(.
1567 * That is why we only mark memory as undefined here.
1569 TC_UNDEFINE_SHRINK_CHUNK(tc, size);
1571 /* do not shrink if we have less than 1k to gain */
1572 tc->size = size;
1573 return ptr;
1575 } else if (tc->size == size) {
1577 * do not change the pointer if it is exactly
1578 * the same size.
1580 return ptr;
1582 #endif
1584 /* by resetting magic we catch users of the old memory */
1585 tc->flags |= TALLOC_FLAG_FREE;
1587 #if ALWAYS_REALLOC
1588 if (pool_tc) {
1589 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1590 pool_tc->hdr.object_count--;
1592 if (new_ptr == NULL) {
1593 new_ptr = malloc(TC_HDR_SIZE+size);
1594 malloced = true;
1597 if (new_ptr) {
1598 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1599 TC_INVALIDATE_FULL_CHUNK(tc);
1601 } else {
1602 new_ptr = malloc(size + TC_HDR_SIZE);
1603 if (new_ptr) {
1604 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1605 free(tc);
1608 #else
1609 if (pool_tc) {
1610 void *next_tc = tc_next_chunk(tc);
1611 size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size);
1612 size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
1613 size_t space_needed;
1614 size_t space_left;
1615 unsigned int chunk_count = pool_tc->hdr.object_count;
1617 if (!(pool_tc->hdr.c.flags & TALLOC_FLAG_FREE)) {
1618 chunk_count -= 1;
1621 if (chunk_count == 1) {
1623 * optimize for the case where 'tc' is the only
1624 * chunk in the pool.
1626 char *start = tc_pool_first_chunk(pool_tc);
1627 space_needed = new_chunk_size;
1628 space_left = (char *)tc_pool_end(pool_tc) - start;
1630 if (space_left >= space_needed) {
1631 size_t old_used = TC_HDR_SIZE + tc->size;
1632 size_t new_used = TC_HDR_SIZE + size;
1633 new_ptr = start;
1634 memmove(new_ptr, tc, old_used);
1636 tc = (struct talloc_chunk *)new_ptr;
1637 TC_UNDEFINE_GROW_CHUNK(tc, size);
1640 * first we do not align the pool pointer
1641 * because we want to invalidate the padding
1642 * too.
1644 pool_tc->hdr.c.pool = new_used + (char *)new_ptr;
1645 tc_invalidate_pool(pool_tc);
1647 /* now the aligned pointer */
1648 pool_tc->hdr.c.pool = new_chunk_size + (char *)new_ptr;
1649 goto got_new_ptr;
1652 next_tc = NULL;
1655 if (new_chunk_size == old_chunk_size) {
1656 TC_UNDEFINE_GROW_CHUNK(tc, size);
1657 tc->flags &= ~TALLOC_FLAG_FREE;
1658 if (!talloc_memlimit_update(tc->limit,
1659 tc->size, size)) {
1660 talloc_abort("cur_size memlimit counter not"
1661 " correct!");
1662 errno = EINVAL;
1663 return NULL;
1666 tc->size = size;
1667 return ptr;
1670 if (next_tc == pool_tc->hdr.c.pool) {
1672 * optimize for the case where 'tc' is the last
1673 * chunk in the pool.
1675 space_needed = new_chunk_size - old_chunk_size;
1676 space_left = tc_pool_space_left(pool_tc);
1678 if (space_left >= space_needed) {
1679 TC_UNDEFINE_GROW_CHUNK(tc, size);
1680 tc->flags &= ~TALLOC_FLAG_FREE;
1681 if (!talloc_memlimit_update(tc->limit,
1682 tc->size, size)) {
1683 talloc_abort("cur_size memlimit "
1684 "counter not correct!");
1685 errno = EINVAL;
1686 return NULL;
1688 tc->size = size;
1689 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1690 return ptr;
1694 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1696 if (new_ptr == NULL) {
1697 new_ptr = malloc(TC_HDR_SIZE+size);
1698 malloced = true;
1701 if (new_ptr) {
1702 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1704 _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
1707 else {
1708 new_ptr = realloc(tc, size + TC_HDR_SIZE);
1710 got_new_ptr:
1711 #endif
1712 if (unlikely(!new_ptr)) {
1713 tc->flags &= ~TALLOC_FLAG_FREE;
1714 return NULL;
1717 tc = (struct talloc_chunk *)new_ptr;
1718 tc->flags &= ~TALLOC_FLAG_FREE;
1719 if (malloced) {
1720 tc->flags &= ~TALLOC_FLAG_POOLMEM;
1722 if (tc->parent) {
1723 tc->parent->child = tc;
1725 if (tc->child) {
1726 tc->child->parent = tc;
1729 if (tc->prev) {
1730 tc->prev->next = tc;
1732 if (tc->next) {
1733 tc->next->prev = tc;
1736 if (!talloc_memlimit_update(tc->limit, tc->size, size)) {
1737 talloc_abort("cur_size memlimit counter not correct!");
1738 errno = EINVAL;
1739 return NULL;
1741 tc->size = size;
1742 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
1744 return TC_PTR_FROM_CHUNK(tc);
1748 a wrapper around talloc_steal() for situations where you are moving a pointer
1749 between two structures, and want the old pointer to be set to NULL
1751 _PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
1753 const void **pptr = discard_const_p(const void *,_pptr);
1754 void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
1755 (*pptr) = NULL;
1756 return ret;
1759 enum talloc_mem_count_type {
1760 TOTAL_MEM_SIZE,
1761 TOTAL_MEM_BLOCKS,
1762 TOTAL_MEM_LIMIT,
1765 static size_t _talloc_total_mem_internal(const void *ptr,
1766 enum talloc_mem_count_type type,
1767 struct talloc_memlimit *old_limit,
1768 struct talloc_memlimit *new_limit)
1770 size_t total = 0;
1771 struct talloc_chunk *c, *tc;
1773 if (ptr == NULL) {
1774 ptr = null_context;
1776 if (ptr == NULL) {
1777 return 0;
1780 tc = talloc_chunk_from_ptr(ptr);
1782 if (old_limit || new_limit) {
1783 if (tc->limit && tc->limit->upper == old_limit) {
1784 tc->limit->upper = new_limit;
1788 /* optimize in the memlimits case */
1789 if (type == TOTAL_MEM_LIMIT &&
1790 tc->limit != NULL &&
1791 tc->limit != old_limit &&
1792 tc->limit->parent == tc) {
1793 return tc->limit->cur_size;
1796 if (tc->flags & TALLOC_FLAG_LOOP) {
1797 return 0;
1800 tc->flags |= TALLOC_FLAG_LOOP;
1802 if (old_limit || new_limit) {
1803 if (old_limit == tc->limit) {
1804 tc->limit = new_limit;
1808 switch (type) {
1809 case TOTAL_MEM_SIZE:
1810 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1811 total = tc->size;
1813 break;
1814 case TOTAL_MEM_BLOCKS:
1815 total++;
1816 break;
1817 case TOTAL_MEM_LIMIT:
1818 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1820 * Don't count memory allocated from a pool
1821 * when calculating limits. Only count the
1822 * pool itself.
1824 if (!(tc->flags & TALLOC_FLAG_POOLMEM)) {
1825 total = tc->size + TC_HDR_SIZE;
1828 break;
1830 for (c = tc->child; c; c = c->next) {
1831 total += _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c), type,
1832 old_limit, new_limit);
1835 tc->flags &= ~TALLOC_FLAG_LOOP;
1837 return total;
1841 return the total size of a talloc pool (subtree)
1843 _PUBLIC_ size_t talloc_total_size(const void *ptr)
1845 return _talloc_total_mem_internal(ptr, TOTAL_MEM_SIZE, NULL, NULL);
1849 return the total number of blocks in a talloc pool (subtree)
1851 _PUBLIC_ size_t talloc_total_blocks(const void *ptr)
1853 return _talloc_total_mem_internal(ptr, TOTAL_MEM_BLOCKS, NULL, NULL);
1857 return the number of external references to a pointer
1859 _PUBLIC_ size_t talloc_reference_count(const void *ptr)
1861 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1862 struct talloc_reference_handle *h;
1863 size_t ret = 0;
1865 for (h=tc->refs;h;h=h->next) {
1866 ret++;
1868 return ret;
1872 report on memory usage by all children of a pointer, giving a full tree view
1874 _PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1875 void (*callback)(const void *ptr,
1876 int depth, int max_depth,
1877 int is_ref,
1878 void *private_data),
1879 void *private_data)
1881 struct talloc_chunk *c, *tc;
1883 if (ptr == NULL) {
1884 ptr = null_context;
1886 if (ptr == NULL) return;
1888 tc = talloc_chunk_from_ptr(ptr);
1890 if (tc->flags & TALLOC_FLAG_LOOP) {
1891 return;
1894 callback(ptr, depth, max_depth, 0, private_data);
1896 if (max_depth >= 0 && depth >= max_depth) {
1897 return;
1900 tc->flags |= TALLOC_FLAG_LOOP;
1901 for (c=tc->child;c;c=c->next) {
1902 if (c->name == TALLOC_MAGIC_REFERENCE) {
1903 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1904 callback(h->ptr, depth + 1, max_depth, 1, private_data);
1905 } else {
1906 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1909 tc->flags &= ~TALLOC_FLAG_LOOP;
1912 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1914 const char *name = talloc_get_name(ptr);
1915 struct talloc_chunk *tc;
1916 FILE *f = (FILE *)_f;
1918 if (is_ref) {
1919 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1920 return;
1923 tc = talloc_chunk_from_ptr(ptr);
1924 if (tc->limit && tc->limit->parent == tc) {
1925 fprintf(f, "%*s%-30s is a memlimit context"
1926 " (max_size = %lu bytes, cur_size = %lu bytes)\n",
1927 depth*4, "",
1928 name,
1929 (unsigned long)tc->limit->max_size,
1930 (unsigned long)tc->limit->cur_size);
1933 if (depth == 0) {
1934 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1935 (max_depth < 0 ? "full " :""), name,
1936 (unsigned long)talloc_total_size(ptr),
1937 (unsigned long)talloc_total_blocks(ptr));
1938 return;
1941 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1942 depth*4, "",
1943 name,
1944 (unsigned long)talloc_total_size(ptr),
1945 (unsigned long)talloc_total_blocks(ptr),
1946 (int)talloc_reference_count(ptr), ptr);
1948 #if 0
1949 fprintf(f, "content: ");
1950 if (talloc_total_size(ptr)) {
1951 int tot = talloc_total_size(ptr);
1952 int i;
1954 for (i = 0; i < tot; i++) {
1955 if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1956 fprintf(f, "%c", ((char *)ptr)[i]);
1957 } else {
1958 fprintf(f, "~%02x", ((char *)ptr)[i]);
1962 fprintf(f, "\n");
1963 #endif
1967 report on memory usage by all children of a pointer, giving a full tree view
1969 _PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1971 if (f) {
1972 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1973 fflush(f);
1978 report on memory usage by all children of a pointer, giving a full tree view
1980 _PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
1982 talloc_report_depth_file(ptr, 0, -1, f);
1986 report on memory usage by all children of a pointer
1988 _PUBLIC_ void talloc_report(const void *ptr, FILE *f)
1990 talloc_report_depth_file(ptr, 0, 1, f);
1994 report on any memory hanging off the null context
1996 static void talloc_report_null(void)
1998 if (talloc_total_size(null_context) != 0) {
1999 talloc_report(null_context, stderr);
2004 report on any memory hanging off the null context
2006 static void talloc_report_null_full(void)
2008 if (talloc_total_size(null_context) != 0) {
2009 talloc_report_full(null_context, stderr);
2014 enable tracking of the NULL context
2016 _PUBLIC_ void talloc_enable_null_tracking(void)
2018 if (null_context == NULL) {
2019 null_context = _talloc_named_const(NULL, 0, "null_context");
2020 if (autofree_context != NULL) {
2021 talloc_reparent(NULL, null_context, autofree_context);
2027 enable tracking of the NULL context, not moving the autofree context
2028 into the NULL context. This is needed for the talloc testsuite
2030 _PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
2032 if (null_context == NULL) {
2033 null_context = _talloc_named_const(NULL, 0, "null_context");
2038 disable tracking of the NULL context
2040 _PUBLIC_ void talloc_disable_null_tracking(void)
2042 if (null_context != NULL) {
2043 /* we have to move any children onto the real NULL
2044 context */
2045 struct talloc_chunk *tc, *tc2;
2046 tc = talloc_chunk_from_ptr(null_context);
2047 for (tc2 = tc->child; tc2; tc2=tc2->next) {
2048 if (tc2->parent == tc) tc2->parent = NULL;
2049 if (tc2->prev == tc) tc2->prev = NULL;
2051 for (tc2 = tc->next; tc2; tc2=tc2->next) {
2052 if (tc2->parent == tc) tc2->parent = NULL;
2053 if (tc2->prev == tc) tc2->prev = NULL;
2055 tc->child = NULL;
2056 tc->next = NULL;
2058 talloc_free(null_context);
2059 null_context = NULL;
2063 enable leak reporting on exit
2065 _PUBLIC_ void talloc_enable_leak_report(void)
2067 talloc_enable_null_tracking();
2068 atexit(talloc_report_null);
2072 enable full leak reporting on exit
2074 _PUBLIC_ void talloc_enable_leak_report_full(void)
2076 talloc_enable_null_tracking();
2077 atexit(talloc_report_null_full);
2081 talloc and zero memory.
2083 _PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
2085 void *p = _talloc_named_const(ctx, size, name);
2087 if (p) {
2088 memset(p, '\0', size);
2091 return p;
2095 memdup with a talloc.
2097 _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
2099 void *newp = _talloc_named_const(t, size, name);
2101 if (likely(newp)) {
2102 memcpy(newp, p, size);
2105 return newp;
2108 static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
2110 char *ret;
2112 ret = (char *)__talloc(t, len + 1);
2113 if (unlikely(!ret)) return NULL;
2115 memcpy(ret, p, len);
2116 ret[len] = 0;
2118 _talloc_set_name_const(ret, ret);
2119 return ret;
2123 strdup with a talloc
2125 _PUBLIC_ char *talloc_strdup(const void *t, const char *p)
2127 if (unlikely(!p)) return NULL;
2128 return __talloc_strlendup(t, p, strlen(p));
2132 strndup with a talloc
2134 _PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
2136 if (unlikely(!p)) return NULL;
2137 return __talloc_strlendup(t, p, strnlen(p, n));
2140 static inline char *__talloc_strlendup_append(char *s, size_t slen,
2141 const char *a, size_t alen)
2143 char *ret;
2145 ret = talloc_realloc(NULL, s, char, slen + alen + 1);
2146 if (unlikely(!ret)) return NULL;
2148 /* append the string and the trailing \0 */
2149 memcpy(&ret[slen], a, alen);
2150 ret[slen+alen] = 0;
2152 _talloc_set_name_const(ret, ret);
2153 return ret;
2157 * Appends at the end of the string.
2159 _PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
2161 if (unlikely(!s)) {
2162 return talloc_strdup(NULL, a);
2165 if (unlikely(!a)) {
2166 return s;
2169 return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
2173 * Appends at the end of the talloc'ed buffer,
2174 * not the end of the string.
2176 _PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
2178 size_t slen;
2180 if (unlikely(!s)) {
2181 return talloc_strdup(NULL, a);
2184 if (unlikely(!a)) {
2185 return s;
2188 slen = talloc_get_size(s);
2189 if (likely(slen > 0)) {
2190 slen--;
2193 return __talloc_strlendup_append(s, slen, a, strlen(a));
2197 * Appends at the end of the string.
2199 _PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
2201 if (unlikely(!s)) {
2202 return talloc_strndup(NULL, a, n);
2205 if (unlikely(!a)) {
2206 return s;
2209 return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
2213 * Appends at the end of the talloc'ed buffer,
2214 * not the end of the string.
2216 _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
2218 size_t slen;
2220 if (unlikely(!s)) {
2221 return talloc_strndup(NULL, a, n);
2224 if (unlikely(!a)) {
2225 return s;
2228 slen = talloc_get_size(s);
2229 if (likely(slen > 0)) {
2230 slen--;
2233 return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
2236 #ifndef HAVE_VA_COPY
2237 #ifdef HAVE___VA_COPY
2238 #define va_copy(dest, src) __va_copy(dest, src)
2239 #else
2240 #define va_copy(dest, src) (dest) = (src)
2241 #endif
2242 #endif
2244 _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
2246 int len;
2247 char *ret;
2248 va_list ap2;
2249 char c;
2251 /* this call looks strange, but it makes it work on older solaris boxes */
2252 va_copy(ap2, ap);
2253 len = vsnprintf(&c, 1, fmt, ap2);
2254 va_end(ap2);
2255 if (unlikely(len < 0)) {
2256 return NULL;
2259 ret = (char *)__talloc(t, len+1);
2260 if (unlikely(!ret)) return NULL;
2262 va_copy(ap2, ap);
2263 vsnprintf(ret, len+1, fmt, ap2);
2264 va_end(ap2);
2266 _talloc_set_name_const(ret, ret);
2267 return ret;
2272 Perform string formatting, and return a pointer to newly allocated
2273 memory holding the result, inside a memory pool.
2275 _PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
2277 va_list ap;
2278 char *ret;
2280 va_start(ap, fmt);
2281 ret = talloc_vasprintf(t, fmt, ap);
2282 va_end(ap);
2283 return ret;
2286 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2287 const char *fmt, va_list ap)
2288 PRINTF_ATTRIBUTE(3,0);
2290 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2291 const char *fmt, va_list ap)
2293 ssize_t alen;
2294 va_list ap2;
2295 char c;
2297 va_copy(ap2, ap);
2298 alen = vsnprintf(&c, 1, fmt, ap2);
2299 va_end(ap2);
2301 if (alen <= 0) {
2302 /* Either the vsnprintf failed or the format resulted in
2303 * no characters being formatted. In the former case, we
2304 * ought to return NULL, in the latter we ought to return
2305 * the original string. Most current callers of this
2306 * function expect it to never return NULL.
2308 return s;
2311 s = talloc_realloc(NULL, s, char, slen + alen + 1);
2312 if (!s) return NULL;
2314 va_copy(ap2, ap);
2315 vsnprintf(s + slen, alen + 1, fmt, ap2);
2316 va_end(ap2);
2318 _talloc_set_name_const(s, s);
2319 return s;
2323 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2324 * and return @p s, which may have moved. Good for gradually
2325 * accumulating output into a string buffer. Appends at the end
2326 * of the string.
2328 _PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
2330 if (unlikely(!s)) {
2331 return talloc_vasprintf(NULL, fmt, ap);
2334 return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
2338 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2339 * and return @p s, which may have moved. Always appends at the
2340 * end of the talloc'ed buffer, not the end of the string.
2342 _PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
2344 size_t slen;
2346 if (unlikely(!s)) {
2347 return talloc_vasprintf(NULL, fmt, ap);
2350 slen = talloc_get_size(s);
2351 if (likely(slen > 0)) {
2352 slen--;
2355 return __talloc_vaslenprintf_append(s, slen, fmt, ap);
2359 Realloc @p s to append the formatted result of @p fmt and return @p
2360 s, which may have moved. Good for gradually accumulating output
2361 into a string buffer.
2363 _PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
2365 va_list ap;
2367 va_start(ap, fmt);
2368 s = talloc_vasprintf_append(s, fmt, ap);
2369 va_end(ap);
2370 return s;
2374 Realloc @p s to append the formatted result of @p fmt and return @p
2375 s, which may have moved. Good for gradually accumulating output
2376 into a buffer.
2378 _PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
2380 va_list ap;
2382 va_start(ap, fmt);
2383 s = talloc_vasprintf_append_buffer(s, fmt, ap);
2384 va_end(ap);
2385 return s;
2389 alloc an array, checking for integer overflow in the array size
2391 _PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2393 if (count >= MAX_TALLOC_SIZE/el_size) {
2394 return NULL;
2396 return _talloc_named_const(ctx, el_size * count, name);
2400 alloc an zero array, checking for integer overflow in the array size
2402 _PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2404 if (count >= MAX_TALLOC_SIZE/el_size) {
2405 return NULL;
2407 return _talloc_zero(ctx, el_size * count, name);
2411 realloc an array, checking for integer overflow in the array size
2413 _PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
2415 if (count >= MAX_TALLOC_SIZE/el_size) {
2416 return NULL;
2418 return _talloc_realloc(ctx, ptr, el_size * count, name);
2422 a function version of talloc_realloc(), so it can be passed as a function pointer
2423 to libraries that want a realloc function (a realloc function encapsulates
2424 all the basic capabilities of an allocation library, which is why this is useful)
2426 _PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
2428 return _talloc_realloc(context, ptr, size, NULL);
2432 static int talloc_autofree_destructor(void *ptr)
2434 autofree_context = NULL;
2435 return 0;
2438 static void talloc_autofree(void)
2440 talloc_free(autofree_context);
2444 return a context which will be auto-freed on exit
2445 this is useful for reducing the noise in leak reports
2447 _PUBLIC_ void *talloc_autofree_context(void)
2449 if (autofree_context == NULL) {
2450 autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
2451 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
2452 atexit(talloc_autofree);
2454 return autofree_context;
2457 _PUBLIC_ size_t talloc_get_size(const void *context)
2459 struct talloc_chunk *tc;
2461 if (context == NULL) {
2462 context = null_context;
2464 if (context == NULL) {
2465 return 0;
2468 tc = talloc_chunk_from_ptr(context);
2470 return tc->size;
2474 find a parent of this context that has the given name, if any
2476 _PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
2478 struct talloc_chunk *tc;
2480 if (context == NULL) {
2481 return NULL;
2484 tc = talloc_chunk_from_ptr(context);
2485 while (tc) {
2486 if (tc->name && strcmp(tc->name, name) == 0) {
2487 return TC_PTR_FROM_CHUNK(tc);
2489 while (tc && tc->prev) tc = tc->prev;
2490 if (tc) {
2491 tc = tc->parent;
2494 return NULL;
2498 show the parentage of a context
2500 _PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
2502 struct talloc_chunk *tc;
2504 if (context == NULL) {
2505 fprintf(file, "talloc no parents for NULL\n");
2506 return;
2509 tc = talloc_chunk_from_ptr(context);
2510 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
2511 while (tc) {
2512 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
2513 while (tc && tc->prev) tc = tc->prev;
2514 if (tc) {
2515 tc = tc->parent;
2518 fflush(file);
2522 return 1 if ptr is a parent of context
2524 static int _talloc_is_parent(const void *context, const void *ptr, int depth)
2526 struct talloc_chunk *tc;
2528 if (context == NULL) {
2529 return 0;
2532 tc = talloc_chunk_from_ptr(context);
2533 while (tc && depth > 0) {
2534 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
2535 while (tc && tc->prev) tc = tc->prev;
2536 if (tc) {
2537 tc = tc->parent;
2538 depth--;
2541 return 0;
2545 return 1 if ptr is a parent of context
2547 _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
2549 return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
2553 return the total size of memory used by this context and all children
2555 static size_t _talloc_total_limit_size(const void *ptr,
2556 struct talloc_memlimit *old_limit,
2557 struct talloc_memlimit *new_limit)
2559 return _talloc_total_mem_internal(ptr, TOTAL_MEM_LIMIT,
2560 old_limit, new_limit);
2563 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size)
2565 struct talloc_memlimit *l;
2567 for (l = limit; l != NULL; l = l->upper) {
2568 if (l->max_size != 0 &&
2569 ((l->max_size <= l->cur_size) ||
2570 (l->max_size - l->cur_size < size))) {
2571 return false;
2575 return true;
2579 Update memory limits when freeing a talloc_chunk.
2581 static void talloc_memlimit_update_on_free(struct talloc_chunk *tc)
2583 if (!tc->limit) {
2584 return;
2588 * Pool entries don't count. Only the pools
2589 * themselves are counted as part of the memory
2590 * limits.
2592 if (tc->flags & TALLOC_FLAG_POOLMEM) {
2593 return;
2597 * If we are part of a memory limited context hierarchy
2598 * we need to subtract the memory used from the counters
2601 talloc_memlimit_shrink(tc->limit, tc->size+TC_HDR_SIZE);
2603 if (tc->limit->parent == tc) {
2604 free(tc->limit);
2607 tc->limit = NULL;
2611 Increase memory limit accounting after a malloc/realloc.
2613 static void talloc_memlimit_grow(struct talloc_memlimit *limit,
2614 size_t size)
2616 struct talloc_memlimit *l;
2618 for (l = limit; l != NULL; l = l->upper) {
2619 size_t new_cur_size = l->cur_size + size;
2620 if (new_cur_size < l->cur_size) {
2621 talloc_abort("logic error in talloc_memlimit_grow\n");
2622 return;
2624 l->cur_size = new_cur_size;
2629 Decrease memory limit accounting after a free/realloc.
2631 static void talloc_memlimit_shrink(struct talloc_memlimit *limit,
2632 size_t size)
2634 struct talloc_memlimit *l;
2636 for (l = limit; l != NULL; l = l->upper) {
2637 if (l->cur_size < size) {
2638 talloc_abort("logic error in talloc_memlimit_shrink\n");
2639 return;
2641 l->cur_size = l->cur_size - size;
2645 static bool talloc_memlimit_update(struct talloc_memlimit *limit,
2646 size_t old_size, size_t new_size)
2648 struct talloc_memlimit *l;
2649 ssize_t d;
2651 if (old_size == 0) {
2652 d = new_size + TC_HDR_SIZE;
2653 } else {
2654 d = new_size - old_size;
2656 for (l = limit; l != NULL; l = l->upper) {
2657 ssize_t new_cur_size = l->cur_size + d;
2658 if (new_cur_size < 0) {
2659 return false;
2661 l->cur_size = new_cur_size;
2664 return true;
2667 _PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size)
2669 struct talloc_chunk *tc = talloc_chunk_from_ptr(ctx);
2670 struct talloc_memlimit *orig_limit;
2671 struct talloc_memlimit *limit = NULL;
2673 if (tc->limit && tc->limit->parent == tc) {
2674 tc->limit->max_size = max_size;
2675 return 0;
2677 orig_limit = tc->limit;
2679 limit = malloc(sizeof(struct talloc_memlimit));
2680 if (limit == NULL) {
2681 return 1;
2683 limit->parent = tc;
2684 limit->max_size = max_size;
2685 limit->cur_size = _talloc_total_limit_size(ctx, tc->limit, limit);
2687 if (orig_limit) {
2688 limit->upper = orig_limit;
2689 } else {
2690 limit->upper = NULL;
2693 return 0;