nss_winbind: add getgroupmembership for FreeBSD
[Samba.git] / lib / talloc / talloc.c
blob76f0aeedfd4209f7d4cf6ac7aca4ec93cbed57e8
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);
242 typedef int (*talloc_destructor_t)(void *);
244 struct talloc_chunk {
245 struct talloc_chunk *next, *prev;
246 struct talloc_chunk *parent, *child;
247 struct talloc_reference_handle *refs;
248 talloc_destructor_t destructor;
249 const char *name;
250 size_t size;
251 unsigned flags;
254 * limit semantics:
255 * if 'limit' is set it means all *new* children of the context will
256 * be limited to a total aggregate size ox max_size for memory
257 * allocations.
258 * cur_size is used to keep track of the current use
260 struct talloc_memlimit *limit;
263 * "pool" has dual use:
265 * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
266 * marks the end of the currently allocated area.
268 * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
269 * is a pointer to the struct talloc_chunk of the pool that it was
270 * allocated from. This way children can quickly find the pool to chew
271 * from.
273 void *pool;
276 /* 16 byte alignment seems to keep everyone happy */
277 #define TC_ALIGN16(s) (((s)+15)&~15)
278 #define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
279 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
281 _PUBLIC_ int talloc_version_major(void)
283 return TALLOC_VERSION_MAJOR;
286 _PUBLIC_ int talloc_version_minor(void)
288 return TALLOC_VERSION_MINOR;
291 static void (*talloc_log_fn)(const char *message);
293 _PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
295 talloc_log_fn = log_fn;
298 static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
299 static void talloc_log(const char *fmt, ...)
301 va_list ap;
302 char *message;
304 if (!talloc_log_fn) {
305 return;
308 va_start(ap, fmt);
309 message = talloc_vasprintf(NULL, fmt, ap);
310 va_end(ap);
312 talloc_log_fn(message);
313 talloc_free(message);
316 static void talloc_log_stderr(const char *message)
318 fprintf(stderr, "%s", message);
321 _PUBLIC_ void talloc_set_log_stderr(void)
323 talloc_set_log_fn(talloc_log_stderr);
326 static void (*talloc_abort_fn)(const char *reason);
328 _PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
330 talloc_abort_fn = abort_fn;
333 static void talloc_abort(const char *reason)
335 talloc_log("%s\n", reason);
337 if (!talloc_abort_fn) {
338 TALLOC_ABORT(reason);
341 talloc_abort_fn(reason);
344 static void talloc_abort_magic(unsigned magic)
346 unsigned striped = magic - TALLOC_MAGIC_BASE;
347 unsigned major = (striped & 0xFFFFF000) >> 12;
348 unsigned minor = (striped & 0x00000FF0) >> 4;
349 talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
350 magic, major, minor,
351 TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR);
352 talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
355 static void talloc_abort_access_after_free(void)
357 talloc_abort("Bad talloc magic value - access after free");
360 static void talloc_abort_unknown_value(void)
362 talloc_abort("Bad talloc magic value - unknown value");
365 /* panic if we get a bad magic value */
366 static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
368 const char *pp = (const char *)ptr;
369 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
370 if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
371 if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) {
372 talloc_abort_magic(tc->flags & (~0xF));
373 return NULL;
376 if (tc->flags & TALLOC_FLAG_FREE) {
377 talloc_log("talloc: access after free error - first free may be at %s\n", tc->name);
378 talloc_abort_access_after_free();
379 return NULL;
380 } else {
381 talloc_abort_unknown_value();
382 return NULL;
385 return tc;
388 /* hook into the front of the list */
389 #define _TLIST_ADD(list, p) \
390 do { \
391 if (!(list)) { \
392 (list) = (p); \
393 (p)->next = (p)->prev = NULL; \
394 } else { \
395 (list)->prev = (p); \
396 (p)->next = (list); \
397 (p)->prev = NULL; \
398 (list) = (p); \
400 } while (0)
402 /* remove an element from a list - element doesn't have to be in list. */
403 #define _TLIST_REMOVE(list, p) \
404 do { \
405 if ((p) == (list)) { \
406 (list) = (p)->next; \
407 if (list) (list)->prev = NULL; \
408 } else { \
409 if ((p)->prev) (p)->prev->next = (p)->next; \
410 if ((p)->next) (p)->next->prev = (p)->prev; \
412 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
413 } while (0)
417 return the parent chunk of a pointer
419 static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
421 struct talloc_chunk *tc;
423 if (unlikely(ptr == NULL)) {
424 return NULL;
427 tc = talloc_chunk_from_ptr(ptr);
428 while (tc->prev) tc=tc->prev;
430 return tc->parent;
433 _PUBLIC_ void *talloc_parent(const void *ptr)
435 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
436 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
440 find parents name
442 _PUBLIC_ const char *talloc_parent_name(const void *ptr)
444 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
445 return tc? tc->name : NULL;
449 A pool carries an in-pool object count count in the first 16 bytes.
450 bytes. This is done to support talloc_steal() to a parent outside of the
451 pool. The count includes the pool itself, so a talloc_free() on a pool will
452 only destroy the pool if the count has dropped to zero. A talloc_free() of a
453 pool member will reduce the count, and eventually also call free(3) on the
454 pool memory.
456 The object count is not put into "struct talloc_chunk" because it is only
457 relevant for talloc pools and the alignment to 16 bytes would increase the
458 memory footprint of each talloc chunk by those 16 bytes.
461 union talloc_pool_chunk {
462 /* This lets object_count nestle into 16-byte padding of talloc_chunk,
463 * on 32-bit platforms. */
464 struct tc_pool_hdr {
465 struct talloc_chunk c;
466 unsigned int object_count;
467 } hdr;
468 /* This makes it always 16 byte aligned. */
469 char pad[TC_ALIGN16(sizeof(struct tc_pool_hdr))];
472 static void *tc_pool_end(union talloc_pool_chunk *pool_tc)
474 return (char *)pool_tc + TC_HDR_SIZE + pool_tc->hdr.c.size;
477 static size_t tc_pool_space_left(union talloc_pool_chunk *pool_tc)
479 return (char *)tc_pool_end(pool_tc) - (char *)pool_tc->hdr.c.pool;
482 static void *tc_pool_first_chunk(union talloc_pool_chunk *pool_tc)
484 return pool_tc + 1;
487 /* If tc is inside a pool, this gives the next neighbour. */
488 static void *tc_next_chunk(struct talloc_chunk *tc)
490 return (char *)tc + TC_ALIGN16(TC_HDR_SIZE + tc->size);
493 /* Mark the whole remaining pool as not accessable */
494 static void tc_invalidate_pool(union talloc_pool_chunk *pool_tc)
496 size_t flen = tc_pool_space_left(pool_tc);
498 if (unlikely(talloc_fill.enabled)) {
499 memset(pool_tc->hdr.c.pool, talloc_fill.fill_value, flen);
502 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
503 VALGRIND_MAKE_MEM_NOACCESS(pool_tc->hdr.c.pool, flen);
504 #endif
508 Allocate from a pool
511 static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
512 size_t size)
514 union talloc_pool_chunk *pool_ctx = NULL;
515 size_t space_left;
516 struct talloc_chunk *result;
517 size_t chunk_size;
519 if (parent == NULL) {
520 return NULL;
523 if (parent->flags & TALLOC_FLAG_POOL) {
524 pool_ctx = (union talloc_pool_chunk *)parent;
526 else if (parent->flags & TALLOC_FLAG_POOLMEM) {
527 pool_ctx = (union talloc_pool_chunk *)parent->pool;
530 if (pool_ctx == NULL) {
531 return NULL;
534 space_left = tc_pool_space_left(pool_ctx);
537 * Align size to 16 bytes
539 chunk_size = TC_ALIGN16(size);
541 if (space_left < chunk_size) {
542 return NULL;
545 result = (struct talloc_chunk *)pool_ctx->hdr.c.pool;
547 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
548 VALGRIND_MAKE_MEM_UNDEFINED(result, size);
549 #endif
551 pool_ctx->hdr.c.pool = (void *)((char *)result + chunk_size);
553 result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
554 result->pool = pool_ctx;
556 pool_ctx->hdr.object_count++;
558 return result;
562 Allocate a bit of memory as a child of an existing pointer
564 static inline void *__talloc(const void *context, size_t size)
566 struct talloc_chunk *tc = NULL;
567 struct talloc_memlimit *limit = NULL;
569 if (unlikely(context == NULL)) {
570 context = null_context;
573 if (unlikely(size >= MAX_TALLOC_SIZE)) {
574 return NULL;
577 if (context != NULL) {
578 struct talloc_chunk *ptc = talloc_chunk_from_ptr(context);
580 if (ptc->limit != NULL) {
581 limit = ptc->limit;
584 if (!talloc_memlimit_check(limit, (TC_HDR_SIZE+size))) {
585 errno = ENOMEM;
586 return NULL;
589 tc = talloc_alloc_pool(ptc, TC_HDR_SIZE+size);
592 if (tc == NULL) {
593 tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
594 if (unlikely(tc == NULL)) return NULL;
595 tc->flags = TALLOC_MAGIC;
596 tc->pool = NULL;
599 if (limit != NULL) {
600 struct talloc_memlimit *l;
602 for (l = limit; l != NULL; l = l->upper) {
603 l->cur_size += TC_HDR_SIZE+size;
607 tc->limit = limit;
608 tc->size = size;
609 tc->destructor = NULL;
610 tc->child = NULL;
611 tc->name = NULL;
612 tc->refs = NULL;
614 if (likely(context)) {
615 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
617 if (parent->child) {
618 parent->child->parent = NULL;
619 tc->next = parent->child;
620 tc->next->prev = tc;
621 } else {
622 tc->next = NULL;
624 tc->parent = parent;
625 tc->prev = NULL;
626 parent->child = tc;
627 } else {
628 tc->next = tc->prev = tc->parent = NULL;
631 return TC_PTR_FROM_CHUNK(tc);
635 * Create a talloc pool
638 _PUBLIC_ void *talloc_pool(const void *context, size_t size)
640 union talloc_pool_chunk *pool_tc;
641 void *result = __talloc(context, sizeof(*pool_tc) - TC_HDR_SIZE + size);
643 if (unlikely(result == NULL)) {
644 return NULL;
647 pool_tc = (union talloc_pool_chunk *)talloc_chunk_from_ptr(result);
648 if (unlikely(pool_tc->hdr.c.flags & TALLOC_FLAG_POOLMEM)) {
649 /* We don't handle this correctly, so fail. */
650 talloc_log("talloc: cannot allocate pool off another pool %s\n",
651 talloc_get_name(context));
652 talloc_free(result);
653 return NULL;
655 pool_tc->hdr.c.flags |= TALLOC_FLAG_POOL;
656 pool_tc->hdr.c.pool = tc_pool_first_chunk(pool_tc);
658 pool_tc->hdr.object_count = 1;
660 tc_invalidate_pool(pool_tc);
662 return result;
666 setup a destructor to be called on free of a pointer
667 the destructor should return 0 on success, or -1 on failure.
668 if the destructor fails then the free is failed, and the memory can
669 be continued to be used
671 _PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
673 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
674 tc->destructor = destructor;
678 increase the reference count on a piece of memory.
680 _PUBLIC_ int talloc_increase_ref_count(const void *ptr)
682 if (unlikely(!talloc_reference(null_context, ptr))) {
683 return -1;
685 return 0;
689 helper for talloc_reference()
691 this is referenced by a function pointer and should not be inline
693 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
695 struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
696 _TLIST_REMOVE(ptr_tc->refs, handle);
697 return 0;
701 more efficient way to add a name to a pointer - the name must point to a
702 true string constant
704 static inline void _talloc_set_name_const(const void *ptr, const char *name)
706 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
707 tc->name = name;
711 internal talloc_named_const()
713 static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
715 void *ptr;
717 ptr = __talloc(context, size);
718 if (unlikely(ptr == NULL)) {
719 return NULL;
722 _talloc_set_name_const(ptr, name);
724 return ptr;
728 make a secondary reference to a pointer, hanging off the given context.
729 the pointer remains valid until both the original caller and this given
730 context are freed.
732 the major use for this is when two different structures need to reference the
733 same underlying data, and you want to be able to free the two instances separately,
734 and in either order
736 _PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
738 struct talloc_chunk *tc;
739 struct talloc_reference_handle *handle;
740 if (unlikely(ptr == NULL)) return NULL;
742 tc = talloc_chunk_from_ptr(ptr);
743 handle = (struct talloc_reference_handle *)_talloc_named_const(context,
744 sizeof(struct talloc_reference_handle),
745 TALLOC_MAGIC_REFERENCE);
746 if (unlikely(handle == NULL)) return NULL;
748 /* note that we hang the destructor off the handle, not the
749 main context as that allows the caller to still setup their
750 own destructor on the context if they want to */
751 talloc_set_destructor(handle, talloc_reference_destructor);
752 handle->ptr = discard_const_p(void, ptr);
753 handle->location = location;
754 _TLIST_ADD(tc->refs, handle);
755 return handle->ptr;
758 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
760 static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
761 const char *location)
763 union talloc_pool_chunk *pool;
764 void *next_tc;
766 pool = (union talloc_pool_chunk *)tc->pool;
767 next_tc = tc_next_chunk(tc);
769 tc->flags |= TALLOC_FLAG_FREE;
771 /* we mark the freed memory with where we called the free
772 * from. This means on a double free error we can report where
773 * the first free came from
775 tc->name = location;
777 TC_INVALIDATE_FULL_CHUNK(tc);
779 if (unlikely(pool->hdr.object_count == 0)) {
780 talloc_abort("Pool object count zero!");
781 return;
784 pool->hdr.object_count--;
786 if (unlikely(pool->hdr.object_count == 1
787 && !(pool->hdr.c.flags & TALLOC_FLAG_FREE))) {
789 * if there is just one object left in the pool
790 * and pool->flags does not have TALLOC_FLAG_FREE,
791 * it means this is the pool itself and
792 * the rest is available for new objects
793 * again.
795 pool->hdr.c.pool = tc_pool_first_chunk(pool);
796 tc_invalidate_pool(pool);
797 return;
800 if (unlikely(pool->hdr.object_count == 0)) {
802 * we mark the freed memory with where we called the free
803 * from. This means on a double free error we can report where
804 * the first free came from
806 pool->hdr.c.name = location;
808 TC_INVALIDATE_FULL_CHUNK(&pool->hdr.c);
809 free(pool);
810 return;
813 if (pool->hdr.c.pool == next_tc) {
815 * if pool->pool still points to end of
816 * 'tc' (which is stored in the 'next_tc' variable),
817 * we can reclaim the memory of 'tc'.
819 pool->hdr.c.pool = tc;
820 return;
824 * Do nothing. The memory is just "wasted", waiting for the pool
825 * itself to be freed.
829 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
830 void *ptr,
831 const char *location);
834 internal talloc_free call
836 static inline int _talloc_free_internal(void *ptr, const char *location)
838 struct talloc_chunk *tc;
840 if (unlikely(ptr == NULL)) {
841 return -1;
844 /* possibly initialised the talloc fill value */
845 if (unlikely(!talloc_fill.initialised)) {
846 const char *fill = getenv(TALLOC_FILL_ENV);
847 if (fill != NULL) {
848 talloc_fill.enabled = true;
849 talloc_fill.fill_value = strtoul(fill, NULL, 0);
851 talloc_fill.initialised = true;
854 tc = talloc_chunk_from_ptr(ptr);
856 if (unlikely(tc->refs)) {
857 int is_child;
858 /* check if this is a reference from a child or
859 * grandchild back to it's parent or grandparent
861 * in that case we need to remove the reference and
862 * call another instance of talloc_free() on the current
863 * pointer.
865 is_child = talloc_is_parent(tc->refs, ptr);
866 _talloc_free_internal(tc->refs, location);
867 if (is_child) {
868 return _talloc_free_internal(ptr, location);
870 return -1;
873 if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
874 /* we have a free loop - stop looping */
875 return 0;
878 if (unlikely(tc->destructor)) {
879 talloc_destructor_t d = tc->destructor;
880 if (d == (talloc_destructor_t)-1) {
881 return -1;
883 tc->destructor = (talloc_destructor_t)-1;
884 if (d(ptr) == -1) {
885 tc->destructor = d;
886 return -1;
888 tc->destructor = NULL;
891 if (tc->parent) {
892 _TLIST_REMOVE(tc->parent->child, tc);
893 if (tc->parent->child) {
894 tc->parent->child->parent = tc->parent;
896 } else {
897 if (tc->prev) tc->prev->next = tc->next;
898 if (tc->next) tc->next->prev = tc->prev;
899 tc->prev = tc->next = NULL;
902 tc->flags |= TALLOC_FLAG_LOOP;
904 _talloc_free_children_internal(tc, ptr, location);
906 tc->flags |= TALLOC_FLAG_FREE;
909 * If we are part of a memory limited context hierarchy
910 * we need to subtract the memory used from the counters
912 if (tc->limit) {
913 struct talloc_memlimit *l;
915 for (l = tc->limit; l != NULL; l = l->upper) {
916 if (l->cur_size >= tc->size+TC_HDR_SIZE) {
917 l->cur_size -= tc->size+TC_HDR_SIZE;
918 } else {
919 talloc_abort("cur_size memlimit counter not correct!");
920 return 0;
924 if (tc->limit->parent == tc) {
925 free(tc->limit);
928 tc->limit = NULL;
931 /* we mark the freed memory with where we called the free
932 * from. This means on a double free error we can report where
933 * the first free came from
935 tc->name = location;
937 if (tc->flags & TALLOC_FLAG_POOL) {
938 union talloc_pool_chunk *pool = (union talloc_pool_chunk *)tc;
940 if (unlikely(pool->hdr.object_count == 0)) {
941 talloc_abort("Pool object count zero!");
942 return 0;
945 pool->hdr.object_count--;
947 if (likely(pool->hdr.object_count != 0)) {
948 return 0;
951 TC_INVALIDATE_FULL_CHUNK(tc);
952 free(tc);
953 return 0;
956 if (tc->flags & TALLOC_FLAG_POOLMEM) {
957 _talloc_free_poolmem(tc, location);
958 return 0;
961 TC_INVALIDATE_FULL_CHUNK(tc);
962 free(tc);
963 return 0;
966 static size_t _talloc_total_limit_size(const void *ptr,
967 struct talloc_memlimit *old_limit,
968 struct talloc_memlimit *new_limit);
971 move a lump of memory from one talloc context to another return the
972 ptr on success, or NULL if it could not be transferred.
973 passing NULL as ptr will always return NULL with no side effects.
975 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr)
977 struct talloc_chunk *tc, *new_tc;
978 size_t ctx_size = 0;
980 if (unlikely(!ptr)) {
981 return NULL;
984 if (unlikely(new_ctx == NULL)) {
985 new_ctx = null_context;
988 tc = talloc_chunk_from_ptr(ptr);
990 if (tc->limit != NULL) {
992 ctx_size = _talloc_total_limit_size(ptr, NULL, NULL);
994 if (!talloc_memlimit_update(tc->limit->upper, ctx_size, 0)) {
995 talloc_abort("cur_size memlimit counter not correct!");
996 errno = EINVAL;
997 return NULL;
1000 if (tc->limit->parent == tc) {
1001 tc->limit->upper = NULL;
1002 } else {
1003 tc->limit = NULL;
1007 if (unlikely(new_ctx == NULL)) {
1008 if (tc->parent) {
1009 _TLIST_REMOVE(tc->parent->child, tc);
1010 if (tc->parent->child) {
1011 tc->parent->child->parent = tc->parent;
1013 } else {
1014 if (tc->prev) tc->prev->next = tc->next;
1015 if (tc->next) tc->next->prev = tc->prev;
1018 tc->parent = tc->next = tc->prev = NULL;
1019 return discard_const_p(void, ptr);
1022 new_tc = talloc_chunk_from_ptr(new_ctx);
1024 if (unlikely(tc == new_tc || tc->parent == new_tc)) {
1025 return discard_const_p(void, ptr);
1028 if (tc->parent) {
1029 _TLIST_REMOVE(tc->parent->child, tc);
1030 if (tc->parent->child) {
1031 tc->parent->child->parent = tc->parent;
1033 } else {
1034 if (tc->prev) tc->prev->next = tc->next;
1035 if (tc->next) tc->next->prev = tc->prev;
1036 tc->prev = tc->next = NULL;
1039 tc->parent = new_tc;
1040 if (new_tc->child) new_tc->child->parent = NULL;
1041 _TLIST_ADD(new_tc->child, tc);
1043 if (tc->limit || new_tc->limit) {
1044 ctx_size = _talloc_total_limit_size(ptr, tc->limit,
1045 new_tc->limit);
1048 if (new_tc->limit) {
1049 struct talloc_memlimit *l;
1051 for (l = new_tc->limit; l != NULL; l = l->upper) {
1052 l->cur_size += ctx_size;
1056 return discard_const_p(void, ptr);
1060 move a lump of memory from one talloc context to another return the
1061 ptr on success, or NULL if it could not be transferred.
1062 passing NULL as ptr will always return NULL with no side effects.
1064 _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
1066 struct talloc_chunk *tc;
1068 if (unlikely(ptr == NULL)) {
1069 return NULL;
1072 tc = talloc_chunk_from_ptr(ptr);
1074 if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
1075 struct talloc_reference_handle *h;
1077 talloc_log("WARNING: talloc_steal with references at %s\n",
1078 location);
1080 for (h=tc->refs; h; h=h->next) {
1081 talloc_log("\treference at %s\n",
1082 h->location);
1086 #if 0
1087 /* this test is probably too expensive to have on in the
1088 normal build, but it useful for debugging */
1089 if (talloc_is_parent(new_ctx, ptr)) {
1090 talloc_log("WARNING: stealing into talloc child at %s\n", location);
1092 #endif
1094 return _talloc_steal_internal(new_ctx, ptr);
1098 this is like a talloc_steal(), but you must supply the old
1099 parent. This resolves the ambiguity in a talloc_steal() which is
1100 called on a context that has more than one parent (via references)
1102 The old parent can be either a reference or a parent
1104 _PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
1106 struct talloc_chunk *tc;
1107 struct talloc_reference_handle *h;
1109 if (unlikely(ptr == NULL)) {
1110 return NULL;
1113 if (old_parent == talloc_parent(ptr)) {
1114 return _talloc_steal_internal(new_parent, ptr);
1117 tc = talloc_chunk_from_ptr(ptr);
1118 for (h=tc->refs;h;h=h->next) {
1119 if (talloc_parent(h) == old_parent) {
1120 if (_talloc_steal_internal(new_parent, h) != h) {
1121 return NULL;
1123 return discard_const_p(void, ptr);
1127 /* it wasn't a parent */
1128 return NULL;
1132 remove a secondary reference to a pointer. This undo's what
1133 talloc_reference() has done. The context and pointer arguments
1134 must match those given to a talloc_reference()
1136 static inline int talloc_unreference(const void *context, const void *ptr)
1138 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1139 struct talloc_reference_handle *h;
1141 if (unlikely(context == NULL)) {
1142 context = null_context;
1145 for (h=tc->refs;h;h=h->next) {
1146 struct talloc_chunk *p = talloc_parent_chunk(h);
1147 if (p == NULL) {
1148 if (context == NULL) break;
1149 } else if (TC_PTR_FROM_CHUNK(p) == context) {
1150 break;
1153 if (h == NULL) {
1154 return -1;
1157 return _talloc_free_internal(h, __location__);
1161 remove a specific parent context from a pointer. This is a more
1162 controlled variant of talloc_free()
1164 _PUBLIC_ int talloc_unlink(const void *context, void *ptr)
1166 struct talloc_chunk *tc_p, *new_p, *tc_c;
1167 void *new_parent;
1169 if (ptr == NULL) {
1170 return -1;
1173 if (context == NULL) {
1174 context = null_context;
1177 if (talloc_unreference(context, ptr) == 0) {
1178 return 0;
1181 if (context != NULL) {
1182 tc_c = talloc_chunk_from_ptr(context);
1183 } else {
1184 tc_c = NULL;
1186 if (tc_c != talloc_parent_chunk(ptr)) {
1187 return -1;
1190 tc_p = talloc_chunk_from_ptr(ptr);
1192 if (tc_p->refs == NULL) {
1193 return _talloc_free_internal(ptr, __location__);
1196 new_p = talloc_parent_chunk(tc_p->refs);
1197 if (new_p) {
1198 new_parent = TC_PTR_FROM_CHUNK(new_p);
1199 } else {
1200 new_parent = NULL;
1203 if (talloc_unreference(new_parent, ptr) != 0) {
1204 return -1;
1207 _talloc_steal_internal(new_parent, ptr);
1209 return 0;
1213 add a name to an existing pointer - va_list version
1215 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1217 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
1219 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1220 tc->name = talloc_vasprintf(ptr, fmt, ap);
1221 if (likely(tc->name)) {
1222 _talloc_set_name_const(tc->name, ".name");
1224 return tc->name;
1228 add a name to an existing pointer
1230 _PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
1232 const char *name;
1233 va_list ap;
1234 va_start(ap, fmt);
1235 name = talloc_set_name_v(ptr, fmt, ap);
1236 va_end(ap);
1237 return name;
1242 create a named talloc pointer. Any talloc pointer can be named, and
1243 talloc_named() operates just like talloc() except that it allows you
1244 to name the pointer.
1246 _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
1248 va_list ap;
1249 void *ptr;
1250 const char *name;
1252 ptr = __talloc(context, size);
1253 if (unlikely(ptr == NULL)) return NULL;
1255 va_start(ap, fmt);
1256 name = talloc_set_name_v(ptr, fmt, ap);
1257 va_end(ap);
1259 if (unlikely(name == NULL)) {
1260 _talloc_free_internal(ptr, __location__);
1261 return NULL;
1264 return ptr;
1268 return the name of a talloc ptr, or "UNNAMED"
1270 _PUBLIC_ const char *talloc_get_name(const void *ptr)
1272 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1273 if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
1274 return ".reference";
1276 if (likely(tc->name)) {
1277 return tc->name;
1279 return "UNNAMED";
1284 check if a pointer has the given name. If it does, return the pointer,
1285 otherwise return NULL
1287 _PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
1289 const char *pname;
1290 if (unlikely(ptr == NULL)) return NULL;
1291 pname = talloc_get_name(ptr);
1292 if (likely(pname == name || strcmp(pname, name) == 0)) {
1293 return discard_const_p(void, ptr);
1295 return NULL;
1298 static void talloc_abort_type_mismatch(const char *location,
1299 const char *name,
1300 const char *expected)
1302 const char *reason;
1304 reason = talloc_asprintf(NULL,
1305 "%s: Type mismatch: name[%s] expected[%s]",
1306 location,
1307 name?name:"NULL",
1308 expected);
1309 if (!reason) {
1310 reason = "Type mismatch";
1313 talloc_abort(reason);
1316 _PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
1318 const char *pname;
1320 if (unlikely(ptr == NULL)) {
1321 talloc_abort_type_mismatch(location, NULL, name);
1322 return NULL;
1325 pname = talloc_get_name(ptr);
1326 if (likely(pname == name || strcmp(pname, name) == 0)) {
1327 return discard_const_p(void, ptr);
1330 talloc_abort_type_mismatch(location, pname, name);
1331 return NULL;
1335 this is for compatibility with older versions of talloc
1337 _PUBLIC_ void *talloc_init(const char *fmt, ...)
1339 va_list ap;
1340 void *ptr;
1341 const char *name;
1343 ptr = __talloc(NULL, 0);
1344 if (unlikely(ptr == NULL)) return NULL;
1346 va_start(ap, fmt);
1347 name = talloc_set_name_v(ptr, fmt, ap);
1348 va_end(ap);
1350 if (unlikely(name == NULL)) {
1351 _talloc_free_internal(ptr, __location__);
1352 return NULL;
1355 return ptr;
1358 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
1359 void *ptr,
1360 const char *location)
1362 while (tc->child) {
1363 /* we need to work out who will own an abandoned child
1364 if it cannot be freed. In priority order, the first
1365 choice is owner of any remaining reference to this
1366 pointer, the second choice is our parent, and the
1367 final choice is the null context. */
1368 void *child = TC_PTR_FROM_CHUNK(tc->child);
1369 const void *new_parent = null_context;
1370 if (unlikely(tc->child->refs)) {
1371 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1372 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1374 if (unlikely(_talloc_free_internal(child, location) == -1)) {
1375 if (new_parent == null_context) {
1376 struct talloc_chunk *p = talloc_parent_chunk(ptr);
1377 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1379 _talloc_steal_internal(new_parent, child);
1385 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1386 should probably not be used in new code. It's in here to keep the talloc
1387 code consistent across Samba 3 and 4.
1389 _PUBLIC_ void talloc_free_children(void *ptr)
1391 struct talloc_chunk *tc_name = NULL;
1392 struct talloc_chunk *tc;
1394 if (unlikely(ptr == NULL)) {
1395 return;
1398 tc = talloc_chunk_from_ptr(ptr);
1400 /* we do not want to free the context name if it is a child .. */
1401 if (likely(tc->child)) {
1402 for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
1403 if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
1405 if (tc_name) {
1406 _TLIST_REMOVE(tc->child, tc_name);
1407 if (tc->child) {
1408 tc->child->parent = tc;
1413 _talloc_free_children_internal(tc, ptr, __location__);
1415 /* .. so we put it back after all other children have been freed */
1416 if (tc_name) {
1417 if (tc->child) {
1418 tc->child->parent = NULL;
1420 tc_name->parent = tc;
1421 _TLIST_ADD(tc->child, tc_name);
1426 Allocate a bit of memory as a child of an existing pointer
1428 _PUBLIC_ void *_talloc(const void *context, size_t size)
1430 return __talloc(context, size);
1434 externally callable talloc_set_name_const()
1436 _PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
1438 _talloc_set_name_const(ptr, name);
1442 create a named talloc pointer. Any talloc pointer can be named, and
1443 talloc_named() operates just like talloc() except that it allows you
1444 to name the pointer.
1446 _PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
1448 return _talloc_named_const(context, size, name);
1452 free a talloc pointer. This also frees all child pointers of this
1453 pointer recursively
1455 return 0 if the memory is actually freed, otherwise -1. The memory
1456 will not be freed if the ref_count is > 1 or the destructor (if
1457 any) returns non-zero
1459 _PUBLIC_ int _talloc_free(void *ptr, const char *location)
1461 struct talloc_chunk *tc;
1463 if (unlikely(ptr == NULL)) {
1464 return -1;
1467 tc = talloc_chunk_from_ptr(ptr);
1469 if (unlikely(tc->refs != NULL)) {
1470 struct talloc_reference_handle *h;
1472 if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
1473 /* in this case we do know which parent should
1474 get this pointer, as there is really only
1475 one parent */
1476 return talloc_unlink(null_context, ptr);
1479 talloc_log("ERROR: talloc_free with references at %s\n",
1480 location);
1482 for (h=tc->refs; h; h=h->next) {
1483 talloc_log("\treference at %s\n",
1484 h->location);
1486 return -1;
1489 return _talloc_free_internal(ptr, location);
1495 A talloc version of realloc. The context argument is only used if
1496 ptr is NULL
1498 _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
1500 struct talloc_chunk *tc;
1501 void *new_ptr;
1502 bool malloced = false;
1503 union talloc_pool_chunk *pool_tc = NULL;
1505 /* size zero is equivalent to free() */
1506 if (unlikely(size == 0)) {
1507 talloc_unlink(context, ptr);
1508 return NULL;
1511 if (unlikely(size >= MAX_TALLOC_SIZE)) {
1512 return NULL;
1515 /* realloc(NULL) is equivalent to malloc() */
1516 if (ptr == NULL) {
1517 return _talloc_named_const(context, size, name);
1520 tc = talloc_chunk_from_ptr(ptr);
1522 /* don't allow realloc on referenced pointers */
1523 if (unlikely(tc->refs)) {
1524 return NULL;
1527 /* don't let anybody try to realloc a talloc_pool */
1528 if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
1529 return NULL;
1532 if (tc->limit && (size - tc->size > 0)) {
1533 if (!talloc_memlimit_check(tc->limit, (size - tc->size))) {
1534 errno = ENOMEM;
1535 return NULL;
1539 /* handle realloc inside a talloc_pool */
1540 if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
1541 pool_tc = (union talloc_pool_chunk *)tc->pool;
1544 #if (ALWAYS_REALLOC == 0)
1545 /* don't shrink if we have less than 1k to gain */
1546 if (size < tc->size && tc->limit == NULL) {
1547 if (pool_tc) {
1548 void *next_tc = tc_next_chunk(tc);
1549 TC_INVALIDATE_SHRINK_CHUNK(tc, size);
1550 tc->size = size;
1551 if (next_tc == pool_tc->hdr.c.pool) {
1552 /* note: tc->size has changed, so this works */
1553 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1555 return ptr;
1556 } else if ((tc->size - size) < 1024) {
1558 * if we call TC_INVALIDATE_SHRINK_CHUNK() here
1559 * we would need to call TC_UNDEFINE_GROW_CHUNK()
1560 * after each realloc call, which slows down
1561 * testing a lot :-(.
1563 * That is why we only mark memory as undefined here.
1565 TC_UNDEFINE_SHRINK_CHUNK(tc, size);
1567 /* do not shrink if we have less than 1k to gain */
1568 tc->size = size;
1569 return ptr;
1571 } else if (tc->size == size) {
1573 * do not change the pointer if it is exactly
1574 * the same size.
1576 return ptr;
1578 #endif
1580 /* by resetting magic we catch users of the old memory */
1581 tc->flags |= TALLOC_FLAG_FREE;
1583 #if ALWAYS_REALLOC
1584 if (pool_tc) {
1585 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1586 pool_tc->hdr.object_count--;
1588 if (new_ptr == NULL) {
1589 new_ptr = malloc(TC_HDR_SIZE+size);
1590 malloced = true;
1593 if (new_ptr) {
1594 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1595 TC_INVALIDATE_FULL_CHUNK(tc);
1597 } else {
1598 new_ptr = malloc(size + TC_HDR_SIZE);
1599 if (new_ptr) {
1600 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1601 free(tc);
1604 #else
1605 if (pool_tc) {
1606 void *next_tc = tc_next_chunk(tc);
1607 size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size);
1608 size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
1609 size_t space_needed;
1610 size_t space_left;
1611 unsigned int chunk_count = pool_tc->hdr.object_count;
1613 if (!(pool_tc->hdr.c.flags & TALLOC_FLAG_FREE)) {
1614 chunk_count -= 1;
1617 if (chunk_count == 1) {
1619 * optimize for the case where 'tc' is the only
1620 * chunk in the pool.
1622 char *start = tc_pool_first_chunk(pool_tc);
1623 space_needed = new_chunk_size;
1624 space_left = (char *)tc_pool_end(pool_tc) - start;
1626 if (space_left >= space_needed) {
1627 size_t old_used = TC_HDR_SIZE + tc->size;
1628 size_t new_used = TC_HDR_SIZE + size;
1629 new_ptr = start;
1630 memmove(new_ptr, tc, old_used);
1632 tc = (struct talloc_chunk *)new_ptr;
1633 TC_UNDEFINE_GROW_CHUNK(tc, size);
1636 * first we do not align the pool pointer
1637 * because we want to invalidate the padding
1638 * too.
1640 pool_tc->hdr.c.pool = new_used + (char *)new_ptr;
1641 tc_invalidate_pool(pool_tc);
1643 /* now the aligned pointer */
1644 pool_tc->hdr.c.pool = new_chunk_size + (char *)new_ptr;
1645 goto got_new_ptr;
1648 next_tc = NULL;
1651 if (new_chunk_size == old_chunk_size) {
1652 TC_UNDEFINE_GROW_CHUNK(tc, size);
1653 tc->flags &= ~TALLOC_FLAG_FREE;
1654 if (!talloc_memlimit_update(tc->limit,
1655 tc->size, size)) {
1656 talloc_abort("cur_size memlimit counter not"
1657 " correct!");
1658 errno = EINVAL;
1659 return NULL;
1662 tc->size = size;
1663 return ptr;
1666 if (next_tc == pool_tc->hdr.c.pool) {
1668 * optimize for the case where 'tc' is the last
1669 * chunk in the pool.
1671 space_needed = new_chunk_size - old_chunk_size;
1672 space_left = tc_pool_space_left(pool_tc);
1674 if (space_left >= space_needed) {
1675 TC_UNDEFINE_GROW_CHUNK(tc, size);
1676 tc->flags &= ~TALLOC_FLAG_FREE;
1677 if (!talloc_memlimit_update(tc->limit,
1678 tc->size, size)) {
1679 talloc_abort("cur_size memlimit "
1680 "counter not correct!");
1681 errno = EINVAL;
1682 return NULL;
1684 tc->size = size;
1685 pool_tc->hdr.c.pool = tc_next_chunk(tc);
1686 return ptr;
1690 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1692 if (new_ptr == NULL) {
1693 new_ptr = malloc(TC_HDR_SIZE+size);
1694 malloced = true;
1697 if (new_ptr) {
1698 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1700 _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
1703 else {
1704 new_ptr = realloc(tc, size + TC_HDR_SIZE);
1706 got_new_ptr:
1707 #endif
1708 if (unlikely(!new_ptr)) {
1709 tc->flags &= ~TALLOC_FLAG_FREE;
1710 return NULL;
1713 tc = (struct talloc_chunk *)new_ptr;
1714 tc->flags &= ~TALLOC_FLAG_FREE;
1715 if (malloced) {
1716 tc->flags &= ~TALLOC_FLAG_POOLMEM;
1718 if (tc->parent) {
1719 tc->parent->child = tc;
1721 if (tc->child) {
1722 tc->child->parent = tc;
1725 if (tc->prev) {
1726 tc->prev->next = tc;
1728 if (tc->next) {
1729 tc->next->prev = tc;
1732 if (!talloc_memlimit_update(tc->limit, tc->size, size)) {
1733 talloc_abort("cur_size memlimit counter not correct!");
1734 errno = EINVAL;
1735 return NULL;
1737 tc->size = size;
1738 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
1740 return TC_PTR_FROM_CHUNK(tc);
1744 a wrapper around talloc_steal() for situations where you are moving a pointer
1745 between two structures, and want the old pointer to be set to NULL
1747 _PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
1749 const void **pptr = discard_const_p(const void *,_pptr);
1750 void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
1751 (*pptr) = NULL;
1752 return ret;
1755 enum talloc_mem_count_type {
1756 TOTAL_MEM_SIZE,
1757 TOTAL_MEM_BLOCKS,
1758 TOTAL_MEM_LIMIT,
1761 static size_t _talloc_total_mem_internal(const void *ptr,
1762 enum talloc_mem_count_type type,
1763 struct talloc_memlimit *old_limit,
1764 struct talloc_memlimit *new_limit)
1766 size_t total = 0;
1767 struct talloc_chunk *c, *tc;
1769 if (ptr == NULL) {
1770 ptr = null_context;
1772 if (ptr == NULL) {
1773 return 0;
1776 tc = talloc_chunk_from_ptr(ptr);
1778 if (old_limit || new_limit) {
1779 if (tc->limit && tc->limit->upper == old_limit) {
1780 tc->limit->upper = new_limit;
1784 /* optimize in the memlimits case */
1785 if (type == TOTAL_MEM_LIMIT &&
1786 tc->limit != NULL &&
1787 tc->limit != old_limit &&
1788 tc->limit->parent == tc) {
1789 return tc->limit->cur_size;
1792 if (tc->flags & TALLOC_FLAG_LOOP) {
1793 return 0;
1796 tc->flags |= TALLOC_FLAG_LOOP;
1798 if (old_limit || new_limit) {
1799 if (old_limit == tc->limit) {
1800 tc->limit = new_limit;
1804 switch (type) {
1805 case TOTAL_MEM_SIZE:
1806 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1807 total = tc->size;
1809 break;
1810 case TOTAL_MEM_BLOCKS:
1811 total++;
1812 break;
1813 case TOTAL_MEM_LIMIT:
1814 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1815 total = tc->size + TC_HDR_SIZE;
1817 break;
1819 for (c = tc->child; c; c = c->next) {
1820 total += _talloc_total_mem_internal(TC_PTR_FROM_CHUNK(c), type,
1821 old_limit, new_limit);
1824 tc->flags &= ~TALLOC_FLAG_LOOP;
1826 return total;
1830 return the total size of a talloc pool (subtree)
1832 _PUBLIC_ size_t talloc_total_size(const void *ptr)
1834 return _talloc_total_mem_internal(ptr, TOTAL_MEM_SIZE, NULL, NULL);
1838 return the total number of blocks in a talloc pool (subtree)
1840 _PUBLIC_ size_t talloc_total_blocks(const void *ptr)
1842 return _talloc_total_mem_internal(ptr, TOTAL_MEM_BLOCKS, NULL, NULL);
1846 return the number of external references to a pointer
1848 _PUBLIC_ size_t talloc_reference_count(const void *ptr)
1850 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1851 struct talloc_reference_handle *h;
1852 size_t ret = 0;
1854 for (h=tc->refs;h;h=h->next) {
1855 ret++;
1857 return ret;
1861 report on memory usage by all children of a pointer, giving a full tree view
1863 _PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1864 void (*callback)(const void *ptr,
1865 int depth, int max_depth,
1866 int is_ref,
1867 void *private_data),
1868 void *private_data)
1870 struct talloc_chunk *c, *tc;
1872 if (ptr == NULL) {
1873 ptr = null_context;
1875 if (ptr == NULL) return;
1877 tc = talloc_chunk_from_ptr(ptr);
1879 if (tc->flags & TALLOC_FLAG_LOOP) {
1880 return;
1883 callback(ptr, depth, max_depth, 0, private_data);
1885 if (max_depth >= 0 && depth >= max_depth) {
1886 return;
1889 tc->flags |= TALLOC_FLAG_LOOP;
1890 for (c=tc->child;c;c=c->next) {
1891 if (c->name == TALLOC_MAGIC_REFERENCE) {
1892 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1893 callback(h->ptr, depth + 1, max_depth, 1, private_data);
1894 } else {
1895 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1898 tc->flags &= ~TALLOC_FLAG_LOOP;
1901 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1903 const char *name = talloc_get_name(ptr);
1904 struct talloc_chunk *tc;
1905 FILE *f = (FILE *)_f;
1907 if (is_ref) {
1908 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1909 return;
1912 tc = talloc_chunk_from_ptr(ptr);
1913 if (tc->limit && tc->limit->parent == tc) {
1914 fprintf(f, "%*s%-30s is a memlimit context"
1915 " (max_size = %lu bytes, cur_size = %lu bytes)\n",
1916 depth*4, "",
1917 name,
1918 (unsigned long)tc->limit->max_size,
1919 (unsigned long)tc->limit->cur_size);
1922 if (depth == 0) {
1923 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1924 (max_depth < 0 ? "full " :""), name,
1925 (unsigned long)talloc_total_size(ptr),
1926 (unsigned long)talloc_total_blocks(ptr));
1927 return;
1930 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1931 depth*4, "",
1932 name,
1933 (unsigned long)talloc_total_size(ptr),
1934 (unsigned long)talloc_total_blocks(ptr),
1935 (int)talloc_reference_count(ptr), ptr);
1937 #if 0
1938 fprintf(f, "content: ");
1939 if (talloc_total_size(ptr)) {
1940 int tot = talloc_total_size(ptr);
1941 int i;
1943 for (i = 0; i < tot; i++) {
1944 if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1945 fprintf(f, "%c", ((char *)ptr)[i]);
1946 } else {
1947 fprintf(f, "~%02x", ((char *)ptr)[i]);
1951 fprintf(f, "\n");
1952 #endif
1956 report on memory usage by all children of a pointer, giving a full tree view
1958 _PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1960 if (f) {
1961 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1962 fflush(f);
1967 report on memory usage by all children of a pointer, giving a full tree view
1969 _PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
1971 talloc_report_depth_file(ptr, 0, -1, f);
1975 report on memory usage by all children of a pointer
1977 _PUBLIC_ void talloc_report(const void *ptr, FILE *f)
1979 talloc_report_depth_file(ptr, 0, 1, f);
1983 report on any memory hanging off the null context
1985 static void talloc_report_null(void)
1987 if (talloc_total_size(null_context) != 0) {
1988 talloc_report(null_context, stderr);
1993 report on any memory hanging off the null context
1995 static void talloc_report_null_full(void)
1997 if (talloc_total_size(null_context) != 0) {
1998 talloc_report_full(null_context, stderr);
2003 enable tracking of the NULL context
2005 _PUBLIC_ void talloc_enable_null_tracking(void)
2007 if (null_context == NULL) {
2008 null_context = _talloc_named_const(NULL, 0, "null_context");
2009 if (autofree_context != NULL) {
2010 talloc_reparent(NULL, null_context, autofree_context);
2016 enable tracking of the NULL context, not moving the autofree context
2017 into the NULL context. This is needed for the talloc testsuite
2019 _PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
2021 if (null_context == NULL) {
2022 null_context = _talloc_named_const(NULL, 0, "null_context");
2027 disable tracking of the NULL context
2029 _PUBLIC_ void talloc_disable_null_tracking(void)
2031 if (null_context != NULL) {
2032 /* we have to move any children onto the real NULL
2033 context */
2034 struct talloc_chunk *tc, *tc2;
2035 tc = talloc_chunk_from_ptr(null_context);
2036 for (tc2 = tc->child; tc2; tc2=tc2->next) {
2037 if (tc2->parent == tc) tc2->parent = NULL;
2038 if (tc2->prev == tc) tc2->prev = NULL;
2040 for (tc2 = tc->next; tc2; tc2=tc2->next) {
2041 if (tc2->parent == tc) tc2->parent = NULL;
2042 if (tc2->prev == tc) tc2->prev = NULL;
2044 tc->child = NULL;
2045 tc->next = NULL;
2047 talloc_free(null_context);
2048 null_context = NULL;
2052 enable leak reporting on exit
2054 _PUBLIC_ void talloc_enable_leak_report(void)
2056 talloc_enable_null_tracking();
2057 atexit(talloc_report_null);
2061 enable full leak reporting on exit
2063 _PUBLIC_ void talloc_enable_leak_report_full(void)
2065 talloc_enable_null_tracking();
2066 atexit(talloc_report_null_full);
2070 talloc and zero memory.
2072 _PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
2074 void *p = _talloc_named_const(ctx, size, name);
2076 if (p) {
2077 memset(p, '\0', size);
2080 return p;
2084 memdup with a talloc.
2086 _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
2088 void *newp = _talloc_named_const(t, size, name);
2090 if (likely(newp)) {
2091 memcpy(newp, p, size);
2094 return newp;
2097 static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
2099 char *ret;
2101 ret = (char *)__talloc(t, len + 1);
2102 if (unlikely(!ret)) return NULL;
2104 memcpy(ret, p, len);
2105 ret[len] = 0;
2107 _talloc_set_name_const(ret, ret);
2108 return ret;
2112 strdup with a talloc
2114 _PUBLIC_ char *talloc_strdup(const void *t, const char *p)
2116 if (unlikely(!p)) return NULL;
2117 return __talloc_strlendup(t, p, strlen(p));
2121 strndup with a talloc
2123 _PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
2125 if (unlikely(!p)) return NULL;
2126 return __talloc_strlendup(t, p, strnlen(p, n));
2129 static inline char *__talloc_strlendup_append(char *s, size_t slen,
2130 const char *a, size_t alen)
2132 char *ret;
2134 ret = talloc_realloc(NULL, s, char, slen + alen + 1);
2135 if (unlikely(!ret)) return NULL;
2137 /* append the string and the trailing \0 */
2138 memcpy(&ret[slen], a, alen);
2139 ret[slen+alen] = 0;
2141 _talloc_set_name_const(ret, ret);
2142 return ret;
2146 * Appends at the end of the string.
2148 _PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
2150 if (unlikely(!s)) {
2151 return talloc_strdup(NULL, a);
2154 if (unlikely(!a)) {
2155 return s;
2158 return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
2162 * Appends at the end of the talloc'ed buffer,
2163 * not the end of the string.
2165 _PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
2167 size_t slen;
2169 if (unlikely(!s)) {
2170 return talloc_strdup(NULL, a);
2173 if (unlikely(!a)) {
2174 return s;
2177 slen = talloc_get_size(s);
2178 if (likely(slen > 0)) {
2179 slen--;
2182 return __talloc_strlendup_append(s, slen, a, strlen(a));
2186 * Appends at the end of the string.
2188 _PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
2190 if (unlikely(!s)) {
2191 return talloc_strndup(NULL, a, n);
2194 if (unlikely(!a)) {
2195 return s;
2198 return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
2202 * Appends at the end of the talloc'ed buffer,
2203 * not the end of the string.
2205 _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
2207 size_t slen;
2209 if (unlikely(!s)) {
2210 return talloc_strndup(NULL, a, n);
2213 if (unlikely(!a)) {
2214 return s;
2217 slen = talloc_get_size(s);
2218 if (likely(slen > 0)) {
2219 slen--;
2222 return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
2225 #ifndef HAVE_VA_COPY
2226 #ifdef HAVE___VA_COPY
2227 #define va_copy(dest, src) __va_copy(dest, src)
2228 #else
2229 #define va_copy(dest, src) (dest) = (src)
2230 #endif
2231 #endif
2233 _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
2235 int len;
2236 char *ret;
2237 va_list ap2;
2238 char c;
2240 /* this call looks strange, but it makes it work on older solaris boxes */
2241 va_copy(ap2, ap);
2242 len = vsnprintf(&c, 1, fmt, ap2);
2243 va_end(ap2);
2244 if (unlikely(len < 0)) {
2245 return NULL;
2248 ret = (char *)__talloc(t, len+1);
2249 if (unlikely(!ret)) return NULL;
2251 va_copy(ap2, ap);
2252 vsnprintf(ret, len+1, fmt, ap2);
2253 va_end(ap2);
2255 _talloc_set_name_const(ret, ret);
2256 return ret;
2261 Perform string formatting, and return a pointer to newly allocated
2262 memory holding the result, inside a memory pool.
2264 _PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
2266 va_list ap;
2267 char *ret;
2269 va_start(ap, fmt);
2270 ret = talloc_vasprintf(t, fmt, ap);
2271 va_end(ap);
2272 return ret;
2275 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2276 const char *fmt, va_list ap)
2277 PRINTF_ATTRIBUTE(3,0);
2279 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2280 const char *fmt, va_list ap)
2282 ssize_t alen;
2283 va_list ap2;
2284 char c;
2286 va_copy(ap2, ap);
2287 alen = vsnprintf(&c, 1, fmt, ap2);
2288 va_end(ap2);
2290 if (alen <= 0) {
2291 /* Either the vsnprintf failed or the format resulted in
2292 * no characters being formatted. In the former case, we
2293 * ought to return NULL, in the latter we ought to return
2294 * the original string. Most current callers of this
2295 * function expect it to never return NULL.
2297 return s;
2300 s = talloc_realloc(NULL, s, char, slen + alen + 1);
2301 if (!s) return NULL;
2303 va_copy(ap2, ap);
2304 vsnprintf(s + slen, alen + 1, fmt, ap2);
2305 va_end(ap2);
2307 _talloc_set_name_const(s, s);
2308 return s;
2312 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2313 * and return @p s, which may have moved. Good for gradually
2314 * accumulating output into a string buffer. Appends at the end
2315 * of the string.
2317 _PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
2319 if (unlikely(!s)) {
2320 return talloc_vasprintf(NULL, fmt, ap);
2323 return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
2327 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2328 * and return @p s, which may have moved. Always appends at the
2329 * end of the talloc'ed buffer, not the end of the string.
2331 _PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
2333 size_t slen;
2335 if (unlikely(!s)) {
2336 return talloc_vasprintf(NULL, fmt, ap);
2339 slen = talloc_get_size(s);
2340 if (likely(slen > 0)) {
2341 slen--;
2344 return __talloc_vaslenprintf_append(s, slen, fmt, ap);
2348 Realloc @p s to append the formatted result of @p fmt and return @p
2349 s, which may have moved. Good for gradually accumulating output
2350 into a string buffer.
2352 _PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
2354 va_list ap;
2356 va_start(ap, fmt);
2357 s = talloc_vasprintf_append(s, fmt, ap);
2358 va_end(ap);
2359 return s;
2363 Realloc @p s to append the formatted result of @p fmt and return @p
2364 s, which may have moved. Good for gradually accumulating output
2365 into a buffer.
2367 _PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
2369 va_list ap;
2371 va_start(ap, fmt);
2372 s = talloc_vasprintf_append_buffer(s, fmt, ap);
2373 va_end(ap);
2374 return s;
2378 alloc an array, checking for integer overflow in the array size
2380 _PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2382 if (count >= MAX_TALLOC_SIZE/el_size) {
2383 return NULL;
2385 return _talloc_named_const(ctx, el_size * count, name);
2389 alloc an zero array, checking for integer overflow in the array size
2391 _PUBLIC_ void *_talloc_zero_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_zero(ctx, el_size * count, name);
2400 realloc an array, checking for integer overflow in the array size
2402 _PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
2404 if (count >= MAX_TALLOC_SIZE/el_size) {
2405 return NULL;
2407 return _talloc_realloc(ctx, ptr, el_size * count, name);
2411 a function version of talloc_realloc(), so it can be passed as a function pointer
2412 to libraries that want a realloc function (a realloc function encapsulates
2413 all the basic capabilities of an allocation library, which is why this is useful)
2415 _PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
2417 return _talloc_realloc(context, ptr, size, NULL);
2421 static int talloc_autofree_destructor(void *ptr)
2423 autofree_context = NULL;
2424 return 0;
2427 static void talloc_autofree(void)
2429 talloc_free(autofree_context);
2433 return a context which will be auto-freed on exit
2434 this is useful for reducing the noise in leak reports
2436 _PUBLIC_ void *talloc_autofree_context(void)
2438 if (autofree_context == NULL) {
2439 autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
2440 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
2441 atexit(talloc_autofree);
2443 return autofree_context;
2446 _PUBLIC_ size_t talloc_get_size(const void *context)
2448 struct talloc_chunk *tc;
2450 if (context == NULL) {
2451 context = null_context;
2453 if (context == NULL) {
2454 return 0;
2457 tc = talloc_chunk_from_ptr(context);
2459 return tc->size;
2463 find a parent of this context that has the given name, if any
2465 _PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
2467 struct talloc_chunk *tc;
2469 if (context == NULL) {
2470 return NULL;
2473 tc = talloc_chunk_from_ptr(context);
2474 while (tc) {
2475 if (tc->name && strcmp(tc->name, name) == 0) {
2476 return TC_PTR_FROM_CHUNK(tc);
2478 while (tc && tc->prev) tc = tc->prev;
2479 if (tc) {
2480 tc = tc->parent;
2483 return NULL;
2487 show the parentage of a context
2489 _PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
2491 struct talloc_chunk *tc;
2493 if (context == NULL) {
2494 fprintf(file, "talloc no parents for NULL\n");
2495 return;
2498 tc = talloc_chunk_from_ptr(context);
2499 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
2500 while (tc) {
2501 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
2502 while (tc && tc->prev) tc = tc->prev;
2503 if (tc) {
2504 tc = tc->parent;
2507 fflush(file);
2511 return 1 if ptr is a parent of context
2513 static int _talloc_is_parent(const void *context, const void *ptr, int depth)
2515 struct talloc_chunk *tc;
2517 if (context == NULL) {
2518 return 0;
2521 tc = talloc_chunk_from_ptr(context);
2522 while (tc && depth > 0) {
2523 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
2524 while (tc && tc->prev) tc = tc->prev;
2525 if (tc) {
2526 tc = tc->parent;
2527 depth--;
2530 return 0;
2534 return 1 if ptr is a parent of context
2536 _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
2538 return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
2542 return the total size of memory used by this context and all children
2544 static size_t _talloc_total_limit_size(const void *ptr,
2545 struct talloc_memlimit *old_limit,
2546 struct talloc_memlimit *new_limit)
2548 return _talloc_total_mem_internal(ptr, TOTAL_MEM_LIMIT,
2549 old_limit, new_limit);
2552 static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size)
2554 struct talloc_memlimit *l;
2556 for (l = limit; l != NULL; l = l->upper) {
2557 if (l->max_size != 0 &&
2558 ((l->max_size <= l->cur_size) ||
2559 (l->max_size - l->cur_size < TC_HDR_SIZE+size))) {
2560 return false;
2564 return true;
2567 static bool talloc_memlimit_update(struct talloc_memlimit *limit,
2568 size_t old_size, size_t new_size)
2570 struct talloc_memlimit *l;
2571 ssize_t d;
2573 if (old_size == 0) {
2574 d = new_size + TC_HDR_SIZE;
2575 } else {
2576 d = new_size - old_size;
2578 for (l = limit; l != NULL; l = l->upper) {
2579 ssize_t new_cur_size = l->cur_size + d;
2580 if (new_cur_size < 0) {
2581 return false;
2583 l->cur_size = new_cur_size;
2586 return true;
2589 _PUBLIC_ int talloc_set_memlimit(const void *ctx, size_t max_size)
2591 struct talloc_chunk *tc = talloc_chunk_from_ptr(ctx);
2592 struct talloc_memlimit *orig_limit;
2593 struct talloc_memlimit *limit = NULL;
2595 if (tc->limit && tc->limit->parent == tc) {
2596 tc->limit->max_size = max_size;
2597 return 0;
2599 orig_limit = tc->limit;
2601 limit = malloc(sizeof(struct talloc_memlimit));
2602 if (limit == NULL) {
2603 return 1;
2605 limit->parent = tc;
2606 limit->max_size = max_size;
2607 limit->cur_size = _talloc_total_limit_size(ctx, tc->limit, limit);
2609 if (orig_limit) {
2610 limit->upper = orig_limit;
2611 } else {
2612 limit->upper = NULL;
2615 return 0;