2 Samba Unix SMB/CIFS implementation.
4 Samba temporary memory allocation functions - new interface
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 inspired by http://swapped.cc/halloc/
29 #define MAX_TALLOC_SIZE 0x10000000
30 #define TALLOC_MAGIC 0xe814ec4f
31 #define TALLOC_MAGIC_FREE 0x7faebef3
33 static const void *null_context;
35 struct talloc_reference_handle {
36 struct talloc_reference_handle *next, *prev;
40 typedef int (*talloc_destructor_t)(void *);
43 struct talloc_chunk *next, *prev;
44 struct talloc_chunk *parent, *child;
45 struct talloc_reference_handle *refs;
48 talloc_destructor_t destructor;
52 /* panic if we get a bad magic value */
53 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
55 struct talloc_chunk *tc = ((struct talloc_chunk *)discard_const(ptr))-1;
56 if (tc->magic != TALLOC_MAGIC) {
57 if (tc->magic == TALLOC_MAGIC_FREE) {
58 smb_panic("Bad talloc magic value - double free\n");
60 smb_panic("Bad talloc magic value\n");
67 Allocate a bit of memory as a child of an existing pointer
69 void *_talloc(const void *context, size_t size)
71 struct talloc_chunk *tc;
73 if (context == NULL) {
74 context = null_context;
77 if (size >= MAX_TALLOC_SIZE) {
81 tc = malloc(sizeof(*tc)+size);
87 tc->magic = TALLOC_MAGIC;
88 tc->destructor = NULL;
94 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
99 parent->child->parent = NULL;
102 DLIST_ADD(parent->child, tc);
104 tc->next = tc->prev = tc->parent = NULL;
107 return (void *)(tc+1);
112 setup a destructor to be called on free of a pointer
113 the destructor should return 0 on success, or -1 on failure.
114 if the destructor fails then the free is failed, and the memory can
115 be continued to be used
117 void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
119 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
120 tc->destructor = destructor;
124 increase the reference count on a piece of memory.
126 void talloc_increase_ref_count(const void *ptr)
128 talloc_reference(null_context, ptr);
132 helper for talloc_reference()
134 static int talloc_reference_destructor(void *ptr)
136 struct talloc_reference_handle *handle = ptr;
137 struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
138 struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
139 if (tc1->destructor != (talloc_destructor_t)-1) {
140 tc1->destructor = NULL;
142 DLIST_REMOVE(tc2->refs, handle);
148 make a secondary reference to a pointer, hanging off the given context.
149 the pointer remains valid until both the original caller and this given
152 the major use for this is when two different structures need to reference the
153 same underlying data, and you want to be able to free the two instances separately,
156 void *talloc_reference(const void *context, const void *ptr)
158 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
159 struct talloc_reference_handle *handle;
160 handle = talloc_named_const(context, sizeof(*handle), ".reference");
161 if (handle == NULL) {
164 /* note that we hang the destructor off the handle, not the
165 main context as that allows the caller to still setup their
166 own destructor on the context if they want to */
167 talloc_set_destructor(handle, talloc_reference_destructor);
168 handle->ptr = discard_const(ptr);
169 DLIST_ADD(tc->refs, handle);
174 remove a secondary reference to a pointer. This undo's what
175 talloc_reference() has done. The context and pointer arguments
176 must match those given to a talloc_reference()
178 void *talloc_unreference(const void *context, const void *ptr)
180 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
181 struct talloc_reference_handle *h;
183 if (context == NULL) {
184 context = null_context;
187 for (h=tc->refs;h;h=h->next) {
188 struct talloc_chunk *tc2 = talloc_chunk_from_ptr(h);
189 const void *parent = tc2->parent?tc2->parent+1:null_context;
190 if (parent == context) break;
196 talloc_set_destructor(h, NULL);
197 DLIST_REMOVE(tc->refs, h);
199 return discard_const(ptr);
203 add a name to an existing pointer - va_list version
205 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
207 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
209 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
210 tc->name = talloc_vasprintf(ptr, fmt, ap);
212 talloc_set_name_const(tc->name, ".name");
217 add a name to an existing pointer
219 void talloc_set_name(const void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
223 talloc_set_name_v(ptr, fmt, ap);
228 more efficient way to add a name to a pointer - the name must point to a
231 void talloc_set_name_const(const void *ptr, const char *name)
233 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
238 create a named talloc pointer. Any talloc pointer can be named, and
239 talloc_named() operates just like talloc() except that it allows you
242 void *talloc_named(const void *context, size_t size,
243 const char *fmt, ...) _PRINTF_ATTRIBUTE(3,4)
248 ptr = _talloc(context, size);
254 talloc_set_name_v(ptr, fmt, ap);
261 create a named talloc pointer. Any talloc pointer can be named, and
262 talloc_named() operates just like talloc() except that it allows you
265 void *talloc_named_const(const void *context, size_t size, const char *name)
269 ptr = _talloc(context, size);
274 talloc_set_name_const(ptr, name);
280 return the name of a talloc ptr, or "UNNAMED"
282 const char *talloc_get_name(const void *ptr)
284 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
292 this is for compatibility with older versions of talloc
294 void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2)
299 ptr = _talloc(NULL, 0);
305 talloc_set_name_v(ptr, fmt, ap);
313 free a talloc pointer. This also frees all child pointers of this
316 return 0 if the memory is actually freed, otherwise -1. The memory
317 will not be freed if the ref_count is > 1 or the destructor (if
318 any) returns non-zero
320 int talloc_free(void *ptr)
322 struct talloc_chunk *tc;
328 tc = talloc_chunk_from_ptr(ptr);
331 talloc_reference_destructor(tc->refs);
335 if (tc->destructor) {
336 talloc_destructor_t d = tc->destructor;
337 if (d == (talloc_destructor_t)-1) {
340 tc->destructor = (talloc_destructor_t)-1;
345 tc->destructor = NULL;
349 /* we need to work out who will own an abandoned child
350 if it cannot be freed. In priority order, the first
351 choice is owner of any remaining reference to this
352 pointer, the second choice is our parent, and the
353 final choice is the null context. */
354 void *child = tc->child+1;
355 const void *new_parent = null_context;
356 if (tc->child->refs) {
357 struct talloc_chunk *ref = talloc_chunk_from_ptr(tc->child->refs);
358 if (ref->parent) new_parent = ref->parent+1;
360 if (new_parent == null_context && tc->parent) {
361 new_parent = tc->parent+1;
363 talloc_free(talloc_steal(new_parent, child));
367 DLIST_REMOVE(tc->parent->child, tc);
368 if (tc->parent->child) {
369 tc->parent->child->parent = tc->parent;
372 if (tc->prev) tc->prev->next = tc->next;
373 if (tc->next) tc->next->prev = tc->prev;
376 tc->magic = TALLOC_MAGIC_FREE;
385 A talloc version of realloc. The context argument is only used if
388 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
390 struct talloc_chunk *tc;
393 /* size zero is equivalent to free() */
399 /* realloc(NULL) is equavalent to malloc() */
401 return talloc_named_const(context, size, name);
404 tc = talloc_chunk_from_ptr(ptr);
406 /* don't allow realloc on referenced pointers */
411 /* by resetting magic we catch users of the old memory */
412 tc->magic = TALLOC_MAGIC_FREE;
414 new_ptr = realloc(tc, size + sizeof(*tc));
416 tc->magic = TALLOC_MAGIC;
421 tc->magic = TALLOC_MAGIC;
423 tc->parent->child = new_ptr;
434 talloc_set_name_const(tc+1, name);
436 return (void *)(tc+1);
440 move a lump of memory from one talloc context to another return the
441 ptr on success, or NULL if it could not be transferred
443 void *talloc_steal(const void *new_ctx, const void *ptr)
445 struct talloc_chunk *tc, *new_tc;
451 tc = talloc_chunk_from_ptr(ptr);
453 if (new_ctx == NULL) {
455 DLIST_REMOVE(tc->parent->child, tc);
456 if (tc->parent->child) {
457 tc->parent->child->parent = tc->parent;
460 if (tc->prev) tc->prev->next = tc->next;
461 if (tc->next) tc->next->prev = tc->prev;
464 tc->parent = tc->next = tc->prev = NULL;
465 return discard_const(ptr);
468 new_tc = talloc_chunk_from_ptr(new_ctx);
471 return discard_const(ptr);
475 DLIST_REMOVE(tc->parent->child, tc);
476 if (tc->parent->child) {
477 tc->parent->child->parent = tc->parent;
480 if (tc->prev) tc->prev->next = tc->next;
481 if (tc->next) tc->next->prev = tc->prev;
485 if (new_tc->child) new_tc->child->parent = NULL;
486 DLIST_ADD(new_tc->child, tc);
488 return discard_const(ptr);
492 return the total size of a talloc pool (subtree)
494 off_t talloc_total_size(const void *ptr)
497 struct talloc_chunk *c, *tc;
506 tc = talloc_chunk_from_ptr(ptr);
509 for (c=tc->child;c;c=c->next) {
510 total += talloc_total_size(c+1);
516 return the total number of blocks in a talloc pool (subtree)
518 static off_t talloc_total_blocks(const void *ptr)
521 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
524 for (c=tc->child;c;c=c->next) {
525 total += talloc_total_blocks(c+1);
531 return the number of external references to a pointer
533 static int talloc_reference_count(const void *ptr)
535 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
536 struct talloc_reference_handle *h;
539 for (h=tc->refs;h;h=h->next) {
546 report on memory usage by all children of a pointer, giving a full tree view
548 static void talloc_report_depth(const void *ptr, FILE *f, int depth)
550 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
552 for (c=tc->child;c;c=c->next) {
553 const char *name = talloc_get_name(c+1);
554 if (strcmp(name, ".reference") == 0) {
555 struct talloc_reference_handle *handle = (void *)(c+1);
556 const char *name2 = talloc_get_name(handle->ptr);
557 fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
559 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
562 (unsigned long)talloc_total_size(c+1),
563 (unsigned long)talloc_total_blocks(c+1),
564 talloc_reference_count(c+1));
565 talloc_report_depth(c+1, f, depth+1);
572 report on memory usage by all children of a pointer, giving a full tree view
574 void talloc_report_full(const void *ptr, FILE *f)
579 if (ptr == NULL) return;
581 fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
582 talloc_get_name(ptr),
583 (unsigned long)talloc_total_size(ptr),
584 (unsigned long)talloc_total_blocks(ptr));
586 talloc_report_depth(ptr, f, 1);
590 report on memory usage by all children of a pointer
592 void talloc_report(const void *ptr, FILE *f)
594 struct talloc_chunk *c, *tc;
599 if (ptr == NULL) return;
601 fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n",
602 talloc_get_name(ptr),
603 (unsigned long)talloc_total_size(ptr),
604 (unsigned long)talloc_total_blocks(ptr));
606 tc = talloc_chunk_from_ptr(ptr);
608 for (c=tc->child;c;c=c->next) {
609 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
610 talloc_get_name(c+1),
611 (unsigned long)talloc_total_size(c+1),
612 (unsigned long)talloc_total_blocks(c+1));
618 report on any memory hanging off the null context
620 static void talloc_report_null(void)
622 if (talloc_total_size(null_context) == 0) {
625 talloc_report(null_context, stderr);
629 report on any memory hanging off the null context
631 static void talloc_report_null_full(void)
633 if (talloc_total_size(null_context) == 0) {
636 talloc_report_full(null_context, stderr);
640 enable leak reporting on exit
642 void talloc_enable_leak_report(void)
644 null_context = talloc_named_const(NULL, 0, "null_context");
645 atexit(talloc_report_null);
649 enable full leak reporting on exit
651 void talloc_enable_leak_report_full(void)
653 null_context = talloc_named_const(NULL, 0, "null_context");
654 atexit(talloc_report_null_full);
658 talloc and zero memory.
660 void *talloc_zero(const void *ctx, size_t size)
662 void *p = talloc(ctx, size);
665 memset(p, '\0', size);
673 memdup with a talloc.
675 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
677 void *newp = talloc_named_const(t, size, name);
680 memcpy(newp, p, size);
689 char *talloc_strdup(const void *t, const char *p)
695 ret = talloc_memdup(t, p, strlen(p) + 1);
697 talloc_set_name_const(ret, ret);
703 strndup with a talloc
705 char *talloc_strndup(const void *t, const char *p, size_t n)
707 size_t len = strnlen(p, n);
710 ret = talloc(t, len + 1);
711 if (!ret) { return NULL; }
717 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2,0)
725 len = vsnprintf(NULL, 0, fmt, ap2);
727 ret = talloc(t, len+1);
730 vsnprintf(ret, len+1, fmt, ap2);
731 talloc_set_name_const(ret, ret);
739 Perform string formatting, and return a pointer to newly allocated
740 memory holding the result, inside a memory pool.
742 char *talloc_asprintf(const void *t, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
748 ret = talloc_vasprintf(t, fmt, ap);
755 * Realloc @p s to append the formatted result of @p fmt and @p ap,
756 * and return @p s, which may have moved. Good for gradually
757 * accumulating output into a string buffer.
760 static char *talloc_vasprintf_append(char *s,
761 const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
763 static char *talloc_vasprintf_append(char *s,
764 const char *fmt, va_list ap)
776 len = vsnprintf(NULL, 0, fmt, ap2);
778 s = talloc_realloc(NULL, s, s_len + len+1);
783 vsnprintf(s+s_len, len+1, fmt, ap2);
784 talloc_set_name_const(s, s);
790 Realloc @p s to append the formatted result of @p fmt and return @p
791 s, which may have moved. Good for gradually accumulating output
792 into a string buffer.
794 char *talloc_asprintf_append(char *s,
795 const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3)
800 s = talloc_vasprintf_append(s, fmt, ap);
806 alloc an array, checking for integer overflow in the array size
808 void *talloc_array(const void *ctx, size_t el_size, uint_t count, const char *name)
811 count >= MAX_TALLOC_SIZE/el_size) {
814 return talloc_named_const(ctx, el_size * count, name);
819 realloc an array, checking for integer overflow in the array size
821 void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, uint_t count, const char *name)
824 count >= MAX_TALLOC_SIZE/el_size) {
827 ptr = talloc_realloc(ctx, ptr, el_size * count);
829 talloc_set_name_const(ptr, name);
835 a alloc function for ldb that uses talloc
837 void *talloc_ldb_alloc(void *context, void *ptr, size_t size)
840 return talloc(context, size);
846 return talloc_realloc(context, ptr, size);