ia64/xen-unstable

view tools/xenstore/talloc.c @ 6812:26cf3cfd3bed

Switch vcpu hotplugging to use xstransact.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue Sep 13 17:31:13 2005 +0000 (2005-09-13)
parents 6d3e8f90c2df
children 40e3df4cffe4
line source
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
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
25 /*
26 inspired by http://swapped.cc/halloc/
27 */
30 #ifdef _SAMBA_BUILD_
31 #include "includes.h"
32 #if ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
33 /* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file
34 * we trust ourselves... */
35 #ifdef malloc
36 #undef malloc
37 #endif
38 #ifdef realloc
39 #undef realloc
40 #endif
41 #endif
42 #else
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <stdarg.h>
47 #include <stdint.h>
48 #include "talloc.h"
49 /* assume a modern system */
50 #define HAVE_VA_COPY
51 #endif
53 /* use this to force every realloc to change the pointer, to stress test
54 code that might not cope */
55 #ifdef TESTING
56 #define ALWAYS_REALLOC 1
57 void *test_malloc(size_t size);
58 #define malloc test_malloc
59 #endif
61 #define MAX_TALLOC_SIZE 0x10000000
62 #define TALLOC_MAGIC 0xe814ec4f
63 #define TALLOC_MAGIC_FREE 0x7faebef3
64 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
66 /* by default we abort when given a bad pointer (such as when talloc_free() is called
67 on a pointer that came from malloc() */
68 #ifndef TALLOC_ABORT
69 #define TALLOC_ABORT(reason) abort()
70 #endif
72 #ifndef discard_const_p
73 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
74 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
75 #else
76 # define discard_const_p(type, ptr) ((type *)(ptr))
77 #endif
78 #endif
80 /* this null_context is only used if talloc_enable_leak_report() or
81 talloc_enable_leak_report_full() is called, otherwise it remains
82 NULL
83 */
84 static const void *null_context;
85 static void *cleanup_context;
86 static int (*malloc_fail_handler)(void *);
87 static void *malloc_fail_data;
89 struct talloc_reference_handle {
90 struct talloc_reference_handle *next, *prev;
91 void *ptr;
92 };
94 typedef int (*talloc_destructor_t)(void *);
96 struct talloc_chunk {
97 struct talloc_chunk *next, *prev;
98 struct talloc_chunk *parent, *child;
99 struct talloc_reference_handle *refs;
100 size_t size;
101 unsigned magic;
102 talloc_destructor_t destructor;
103 const char *name;
104 };
106 /* panic if we get a bad magic value */
107 static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
108 {
109 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1;
110 if (tc->magic != TALLOC_MAGIC) {
111 if (tc->magic == TALLOC_MAGIC_FREE) {
112 TALLOC_ABORT("Bad talloc magic value - double free");
113 } else {
114 TALLOC_ABORT("Bad talloc magic value - unknown value");
115 }
116 }
118 return tc;
119 }
121 /* hook into the front of the list */
122 #define _TLIST_ADD(list, p) \
123 do { \
124 if (!(list)) { \
125 (list) = (p); \
126 (p)->next = (p)->prev = NULL; \
127 } else { \
128 (list)->prev = (p); \
129 (p)->next = (list); \
130 (p)->prev = NULL; \
131 (list) = (p); \
132 }\
133 } while (0)
135 /* remove an element from a list - element doesn't have to be in list. */
136 #define _TLIST_REMOVE(list, p) \
137 do { \
138 if ((p) == (list)) { \
139 (list) = (p)->next; \
140 if (list) (list)->prev = NULL; \
141 } else { \
142 if ((p)->prev) (p)->prev->next = (p)->next; \
143 if ((p)->next) (p)->next->prev = (p)->prev; \
144 } \
145 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
146 } while (0)
149 /*
150 return the parent chunk of a pointer
151 */
152 static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
153 {
154 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
155 while (tc->prev) tc=tc->prev;
156 return tc->parent;
157 }
159 void *talloc_parent(const void *ptr)
160 {
161 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
162 return (void *)(tc+1);
163 }
165 /*
166 Allocate a bit of memory as a child of an existing pointer
167 */
168 void *_talloc(const void *context, size_t size)
169 {
170 struct talloc_chunk *tc;
172 if (context == NULL) {
173 context = null_context;
174 }
176 if (size >= MAX_TALLOC_SIZE) {
177 return NULL;
178 }
180 tc = malloc(sizeof(*tc)+size);
181 if (tc == NULL) {
182 if (malloc_fail_handler)
183 if (malloc_fail_handler(malloc_fail_data))
184 tc = malloc(sizeof(*tc)+size);
185 if (!tc)
186 return NULL;
187 }
189 tc->size = size;
190 tc->magic = TALLOC_MAGIC;
191 tc->destructor = NULL;
192 tc->child = NULL;
193 tc->name = NULL;
194 tc->refs = NULL;
196 if (context) {
197 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
199 tc->parent = parent;
201 if (parent->child) {
202 parent->child->parent = NULL;
203 }
205 _TLIST_ADD(parent->child, tc);
206 } else {
207 tc->next = tc->prev = tc->parent = NULL;
208 }
210 return (void *)(tc+1);
211 }
214 /*
215 setup a destructor to be called on free of a pointer
216 the destructor should return 0 on success, or -1 on failure.
217 if the destructor fails then the free is failed, and the memory can
218 be continued to be used
219 */
220 void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
221 {
222 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
223 tc->destructor = destructor;
224 }
226 /*
227 increase the reference count on a piece of memory.
228 */
229 void talloc_increase_ref_count(const void *ptr)
230 {
231 talloc_reference(null_context, ptr);
232 }
234 /*
235 helper for talloc_reference()
236 */
237 static int talloc_reference_destructor(void *ptr)
238 {
239 struct talloc_reference_handle *handle = ptr;
240 struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
241 struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
242 if (tc1->destructor != (talloc_destructor_t)-1) {
243 tc1->destructor = NULL;
244 }
245 _TLIST_REMOVE(tc2->refs, handle);
246 talloc_free(handle);
247 return 0;
248 }
250 /*
251 make a secondary reference to a pointer, hanging off the given context.
252 the pointer remains valid until both the original caller and this given
253 context are freed.
255 the major use for this is when two different structures need to reference the
256 same underlying data, and you want to be able to free the two instances separately,
257 and in either order
258 */
259 void *talloc_reference(const void *context, const void *ptr)
260 {
261 struct talloc_chunk *tc;
262 struct talloc_reference_handle *handle;
263 if (ptr == NULL) return NULL;
265 tc = talloc_chunk_from_ptr(ptr);
266 handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE);
268 if (handle == NULL) return NULL;
270 /* note that we hang the destructor off the handle, not the
271 main context as that allows the caller to still setup their
272 own destructor on the context if they want to */
273 talloc_set_destructor(handle, talloc_reference_destructor);
274 handle->ptr = discard_const_p(void, ptr);
275 _TLIST_ADD(tc->refs, handle);
276 return handle->ptr;
277 }
279 /*
280 remove a secondary reference to a pointer. This undo's what
281 talloc_reference() has done. The context and pointer arguments
282 must match those given to a talloc_reference()
283 */
284 static int talloc_unreference(const void *context, const void *ptr)
285 {
286 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
287 struct talloc_reference_handle *h;
289 if (context == NULL) {
290 context = null_context;
291 }
293 for (h=tc->refs;h;h=h->next) {
294 struct talloc_chunk *p = talloc_parent_chunk(h);
295 if ((p==NULL && context==NULL) || p+1 == context) break;
296 }
297 if (h == NULL) {
298 return -1;
299 }
301 talloc_set_destructor(h, NULL);
302 _TLIST_REMOVE(tc->refs, h);
303 talloc_free(h);
304 return 0;
305 }
307 /*
308 remove a specific parent context from a pointer. This is a more
309 controlled varient of talloc_free()
310 */
311 int talloc_unlink(const void *context, void *ptr)
312 {
313 struct talloc_chunk *tc_p, *new_p;
314 void *new_parent;
316 if (ptr == NULL) {
317 return -1;
318 }
320 if (context == NULL) {
321 context = null_context;
322 }
324 if (talloc_unreference(context, ptr) == 0) {
325 return 0;
326 }
328 if (context == NULL) {
329 if (talloc_parent_chunk(ptr) != NULL) {
330 return -1;
331 }
332 } else {
333 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
334 return -1;
335 }
336 }
338 tc_p = talloc_chunk_from_ptr(ptr);
340 if (tc_p->refs == NULL) {
341 return talloc_free(ptr);
342 }
344 new_p = talloc_parent_chunk(tc_p->refs);
345 if (new_p) {
346 new_parent = new_p+1;
347 } else {
348 new_parent = NULL;
349 }
351 if (talloc_unreference(new_parent, ptr) != 0) {
352 return -1;
353 }
355 talloc_steal(new_parent, ptr);
357 return 0;
358 }
360 /*
361 add a name to an existing pointer - va_list version
362 */
363 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
365 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
366 {
367 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
368 tc->name = talloc_vasprintf(ptr, fmt, ap);
369 if (tc->name) {
370 talloc_set_name_const(tc->name, ".name");
371 }
372 }
374 /*
375 add a name to an existing pointer
376 */
377 void talloc_set_name(const void *ptr, const char *fmt, ...)
378 {
379 va_list ap;
380 va_start(ap, fmt);
381 talloc_set_name_v(ptr, fmt, ap);
382 va_end(ap);
383 }
385 /*
386 more efficient way to add a name to a pointer - the name must point to a
387 true string constant
388 */
389 void talloc_set_name_const(const void *ptr, const char *name)
390 {
391 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
392 tc->name = name;
393 }
395 /*
396 create a named talloc pointer. Any talloc pointer can be named, and
397 talloc_named() operates just like talloc() except that it allows you
398 to name the pointer.
399 */
400 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
401 {
402 va_list ap;
403 void *ptr;
405 ptr = _talloc(context, size);
406 if (ptr == NULL) return NULL;
408 va_start(ap, fmt);
409 talloc_set_name_v(ptr, fmt, ap);
410 va_end(ap);
412 return ptr;
413 }
415 /*
416 create a named talloc pointer. Any talloc pointer can be named, and
417 talloc_named() operates just like talloc() except that it allows you
418 to name the pointer.
419 */
420 void *talloc_named_const(const void *context, size_t size, const char *name)
421 {
422 void *ptr;
424 ptr = _talloc(context, size);
425 if (ptr == NULL) {
426 return NULL;
427 }
429 talloc_set_name_const(ptr, name);
431 return ptr;
432 }
434 /*
435 return the name of a talloc ptr, or "UNNAMED"
436 */
437 const char *talloc_get_name(const void *ptr)
438 {
439 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
440 if (tc->name == TALLOC_MAGIC_REFERENCE) {
441 return ".reference";
442 }
443 if (tc->name) {
444 return tc->name;
445 }
446 return "UNNAMED";
447 }
450 /*
451 check if a pointer has the given name. If it does, return the pointer,
452 otherwise return NULL
453 */
454 void *talloc_check_name(const void *ptr, const char *name)
455 {
456 const char *pname;
457 if (ptr == NULL) return NULL;
458 pname = talloc_get_name(ptr);
459 if (pname == name || strcmp(pname, name) == 0) {
460 return discard_const_p(void, ptr);
461 }
462 return NULL;
463 }
466 /*
467 this is for compatibility with older versions of talloc
468 */
469 void *talloc_init(const char *fmt, ...)
470 {
471 va_list ap;
472 void *ptr;
474 ptr = _talloc(NULL, 0);
475 if (ptr == NULL) return NULL;
477 va_start(ap, fmt);
478 talloc_set_name_v(ptr, fmt, ap);
479 va_end(ap);
481 return ptr;
482 }
484 /*
485 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
486 should probably not be used in new code. It's in here to keep the talloc
487 code consistent across Samba 3 and 4.
488 */
489 void talloc_free_children(void *ptr)
490 {
491 struct talloc_chunk *tc;
493 if (ptr == NULL) {
494 return;
495 }
497 tc = talloc_chunk_from_ptr(ptr);
499 while (tc->child) {
500 /* we need to work out who will own an abandoned child
501 if it cannot be freed. In priority order, the first
502 choice is owner of any remaining reference to this
503 pointer, the second choice is our parent, and the
504 final choice is the null context. */
505 void *child = tc->child+1;
506 const void *new_parent = null_context;
507 if (tc->child->refs) {
508 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
509 if (p) new_parent = p+1;
510 }
511 if (talloc_free(child) == -1) {
512 if (new_parent == null_context) {
513 struct talloc_chunk *p = talloc_parent_chunk(ptr);
514 if (p) new_parent = p+1;
515 }
516 talloc_steal(new_parent, child);
517 }
518 }
519 }
521 /*
522 free a talloc pointer. This also frees all child pointers of this
523 pointer recursively
525 return 0 if the memory is actually freed, otherwise -1. The memory
526 will not be freed if the ref_count is > 1 or the destructor (if
527 any) returns non-zero
528 */
529 int talloc_free(void *ptr)
530 {
531 struct talloc_chunk *tc;
533 if (ptr == NULL) {
534 return -1;
535 }
537 tc = talloc_chunk_from_ptr(ptr);
539 if (tc->refs) {
540 talloc_reference_destructor(tc->refs);
541 return -1;
542 }
544 if (tc->destructor) {
545 talloc_destructor_t d = tc->destructor;
546 if (d == (talloc_destructor_t)-1) {
547 return -1;
548 }
549 tc->destructor = (talloc_destructor_t)-1;
550 if (d(ptr) == -1) {
551 tc->destructor = d;
552 return -1;
553 }
554 tc->destructor = NULL;
555 }
557 talloc_free_children(ptr);
559 if (tc->parent) {
560 _TLIST_REMOVE(tc->parent->child, tc);
561 if (tc->parent->child) {
562 tc->parent->child->parent = tc->parent;
563 }
564 } else {
565 if (tc->prev) tc->prev->next = tc->next;
566 if (tc->next) tc->next->prev = tc->prev;
567 }
569 tc->magic = TALLOC_MAGIC_FREE;
571 free(tc);
572 return 0;
573 }
577 /*
578 A talloc version of realloc. The context argument is only used if
579 ptr is NULL
580 */
581 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
582 {
583 struct talloc_chunk *tc;
584 void *new_ptr;
586 /* size zero is equivalent to free() */
587 if (size == 0) {
588 talloc_free(ptr);
589 return NULL;
590 }
592 if (size >= MAX_TALLOC_SIZE) {
593 return NULL;
594 }
596 /* realloc(NULL) is equavalent to malloc() */
597 if (ptr == NULL) {
598 return talloc_named_const(context, size, name);
599 }
601 tc = talloc_chunk_from_ptr(ptr);
603 /* don't allow realloc on referenced pointers */
604 if (tc->refs) {
605 return NULL;
606 }
608 /* by resetting magic we catch users of the old memory */
609 tc->magic = TALLOC_MAGIC_FREE;
611 #if ALWAYS_REALLOC
612 new_ptr = malloc(size + sizeof(*tc));
613 if (!new_ptr) {
614 tc->magic = TALLOC_MAGIC;
615 if (malloc_fail_handler)
616 if (malloc_fail_handler(malloc_fail_data))
617 new_ptr = malloc(size + sizeof(*tc));
618 }
619 if (new_ptr) {
620 memcpy(new_ptr, tc, tc->size + sizeof(*tc));
621 free(tc);
622 }
623 #else
624 new_ptr = realloc(tc, size + sizeof(*tc));
625 if (!new_ptr) {
626 tc->magic = TALLOC_MAGIC;
627 if (malloc_fail_handler)
628 if (malloc_fail_handler(malloc_fail_data))
629 new_ptr = realloc(tc, size + sizeof(*tc));
630 }
631 #endif
632 if (!new_ptr) {
633 tc->magic = TALLOC_MAGIC;
634 return NULL;
635 }
637 tc = new_ptr;
638 tc->magic = TALLOC_MAGIC;
639 if (tc->parent) {
640 tc->parent->child = new_ptr;
641 }
642 if (tc->child) {
643 tc->child->parent = new_ptr;
644 }
646 if (tc->prev) {
647 tc->prev->next = tc;
648 }
649 if (tc->next) {
650 tc->next->prev = tc;
651 }
653 tc->size = size;
654 talloc_set_name_const(tc+1, name);
656 return (void *)(tc+1);
657 }
659 /*
660 move a lump of memory from one talloc context to another return the
661 ptr on success, or NULL if it could not be transferred.
662 passing NULL as ptr will always return NULL with no side effects.
663 */
664 void *talloc_steal(const void *new_ctx, const void *ptr)
665 {
666 struct talloc_chunk *tc, *new_tc;
668 if (!ptr) {
669 return NULL;
670 }
672 if (new_ctx == NULL) {
673 new_ctx = null_context;
674 }
676 tc = talloc_chunk_from_ptr(ptr);
678 if (new_ctx == NULL) {
679 if (tc->parent) {
680 _TLIST_REMOVE(tc->parent->child, tc);
681 if (tc->parent->child) {
682 tc->parent->child->parent = tc->parent;
683 }
684 } else {
685 if (tc->prev) tc->prev->next = tc->next;
686 if (tc->next) tc->next->prev = tc->prev;
687 }
689 tc->parent = tc->next = tc->prev = NULL;
690 return discard_const_p(void, ptr);
691 }
693 new_tc = talloc_chunk_from_ptr(new_ctx);
695 if (tc == new_tc) {
696 return discard_const_p(void, ptr);
697 }
699 if (tc->parent) {
700 _TLIST_REMOVE(tc->parent->child, tc);
701 if (tc->parent->child) {
702 tc->parent->child->parent = tc->parent;
703 }
704 } else {
705 if (tc->prev) tc->prev->next = tc->next;
706 if (tc->next) tc->next->prev = tc->prev;
707 }
709 tc->parent = new_tc;
710 if (new_tc->child) new_tc->child->parent = NULL;
711 _TLIST_ADD(new_tc->child, tc);
713 return discard_const_p(void, ptr);
714 }
716 /*
717 return the total size of a talloc pool (subtree)
718 */
719 off_t talloc_total_size(const void *ptr)
720 {
721 off_t total = 0;
722 struct talloc_chunk *c, *tc;
724 if (ptr == NULL) {
725 ptr = null_context;
726 }
727 if (ptr == NULL) {
728 return 0;
729 }
731 tc = talloc_chunk_from_ptr(ptr);
733 total = tc->size;
734 for (c=tc->child;c;c=c->next) {
735 total += talloc_total_size(c+1);
736 }
737 return total;
738 }
740 /*
741 return the total number of blocks in a talloc pool (subtree)
742 */
743 off_t talloc_total_blocks(const void *ptr)
744 {
745 off_t total = 0;
746 struct talloc_chunk *c, *tc;
748 if (ptr == NULL) {
749 ptr = null_context;
750 }
751 if (ptr == NULL) {
752 return 0;
753 }
754 tc = talloc_chunk_from_ptr(ptr);
756 total++;
757 for (c=tc->child;c;c=c->next) {
758 total += talloc_total_blocks(c+1);
759 }
760 return total;
761 }
763 /*
764 return the number of external references to a pointer
765 */
766 static int talloc_reference_count(const void *ptr)
767 {
768 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
769 struct talloc_reference_handle *h;
770 int ret = 0;
772 for (h=tc->refs;h;h=h->next) {
773 ret++;
774 }
775 return ret;
776 }
778 /*
779 report on memory usage by all children of a pointer, giving a full tree view
780 */
781 void talloc_report_depth(const void *ptr, FILE *f, int depth)
782 {
783 struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
785 for (c=tc->child;c;c=c->next) {
786 if (c->name == TALLOC_MAGIC_REFERENCE) {
787 struct talloc_reference_handle *handle = (void *)(c+1);
788 const char *name2 = talloc_get_name(handle->ptr);
789 fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
790 } else {
791 const char *name = talloc_get_name(c+1);
792 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
793 depth*4, "",
794 name,
795 (unsigned long)talloc_total_size(c+1),
796 (unsigned long)talloc_total_blocks(c+1),
797 talloc_reference_count(c+1));
798 talloc_report_depth(c+1, f, depth+1);
799 }
800 }
802 }
804 /*
805 report on memory usage by all children of a pointer, giving a full tree view
806 */
807 void talloc_report_full(const void *ptr, FILE *f)
808 {
809 if (ptr == NULL) {
810 ptr = null_context;
811 }
812 if (ptr == NULL) return;
814 fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
815 talloc_get_name(ptr),
816 (unsigned long)talloc_total_size(ptr),
817 (unsigned long)talloc_total_blocks(ptr));
819 talloc_report_depth(ptr, f, 1);
820 fflush(f);
821 }
823 /*
824 report on memory usage by all children of a pointer
825 */
826 void talloc_report(const void *ptr, FILE *f)
827 {
828 struct talloc_chunk *c, *tc;
830 if (ptr == NULL) {
831 ptr = null_context;
832 }
833 if (ptr == NULL) return;
835 fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n",
836 talloc_get_name(ptr),
837 (unsigned long)talloc_total_size(ptr),
838 (unsigned long)talloc_total_blocks(ptr));
840 tc = talloc_chunk_from_ptr(ptr);
842 for (c=tc->child;c;c=c->next) {
843 fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
844 talloc_get_name(c+1),
845 (unsigned long)talloc_total_size(c+1),
846 (unsigned long)talloc_total_blocks(c+1));
847 }
848 fflush(f);
849 }
851 /*
852 report on any memory hanging off the null context
853 */
854 static void talloc_report_null(void)
855 {
856 if (talloc_total_size(null_context) != 0) {
857 talloc_report(null_context, stderr);
858 }
859 }
861 /*
862 report on any memory hanging off the null context
863 */
864 static void talloc_report_null_full(void)
865 {
866 if (talloc_total_size(null_context) != 0) {
867 talloc_report_full(null_context, stderr);
868 }
869 }
871 /*
872 enable tracking of the NULL context
873 */
874 void talloc_enable_null_tracking(void)
875 {
876 if (null_context == NULL) {
877 null_context = talloc_named_const(NULL, 0, "null_context");
878 }
879 }
881 /*
882 enable leak reporting on exit
883 */
884 void talloc_enable_leak_report(void)
885 {
886 talloc_enable_null_tracking();
887 atexit(talloc_report_null);
888 }
890 /*
891 enable full leak reporting on exit
892 */
893 void talloc_enable_leak_report_full(void)
894 {
895 talloc_enable_null_tracking();
896 atexit(talloc_report_null_full);
897 }
899 /*
900 talloc and zero memory.
901 */
902 void *_talloc_zero(const void *ctx, size_t size, const char *name)
903 {
904 void *p = talloc_named_const(ctx, size, name);
906 if (p) {
907 memset(p, '\0', size);
908 }
910 return p;
911 }
914 /*
915 memdup with a talloc.
916 */
917 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
918 {
919 void *newp = talloc_named_const(t, size, name);
921 if (newp) {
922 memcpy(newp, p, size);
923 }
925 return newp;
926 }
928 /*
929 strdup with a talloc
930 */
931 char *talloc_strdup(const void *t, const char *p)
932 {
933 char *ret;
934 if (!p) {
935 return NULL;
936 }
937 ret = talloc_memdup(t, p, strlen(p) + 1);
938 if (ret) {
939 talloc_set_name_const(ret, ret);
940 }
941 return ret;
942 }
944 /*
945 strndup with a talloc
946 */
947 char *talloc_strndup(const void *t, const char *p, size_t n)
948 {
949 size_t len;
950 char *ret;
952 for (len=0; p[len] && len<n; len++) ;
954 ret = _talloc(t, len + 1);
955 if (!ret) { return NULL; }
956 memcpy(ret, p, len);
957 ret[len] = 0;
958 talloc_set_name_const(ret, ret);
959 return ret;
960 }
962 #ifndef VA_COPY
963 #ifdef HAVE_VA_COPY
964 #define VA_COPY(dest, src) va_copy(dest, src)
965 #elif defined(HAVE___VA_COPY)
966 #define VA_COPY(dest, src) __va_copy(dest, src)
967 #else
968 #define VA_COPY(dest, src) (dest) = (src)
969 #endif
970 #endif
972 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
973 {
974 int len;
975 char *ret;
976 va_list ap2;
978 VA_COPY(ap2, ap);
980 len = vsnprintf(NULL, 0, fmt, ap2);
982 ret = _talloc(t, len+1);
983 if (ret) {
984 VA_COPY(ap2, ap);
985 vsnprintf(ret, len+1, fmt, ap2);
986 talloc_set_name_const(ret, ret);
987 }
989 return ret;
990 }
993 /*
994 Perform string formatting, and return a pointer to newly allocated
995 memory holding the result, inside a memory pool.
996 */
997 char *talloc_asprintf(const void *t, const char *fmt, ...)
998 {
999 va_list ap;
1000 char *ret;
1002 va_start(ap, fmt);
1003 ret = talloc_vasprintf(t, fmt, ap);
1004 va_end(ap);
1005 return ret;
1009 /**
1010 * Realloc @p s to append the formatted result of @p fmt and @p ap,
1011 * and return @p s, which may have moved. Good for gradually
1012 * accumulating output into a string buffer.
1013 **/
1015 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1017 static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1019 struct talloc_chunk *tc;
1020 int len, s_len;
1021 va_list ap2;
1023 if (s == NULL) {
1024 return talloc_vasprintf(NULL, fmt, ap);
1027 tc = talloc_chunk_from_ptr(s);
1029 VA_COPY(ap2, ap);
1031 s_len = tc->size - 1;
1032 len = vsnprintf(NULL, 0, fmt, ap2);
1034 s = talloc_realloc(NULL, s, char, s_len + len+1);
1035 if (!s) return NULL;
1037 VA_COPY(ap2, ap);
1039 vsnprintf(s+s_len, len+1, fmt, ap2);
1040 talloc_set_name_const(s, s);
1042 return s;
1045 /*
1046 Realloc @p s to append the formatted result of @p fmt and return @p
1047 s, which may have moved. Good for gradually accumulating output
1048 into a string buffer.
1049 */
1050 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1052 va_list ap;
1054 va_start(ap, fmt);
1055 s = talloc_vasprintf_append(s, fmt, ap);
1056 va_end(ap);
1057 return s;
1060 /*
1061 alloc an array, checking for integer overflow in the array size
1062 */
1063 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1065 if (count >= MAX_TALLOC_SIZE/el_size) {
1066 return NULL;
1068 return talloc_named_const(ctx, el_size * count, name);
1071 /*
1072 alloc an zero array, checking for integer overflow in the array size
1073 */
1074 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1076 if (count >= MAX_TALLOC_SIZE/el_size) {
1077 return NULL;
1079 return _talloc_zero(ctx, el_size * count, name);
1083 /*
1084 realloc an array, checking for integer overflow in the array size
1085 */
1086 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1088 if (count >= MAX_TALLOC_SIZE/el_size) {
1089 return NULL;
1091 return _talloc_realloc(ctx, ptr, el_size * count, name);
1094 /*
1095 a function version of talloc_realloc(), so it can be passed as a function pointer
1096 to libraries that want a realloc function (a realloc function encapsulates
1097 all the basic capabilities of an allocation library, which is why this is useful)
1098 */
1099 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1101 return _talloc_realloc(context, ptr, size, NULL);
1105 static void talloc_autofree(void)
1107 talloc_free(cleanup_context);
1108 cleanup_context = NULL;
1111 /*
1112 return a context which will be auto-freed on exit
1113 this is useful for reducing the noise in leak reports
1114 */
1115 void *talloc_autofree_context(void)
1117 if (cleanup_context == NULL) {
1118 cleanup_context = talloc_named_const(NULL, 0, "autofree_context");
1119 atexit(talloc_autofree);
1121 return cleanup_context;
1124 size_t talloc_get_size(const void *context)
1126 struct talloc_chunk *tc;
1128 if (context == NULL)
1129 return 0;
1131 tc = talloc_chunk_from_ptr(context);
1133 return tc->size;
1136 talloc_fail_handler *talloc_set_fail_handler(talloc_fail_handler *handler,
1137 void *data)
1139 talloc_fail_handler *old = malloc_fail_handler;
1140 malloc_fail_handler = handler;
1141 malloc_fail_data = data;
1142 return old;