]> git.ozlabs.org Git - ccan/blob - ccan/talloc/talloc.c
a5cd447e908b79cafc6709d860eac959715a9150
[ccan] / ccan / talloc / talloc.c
1 /* 
2    Samba Unix SMB/CIFS implementation.
3
4    Samba trivial allocation library - new interface
5
6    NOTE: Please read talloc_guide.txt for full documentation
7
8    Copyright (C) Andrew Tridgell 2004
9    Copyright (C) Stefan Metzmacher 2006
10    
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
14    
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 2 of the License, or (at your option) any later version.
19
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.
24
25    You should have received a copy of the GNU Lesser General Public
26    License along with this library; if not, write to the Free Software
27    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 */
29
30 /*
31   inspired by http://swapped.cc/halloc/
32 */
33
34 #include "talloc.h"
35 #include <string.h>
36 #include <stdint.h>
37 #include <errno.h>
38 #include <sys/types.h>
39 #include <unistd.h>
40
41 /* use this to force every realloc to change the pointer, to stress test
42    code that might not cope */
43 #define ALWAYS_REALLOC 0
44
45
46 #define MAX_TALLOC_SIZE 0x10000000
47 #define TALLOC_MAGIC 0xe814ec70
48 #define TALLOC_FLAG_FREE 0x01
49 #define TALLOC_FLAG_LOOP 0x02
50 #define TALLOC_FLAG_EXT_ALLOC 0x04
51 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
52
53 /* by default we abort when given a bad pointer (such as when talloc_free() is called 
54    on a pointer that came from malloc() */
55 #ifndef TALLOC_ABORT
56 #define TALLOC_ABORT(reason) abort()
57 #endif
58
59 #ifndef discard_const_p
60 #if defined(INTPTR_MIN)
61 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
62 #else
63 # define discard_const_p(type, ptr) ((type *)(ptr))
64 #endif
65 #endif
66
67 /* these macros gain us a few percent of speed on gcc */
68 #if HAVE_BUILTIN_EXPECT
69 /* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
70    as its first argument */
71 #define likely(x)   __builtin_expect(!!(x), 1)
72 #define unlikely(x) __builtin_expect(!!(x), 0)
73 #else
74 #define likely(x) x
75 #define unlikely(x) x
76 #endif
77
78 /* this null_context is only used if talloc_enable_leak_report() or
79    talloc_enable_leak_report_full() is called, otherwise it remains
80    NULL
81 */
82 static void *null_context;
83 static pid_t *autofree_context;
84
85 static void *(*tc_external_realloc)(const void *parent, void *ptr, size_t size);
86 static void (*tc_lock)(const void *ctx);
87 static void (*tc_unlock)(void);
88
89 struct talloc_reference_handle {
90         struct talloc_reference_handle *next, *prev;
91         void *ptr;
92 };
93
94 typedef int (*talloc_destructor_t)(void *);
95
96 struct talloc_chunk {
97         struct talloc_chunk *next, *prev;
98         struct talloc_chunk *parent, *child;
99         struct talloc_reference_handle *refs;
100         talloc_destructor_t destructor;
101         const char *name;
102         size_t size;
103         unsigned flags;
104 };
105
106 /* 16 byte alignment seems to keep everyone happy */
107 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
108 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
109
110 /* panic if we get a bad magic value */
111 static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
112 {
113         const char *pp = (const char *)ptr;
114         struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
115         if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) { 
116                 if (tc->flags & TALLOC_FLAG_FREE) {
117                         TALLOC_ABORT("Bad talloc magic value - double free"); 
118                 } else {
119                         TALLOC_ABORT("Bad talloc magic value - unknown value"); 
120                 }
121         }
122         return tc;
123 }
124
125 /* hook into the front of the list */
126 #define _TLIST_ADD(list, p) \
127 do { \
128         if (!(list)) { \
129                 (list) = (p); \
130                 (p)->next = (p)->prev = NULL; \
131         } else { \
132                 (list)->prev = (p); \
133                 (p)->next = (list); \
134                 (p)->prev = NULL; \
135                 (list) = (p); \
136         }\
137 } while (0)
138
139 /* remove an element from a list - element doesn't have to be in list. */
140 #define _TLIST_REMOVE(list, p) \
141 do { \
142         if ((p) == (list)) { \
143                 (list) = (p)->next; \
144                 if (list) (list)->prev = NULL; \
145         } else { \
146                 if ((p)->prev) (p)->prev->next = (p)->next; \
147                 if ((p)->next) (p)->next->prev = (p)->prev; \
148         } \
149         if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
150 } while (0)
151
152 static int locked;
153 static inline void lock(const void *p)
154 {
155         if (tc_lock && p) {
156                 struct talloc_chunk *tc = talloc_chunk_from_ptr(p);
157
158                 if (tc->flags & TALLOC_FLAG_EXT_ALLOC) {
159                         if (locked)
160                                 TALLOC_ABORT("nested locking");
161                         tc_lock(tc);
162                         locked = 1;
163                 }
164         }
165 }
166
167 static inline void unlock(void)
168 {
169         if (locked) {
170                 tc_unlock();
171                 locked = 0;
172         }
173 }
174
175 /*
176   return the parent chunk of a pointer
177 */
178 static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
179 {
180         struct talloc_chunk *tc;
181
182         if (unlikely(ptr == NULL)) {
183                 return NULL;
184         }
185
186         tc = talloc_chunk_from_ptr(ptr);
187         while (tc->prev) tc=tc->prev;
188
189         return tc->parent;
190 }
191
192 /* This version doesn't do locking, so you must already have it. */
193 static void *talloc_parent_nolock(const void *ptr)
194 {
195         struct talloc_chunk *tc;
196
197         tc = talloc_parent_chunk(ptr);
198         return tc ? TC_PTR_FROM_CHUNK(tc) : NULL;
199 }
200
201 void *talloc_parent(const void *ptr)
202 {
203         void *parent;
204
205         lock(ptr);
206         parent = talloc_parent_nolock(ptr);
207         unlock();
208         return parent;
209 }
210
211 /*
212   find parents name
213 */
214 const char *talloc_parent_name(const void *ptr)
215 {
216         struct talloc_chunk *tc;
217
218         lock(ptr);
219         tc = talloc_parent_chunk(ptr);
220         unlock();
221
222         return tc? tc->name : NULL;
223 }
224
225 static void *init_talloc(struct talloc_chunk *parent,
226                          struct talloc_chunk *tc,
227                          size_t size, int external)
228 {
229         if (unlikely(tc == NULL))
230                 return NULL;
231
232         tc->size = size;
233         tc->flags = TALLOC_MAGIC;
234         if (external)
235                 tc->flags |= TALLOC_FLAG_EXT_ALLOC;
236         tc->destructor = NULL;
237         tc->child = NULL;
238         tc->name = NULL;
239         tc->refs = NULL;
240
241         if (likely(parent)) {
242                 if (parent->child) {
243                         parent->child->parent = NULL;
244                         tc->next = parent->child;
245                         tc->next->prev = tc;
246                 } else {
247                         tc->next = NULL;
248                 }
249                 tc->parent = parent;
250                 tc->prev = NULL;
251                 parent->child = tc;
252         } else {
253                 tc->next = tc->prev = tc->parent = NULL;
254         }
255
256         return TC_PTR_FROM_CHUNK(tc);
257 }
258
259 /* 
260    Allocate a bit of memory as a child of an existing pointer
261 */
262 static inline void *__talloc(const void *context, size_t size)
263 {
264         struct talloc_chunk *tc;
265         struct talloc_chunk *parent = NULL;
266         int external = 0;
267
268         if (unlikely(context == NULL)) {
269                 context = null_context;
270         }
271
272         if (unlikely(size >= MAX_TALLOC_SIZE)) {
273                 return NULL;
274         }
275
276         if (likely(context)) {
277                 parent = talloc_chunk_from_ptr(context);
278                 if (unlikely(parent->flags & TALLOC_FLAG_EXT_ALLOC)) {
279                         tc = tc_external_realloc(context, NULL,
280                                                  TC_HDR_SIZE+size);
281                         external = 1;
282                         goto alloc_done;
283                 }
284         }
285
286         tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
287 alloc_done:
288         return init_talloc(parent, tc, size, external);
289 }
290
291 /*
292   setup a destructor to be called on free of a pointer
293   the destructor should return 0 on success, or -1 on failure.
294   if the destructor fails then the free is failed, and the memory can
295   be continued to be used
296 */
297 void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
298 {
299         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
300         tc->destructor = destructor;
301 }
302
303 /*
304   increase the reference count on a piece of memory. 
305 */
306 int talloc_increase_ref_count(const void *ptr)
307 {
308         if (unlikely(!talloc_reference(null_context, ptr))) {
309                 return -1;
310         }
311         return 0;
312 }
313
314 /*
315   helper for talloc_reference()
316
317   this is referenced by a function pointer and should not be inline
318 */
319 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
320 {
321         struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
322         _TLIST_REMOVE(ptr_tc->refs, handle);
323         return 0;
324 }
325
326 /*
327    more efficient way to add a name to a pointer - the name must point to a 
328    true string constant
329 */
330 static inline void _talloc_set_name_const(const void *ptr, const char *name)
331 {
332         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
333         tc->name = name;
334 }
335
336 /*
337   internal talloc_named_const()
338 */
339 static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
340 {
341         void *ptr;
342
343         ptr = __talloc(context, size);
344         if (unlikely(ptr == NULL)) {
345                 return NULL;
346         }
347
348         _talloc_set_name_const(ptr, name);
349
350         return ptr;
351 }
352
353 /*
354   make a secondary reference to a pointer, hanging off the given context.
355   the pointer remains valid until both the original caller and this given
356   context are freed.
357   
358   the major use for this is when two different structures need to reference the 
359   same underlying data, and you want to be able to free the two instances separately,
360   and in either order
361 */
362 void *_talloc_reference(const void *context, const void *ptr)
363 {
364         struct talloc_chunk *tc;
365         struct talloc_reference_handle *handle;
366         if (unlikely(ptr == NULL)) return NULL;
367
368         lock(context);
369         tc = talloc_chunk_from_ptr(ptr);
370         handle = (struct talloc_reference_handle *)_talloc_named_const(context,
371                                                    sizeof(struct talloc_reference_handle),
372                                                    TALLOC_MAGIC_REFERENCE);
373         if (unlikely(handle == NULL)) {
374                 unlock();
375                 return NULL;
376         }
377
378         /* note that we hang the destructor off the handle, not the
379            main context as that allows the caller to still setup their
380            own destructor on the context if they want to */
381         talloc_set_destructor(handle, talloc_reference_destructor);
382         handle->ptr = discard_const_p(void, ptr);
383         _TLIST_ADD(tc->refs, handle);
384         unlock();
385         return handle->ptr;
386 }
387
388 /*
389   return 1 if ptr is a parent of context
390 */
391 static int _talloc_is_parent(const void *context, const void *ptr)
392 {
393         struct talloc_chunk *tc;
394
395         if (context == NULL) {
396                 return 0;
397         }
398
399         tc = talloc_chunk_from_ptr(context);
400         while (tc) {
401                 if (TC_PTR_FROM_CHUNK(tc) == ptr) {
402                         return 1;
403                 }
404                 while (tc && tc->prev) tc = tc->prev;
405                 if (tc) {
406                         tc = tc->parent;
407                 }
408         }
409         return 0;
410 }
411
412 /* 
413    move a lump of memory from one talloc context to another return the
414    ptr on success, or NULL if it could not be transferred.
415    passing NULL as ptr will always return NULL with no side effects.
416 */
417 static void *__talloc_steal(const void *new_ctx, const void *ptr)
418 {
419         struct talloc_chunk *tc, *new_tc;
420
421         if (unlikely(!ptr)) {
422                 return NULL;
423         }
424
425         if (unlikely(new_ctx == NULL)) {
426                 new_ctx = null_context;
427         }
428
429         tc = talloc_chunk_from_ptr(ptr);
430
431         if (unlikely(new_ctx == NULL)) {
432                 if (tc->parent) {
433                         _TLIST_REMOVE(tc->parent->child, tc);
434                         if (tc->parent->child) {
435                                 tc->parent->child->parent = tc->parent;
436                         }
437                 } else {
438                         if (tc->prev) tc->prev->next = tc->next;
439                         if (tc->next) tc->next->prev = tc->prev;
440                 }
441                 
442                 tc->parent = tc->next = tc->prev = NULL;
443                 return discard_const_p(void, ptr);
444         }
445
446         new_tc = talloc_chunk_from_ptr(new_ctx);
447
448         if (unlikely(tc == new_tc || tc->parent == new_tc)) {
449                 return discard_const_p(void, ptr);
450         }
451
452         if (tc->parent) {
453                 _TLIST_REMOVE(tc->parent->child, tc);
454                 if (tc->parent->child) {
455                         tc->parent->child->parent = tc->parent;
456                 }
457         } else {
458                 if (tc->prev) tc->prev->next = tc->next;
459                 if (tc->next) tc->next->prev = tc->prev;
460         }
461
462         tc->parent = new_tc;
463         if (new_tc->child) new_tc->child->parent = NULL;
464         _TLIST_ADD(new_tc->child, tc);
465
466         return discard_const_p(void, ptr);
467 }
468
469 /* 
470    internal talloc_free call
471 */
472 static inline int _talloc_free(const void *ptr)
473 {
474         struct talloc_chunk *tc;
475         void *oldparent = NULL;
476
477         if (unlikely(ptr == NULL)) {
478                 return -1;
479         }
480
481         tc = talloc_chunk_from_ptr(ptr);
482
483         if (unlikely(tc->refs)) {
484                 int is_child;
485                 /* check this is a reference from a child or grantchild
486                  * back to it's parent or grantparent
487                  *
488                  * in that case we need to remove the reference and
489                  * call another instance of talloc_free() on the current
490                  * pointer.
491                  */
492                 is_child = _talloc_is_parent(tc->refs, ptr);
493                 _talloc_free(tc->refs);
494                 if (is_child) {
495                         return _talloc_free(ptr);
496                 }
497                 return -1;
498         }
499
500         if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
501                 /* we have a free loop - stop looping */
502                 return 0;
503         }
504
505         if (unlikely(tc->destructor)) {
506                 talloc_destructor_t d = tc->destructor;
507                 if (d == (talloc_destructor_t)-1) {
508                         return -1;
509                 }
510                 tc->destructor = (talloc_destructor_t)-1;
511                 if (d(discard_const_p(void, ptr)) == -1) {
512                         tc->destructor = d;
513                         return -1;
514                 }
515                 tc->destructor = NULL;
516         }
517
518         if (unlikely(tc->flags & TALLOC_FLAG_EXT_ALLOC))
519                 oldparent = talloc_parent_nolock(ptr);
520
521         if (tc->parent) {
522                 _TLIST_REMOVE(tc->parent->child, tc);
523                 if (tc->parent->child) {
524                         tc->parent->child->parent = tc->parent;
525                 }
526         } else {
527                 if (tc->prev) tc->prev->next = tc->next;
528                 if (tc->next) tc->next->prev = tc->prev;
529         }
530
531         tc->flags |= TALLOC_FLAG_LOOP;
532
533         while (tc->child) {
534                 /* we need to work out who will own an abandoned child
535                    if it cannot be freed. In priority order, the first
536                    choice is owner of any remaining reference to this
537                    pointer, the second choice is our parent, and the
538                    final choice is the null context. */
539                 void *child = TC_PTR_FROM_CHUNK(tc->child);
540                 const void *new_parent = null_context;
541                 if (unlikely(tc->child->refs)) {
542                         struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
543                         if (p) new_parent = TC_PTR_FROM_CHUNK(p);
544                 }
545                 if (unlikely(_talloc_free(child) == -1)) {
546                         if (new_parent == null_context) {
547                                 struct talloc_chunk *p = talloc_parent_chunk(ptr);
548                                 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
549                         }
550                         __talloc_steal(new_parent, child);
551                 }
552         }
553
554         tc->flags |= TALLOC_FLAG_FREE;
555
556         if (unlikely(tc->flags & TALLOC_FLAG_EXT_ALLOC))
557                 tc_external_realloc(oldparent, tc, 0);
558         else
559                 free(tc);
560
561         return 0;
562 }
563
564 void *_talloc_steal(const void *new_ctx, const void *ptr)
565 {
566         void *p;
567
568         lock(new_ctx);
569         p = __talloc_steal(new_ctx, ptr);
570         unlock();
571         return p;
572 }
573
574 /*
575   remove a secondary reference to a pointer. This undo's what
576   talloc_reference() has done. The context and pointer arguments
577   must match those given to a talloc_reference()
578 */
579 static inline int talloc_unreference(const void *context, const void *ptr)
580 {
581         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
582         struct talloc_reference_handle *h;
583
584         if (unlikely(context == NULL)) {
585                 context = null_context;
586         }
587
588         for (h=tc->refs;h;h=h->next) {
589                 struct talloc_chunk *p = talloc_parent_chunk(h);
590                 if (p == NULL) {
591                         if (context == NULL) break;
592                 } else if (TC_PTR_FROM_CHUNK(p) == context) {
593                         break;
594                 }
595         }
596         if (h == NULL) {
597                 return -1;
598         }
599
600         return _talloc_free(h);
601 }
602
603 /*
604   remove a specific parent context from a pointer. This is a more
605   controlled varient of talloc_free()
606 */
607 int talloc_unlink(const void *context, void *ptr)
608 {
609         struct talloc_chunk *tc_p, *new_p;
610         void *new_parent;
611
612         if (ptr == NULL) {
613                 return -1;
614         }
615
616         if (context == NULL) {
617                 context = null_context;
618         }
619
620         lock(context);
621         if (talloc_unreference(context, ptr) == 0) {
622                 unlock();
623                 return 0;
624         }
625
626         if (context == NULL) {
627                 if (talloc_parent_chunk(ptr) != NULL) {
628                         unlock();
629                         return -1;
630                 }
631         } else {
632                 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
633                         unlock();
634                         return -1;
635                 }
636         }
637         
638         tc_p = talloc_chunk_from_ptr(ptr);
639
640         if (tc_p->refs == NULL) {
641                 int ret = _talloc_free(ptr);
642                 unlock();
643                 return ret;
644         }
645
646         new_p = talloc_parent_chunk(tc_p->refs);
647         if (new_p) {
648                 new_parent = TC_PTR_FROM_CHUNK(new_p);
649         } else {
650                 new_parent = NULL;
651         }
652
653         if (talloc_unreference(new_parent, ptr) != 0) {
654                 unlock();
655                 return -1;
656         }
657
658         __talloc_steal(new_parent, ptr);
659         unlock();
660
661         return 0;
662 }
663
664 /*
665   add a name to an existing pointer - va_list version
666 */
667 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
668
669 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
670 {
671         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
672         tc->name = talloc_vasprintf(ptr, fmt, ap);
673         if (likely(tc->name)) {
674                 _talloc_set_name_const(tc->name, ".name");
675         }
676         return tc->name;
677 }
678
679 /*
680   add a name to an existing pointer
681 */
682 const char *talloc_set_name(const void *ptr, const char *fmt, ...)
683 {
684         const char *name;
685         va_list ap;
686         va_start(ap, fmt);
687         name = talloc_set_name_v(ptr, fmt, ap);
688         va_end(ap);
689         return name;
690 }
691
692
693 /*
694   create a named talloc pointer. Any talloc pointer can be named, and
695   talloc_named() operates just like talloc() except that it allows you
696   to name the pointer.
697 */
698 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
699 {
700         va_list ap;
701         void *ptr;
702         const char *name;
703
704         lock(context);
705         ptr = __talloc(context, size);
706         unlock();
707         if (unlikely(ptr == NULL)) return NULL;
708
709         va_start(ap, fmt);
710         name = talloc_set_name_v(ptr, fmt, ap);
711         va_end(ap);
712
713         if (unlikely(name == NULL)) {
714                 talloc_free(ptr);
715                 return NULL;
716         }
717
718         return ptr;
719 }
720
721 /*
722   return the name of a talloc ptr, or "UNNAMED"
723 */
724 const char *talloc_get_name(const void *ptr)
725 {
726         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
727         if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
728                 return ".reference";
729         }
730         if (likely(tc->name)) {
731                 return tc->name;
732         }
733         return "UNNAMED";
734 }
735
736
737 /*
738   check if a pointer has the given name. If it does, return the pointer,
739   otherwise return NULL
740 */
741 void *talloc_check_name(const void *ptr, const char *name)
742 {
743         const char *pname;
744         if (unlikely(ptr == NULL)) return NULL;
745         pname = talloc_get_name(ptr);
746         if (likely(pname == name || strcmp(pname, name) == 0)) {
747                 return discard_const_p(void, ptr);
748         }
749         return NULL;
750 }
751
752
753 /*
754   this is for compatibility with older versions of talloc
755 */
756 void *talloc_init(const char *fmt, ...)
757 {
758         va_list ap;
759         void *ptr;
760         const char *name;
761
762         /*
763          * samba3 expects talloc_report_depth_cb(NULL, ...)
764          * reports all talloc'ed memory, so we need to enable
765          * null_tracking
766          */
767         talloc_enable_null_tracking();
768
769         ptr = __talloc(NULL, 0);
770         if (unlikely(ptr == NULL)) return NULL;
771
772         va_start(ap, fmt);
773         name = talloc_set_name_v(ptr, fmt, ap);
774         va_end(ap);
775
776         if (unlikely(name == NULL)) {
777                 talloc_free(ptr);
778                 return NULL;
779         }
780
781         return ptr;
782 }
783
784 /* 
785    Allocate a bit of memory as a child of an existing pointer
786 */
787 void *_talloc(const void *context, size_t size)
788 {
789         return __talloc(context, size);
790 }
791
792 /*
793   externally callable talloc_set_name_const()
794 */
795 void talloc_set_name_const(const void *ptr, const char *name)
796 {
797         _talloc_set_name_const(ptr, name);
798 }
799
800 /*
801   create a named talloc pointer. Any talloc pointer can be named, and
802   talloc_named() operates just like talloc() except that it allows you
803   to name the pointer.
804 */
805 void *talloc_named_const(const void *context, size_t size, const char *name)
806 {
807         void *p;
808         lock(context);
809         p = _talloc_named_const(context, size, name);
810         unlock();
811         return p;
812 }
813
814 /* 
815    free a talloc pointer. This also frees all child pointers of this 
816    pointer recursively
817
818    return 0 if the memory is actually freed, otherwise -1. The memory
819    will not be freed if the ref_count is > 1 or the destructor (if
820    any) returns non-zero
821 */
822 int talloc_free(const void *ptr)
823 {
824         int saved_errno = errno, ret;
825
826         lock(ptr);
827         ret = _talloc_free(discard_const_p(void, ptr));
828         unlock();
829         if (ret == 0)
830                 errno = saved_errno;
831         return ret;
832 }
833
834
835
836 /*
837   A talloc version of realloc. The context argument is only used if
838   ptr is NULL
839 */
840 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
841 {
842         struct talloc_chunk *tc;
843         void *new_ptr;
844
845         /* size zero is equivalent to free() */
846         if (unlikely(size == 0)) {
847                 talloc_free(ptr);
848                 return NULL;
849         }
850
851         if (unlikely(size >= MAX_TALLOC_SIZE)) {
852                 return NULL;
853         }
854
855         /* realloc(NULL) is equivalent to malloc() */
856         if (ptr == NULL) {
857                 return talloc_named_const(context, size, name);
858         }
859
860         tc = talloc_chunk_from_ptr(ptr);
861
862         /* don't allow realloc on referenced pointers */
863         if (unlikely(tc->refs)) {
864                 return NULL;
865         }
866
867         lock(ptr);
868         if (unlikely(tc->flags & TALLOC_FLAG_EXT_ALLOC)) {
869                 /* need to get parent before setting free flag. */
870                 void *parent = talloc_parent_nolock(ptr);
871                 tc->flags |= TALLOC_FLAG_FREE;
872                 new_ptr = tc_external_realloc(parent, tc, size + TC_HDR_SIZE);
873         } else {
874                 /* by resetting magic we catch users of the old memory */
875                 tc->flags |= TALLOC_FLAG_FREE;
876
877 #if ALWAYS_REALLOC
878                 new_ptr = malloc(size + TC_HDR_SIZE);
879                 if (new_ptr) {
880                         memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
881                         free(tc);
882                 }
883 #else
884                 new_ptr = realloc(tc, size + TC_HDR_SIZE);
885 #endif
886         }
887
888         if (unlikely(!new_ptr)) {       
889                 tc->flags &= ~TALLOC_FLAG_FREE; 
890                 unlock();
891                 return NULL; 
892         }
893
894         tc = (struct talloc_chunk *)new_ptr;
895         tc->flags &= ~TALLOC_FLAG_FREE; 
896         if (tc->parent) {
897                 tc->parent->child = tc;
898         }
899         if (tc->child) {
900                 tc->child->parent = tc;
901         }
902
903         if (tc->prev) {
904                 tc->prev->next = tc;
905         }
906         if (tc->next) {
907                 tc->next->prev = tc;
908         }
909
910         tc->size = size;
911         _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
912         unlock();
913
914         return TC_PTR_FROM_CHUNK(tc);
915 }
916
917 /*
918   a wrapper around talloc_steal() for situations where you are moving a pointer
919   between two structures, and want the old pointer to be set to NULL
920 */
921 void *_talloc_move(const void *new_ctx, const void *_pptr)
922 {
923         const void **pptr = discard_const_p(const void *,_pptr);
924         void *ret = _talloc_steal(new_ctx, *pptr);
925         (*pptr) = NULL;
926         return ret;
927 }
928
929 /*
930   return the total size of a talloc pool (subtree)
931 */
932 static size_t _talloc_total_size(const void *ptr)
933 {
934         size_t total = 0;
935         struct talloc_chunk *c, *tc;
936
937         tc = talloc_chunk_from_ptr(ptr);
938
939         if (tc->flags & TALLOC_FLAG_LOOP) {
940                 return 0;
941         }
942
943         tc->flags |= TALLOC_FLAG_LOOP;
944
945         total = tc->size;
946         for (c=tc->child;c;c=c->next) {
947                 total += _talloc_total_size(TC_PTR_FROM_CHUNK(c));
948         }
949
950         tc->flags &= ~TALLOC_FLAG_LOOP;
951
952         return total;
953 }
954
955 size_t talloc_total_size(const void *ptr)
956 {
957         size_t total;
958
959         if (ptr == NULL) {
960                 ptr = null_context;
961         }
962         if (ptr == NULL) {
963                 return 0;
964         }
965
966         lock(ptr);
967         total = _talloc_total_size(ptr);
968         unlock();
969         return total;
970 }       
971
972 /*
973   return the total number of blocks in a talloc pool (subtree)
974 */
975 static size_t _talloc_total_blocks(const void *ptr)
976 {
977         size_t total = 0;
978         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
979
980         if (tc->flags & TALLOC_FLAG_LOOP) {
981                 return 0;
982         }
983
984         tc->flags |= TALLOC_FLAG_LOOP;
985
986         total++;
987         for (c=tc->child;c;c=c->next) {
988                 total += _talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
989         }
990
991         tc->flags &= ~TALLOC_FLAG_LOOP;
992
993         return total;
994 }
995
996 size_t talloc_total_blocks(const void *ptr)
997 {
998         size_t total;
999
1000         lock(ptr);
1001         total = _talloc_total_blocks(ptr);
1002         unlock();
1003
1004         return total;
1005 }
1006
1007 static size_t _talloc_reference_count(const void *ptr)
1008 {
1009         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1010         struct talloc_reference_handle *h;
1011         size_t ret = 0;
1012
1013         for (h=tc->refs;h;h=h->next) {
1014                 ret++;
1015         }
1016         return ret;
1017 }
1018
1019 /*
1020   return the number of external references to a pointer
1021 */
1022 size_t talloc_reference_count(const void *ptr)
1023 {
1024         size_t ret;
1025
1026         lock(talloc_chunk_from_ptr(ptr));
1027         ret = _talloc_reference_count(ptr);
1028         unlock();
1029         return ret;
1030 }
1031
1032 /*
1033   report on memory usage by all children of a pointer, giving a full tree view
1034 */
1035 static void _talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1036                             void (*callback)(const void *ptr,
1037                                              int depth, int max_depth,
1038                                              int is_ref,
1039                                              void *private_data),
1040                             void *private_data)
1041 {
1042         struct talloc_chunk *c, *tc;
1043
1044         tc = talloc_chunk_from_ptr(ptr);
1045
1046         if (tc->flags & TALLOC_FLAG_LOOP) {
1047                 return;
1048         }
1049
1050         callback(ptr, depth, max_depth, 0, private_data);
1051
1052         if (max_depth >= 0 && depth >= max_depth) {
1053                 return;
1054         }
1055
1056         tc->flags |= TALLOC_FLAG_LOOP;
1057         for (c=tc->child;c;c=c->next) {
1058                 if (c->name == TALLOC_MAGIC_REFERENCE) {
1059                         struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1060                         callback(h->ptr, depth + 1, max_depth, 1, private_data);
1061                 } else {
1062                         _talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1063                 }
1064         }
1065         tc->flags &= ~TALLOC_FLAG_LOOP;
1066 }
1067
1068 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1069                             void (*callback)(const void *ptr,
1070                                              int depth, int max_depth,
1071                                              int is_ref,
1072                                              void *private_data),
1073                             void *private_data)
1074 {
1075         if (ptr == NULL) {
1076                 ptr = null_context;
1077         }
1078         if (ptr == NULL) return;
1079
1080         lock(ptr);
1081         _talloc_report_depth_cb(ptr, depth, max_depth, callback, private_data);
1082         unlock();
1083 }
1084
1085 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1086 {
1087         const char *name = talloc_get_name(ptr);
1088         FILE *f = (FILE *)_f;
1089
1090         if (is_ref) {
1091                 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1092                 return;
1093         }
1094
1095         if (depth == 0) {
1096                 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", 
1097                         (max_depth < 0 ? "full " :""), name,
1098                         (unsigned long)_talloc_total_size(ptr),
1099                         (unsigned long)_talloc_total_blocks(ptr));
1100                 return;
1101         }
1102
1103         fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", 
1104                 depth*4, "",
1105                 name,
1106                 (unsigned long)_talloc_total_size(ptr),
1107                 (unsigned long)_talloc_total_blocks(ptr),
1108                 (int)_talloc_reference_count(ptr), ptr);
1109
1110 #if 0
1111         fprintf(f, "content: ");
1112         if (talloc_total_size(ptr)) {
1113                 int tot = talloc_total_size(ptr);
1114                 int i;
1115
1116                 for (i = 0; i < tot; i++) {
1117                         if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1118                                 fprintf(f, "%c", ((char *)ptr)[i]);
1119                         } else {
1120                                 fprintf(f, "~%02x", ((char *)ptr)[i]);
1121                         }
1122                 }
1123         }
1124         fprintf(f, "\n");
1125 #endif
1126 }
1127
1128 /*
1129   report on memory usage by all children of a pointer, giving a full tree view
1130 */
1131 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1132 {
1133         talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1134         fflush(f);
1135 }
1136
1137 /*
1138   report on memory usage by all children of a pointer, giving a full tree view
1139 */
1140 void talloc_report_full(const void *ptr, FILE *f)
1141 {
1142         talloc_report_depth_file(ptr, 0, -1, f);
1143 }
1144
1145 /*
1146   report on memory usage by all children of a pointer
1147 */
1148 void talloc_report(const void *ptr, FILE *f)
1149 {
1150         talloc_report_depth_file(ptr, 0, 1, f);
1151 }
1152
1153 /*
1154   report on any memory hanging off the null context
1155 */
1156 static void talloc_report_null(void)
1157 {
1158         if (talloc_total_size(null_context) != 0) {
1159                 talloc_report(null_context, stderr);
1160         }
1161 }
1162
1163 /*
1164   report on any memory hanging off the null context
1165 */
1166 static void talloc_report_null_full(void)
1167 {
1168         if (talloc_total_size(null_context) != 0) {
1169                 talloc_report_full(null_context, stderr);
1170         }
1171 }
1172
1173 /*
1174   enable tracking of the NULL context
1175 */
1176 void talloc_enable_null_tracking(void)
1177 {
1178         if (null_context == NULL) {
1179                 null_context = _talloc_named_const(NULL, 0, "null_context");
1180         }
1181 }
1182
1183 /*
1184   disable tracking of the NULL context
1185 */
1186 void talloc_disable_null_tracking(void)
1187 {
1188         _talloc_free(null_context);
1189         null_context = NULL;
1190 }
1191
1192 /*
1193   enable leak reporting on exit
1194 */
1195 void talloc_enable_leak_report(void)
1196 {
1197         talloc_enable_null_tracking();
1198         atexit(talloc_report_null);
1199 }
1200
1201 /*
1202   enable full leak reporting on exit
1203 */
1204 void talloc_enable_leak_report_full(void)
1205 {
1206         talloc_enable_null_tracking();
1207         atexit(talloc_report_null_full);
1208 }
1209
1210 /* 
1211    talloc and zero memory. 
1212 */
1213 void *_talloc_zero(const void *ctx, size_t size, const char *name)
1214 {
1215         void *p;
1216
1217         lock(ctx);
1218         p = _talloc_named_const(ctx, size, name);
1219         unlock();
1220
1221         if (p) {
1222                 memset(p, '\0', size);
1223         }
1224
1225         return p;
1226 }
1227
1228 /*
1229   memdup with a talloc. 
1230 */
1231 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
1232 {
1233         void *newp;
1234
1235         lock(t);
1236         newp = _talloc_named_const(t, size, name);
1237         unlock();
1238
1239         if (likely(newp)) {
1240                 memcpy(newp, p, size);
1241         }
1242
1243         return newp;
1244 }
1245
1246 /*
1247   strdup with a talloc 
1248 */
1249 char *talloc_strdup(const void *t, const char *p)
1250 {
1251         char *ret;
1252         if (!p) {
1253                 return NULL;
1254         }
1255         ret = (char *)talloc_memdup(t, p, strlen(p) + 1);
1256         if (likely(ret)) {
1257                 _talloc_set_name_const(ret, ret);
1258         }
1259         return ret;
1260 }
1261
1262 /*
1263  append to a talloced string 
1264 */
1265 char *talloc_append_string(char *orig, const char *append)
1266 {
1267         char *ret;
1268         size_t olen = strlen(orig);
1269         size_t alenz;
1270
1271         if (!append)
1272                 return orig;
1273
1274         alenz = strlen(append) + 1;
1275
1276         ret = talloc_realloc(NULL, orig, char, olen + alenz);
1277         if (!ret)
1278                 return NULL;
1279
1280         /* append the string with the trailing \0 */
1281         memcpy(&ret[olen], append, alenz);
1282
1283         _talloc_set_name_const(ret, ret);
1284
1285         return ret;
1286 }
1287
1288 /*
1289   strndup with a talloc 
1290 */
1291 char *talloc_strndup(const void *t, const char *p, size_t n)
1292 {
1293         size_t len;
1294         char *ret;
1295
1296         for (len=0; len<n && p[len]; len++) ;
1297
1298         lock(t);
1299         ret = (char *)__talloc(t, len + 1);
1300         unlock();
1301         if (!ret) { return NULL; }
1302         memcpy(ret, p, len);
1303         ret[len] = 0;
1304         _talloc_set_name_const(ret, ret);
1305         return ret;
1306 }
1307
1308 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1309 {       
1310         int len;
1311         char *ret;
1312         va_list ap2;
1313         char c;
1314         
1315         /* this call looks strange, but it makes it work on older solaris boxes */
1316         va_copy(ap2, ap);
1317         len = vsnprintf(&c, 1, fmt, ap2);
1318         va_end(ap2);
1319         if (len < 0) {
1320                 return NULL;
1321         }
1322
1323         lock(t);
1324         ret = (char *)__talloc(t, len+1);
1325         unlock();
1326         if (ret) {
1327                 va_copy(ap2, ap);
1328                 vsnprintf(ret, len+1, fmt, ap2);
1329                 va_end(ap2);
1330                 _talloc_set_name_const(ret, ret);
1331         }
1332
1333         return ret;
1334 }
1335
1336
1337 /*
1338   Perform string formatting, and return a pointer to newly allocated
1339   memory holding the result, inside a memory pool.
1340  */
1341 char *talloc_asprintf(const void *t, const char *fmt, ...)
1342 {
1343         va_list ap;
1344         char *ret;
1345
1346         va_start(ap, fmt);
1347         ret = talloc_vasprintf(t, fmt, ap);
1348         va_end(ap);
1349         return ret;
1350 }
1351
1352
1353 /**
1354  * Realloc @p s to append the formatted result of @p fmt and @p ap,
1355  * and return @p s, which may have moved.  Good for gradually
1356  * accumulating output into a string buffer.
1357  **/
1358 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1359 {       
1360         struct talloc_chunk *tc;
1361         int len, s_len;
1362         va_list ap2;
1363         char c;
1364
1365         if (s == NULL) {
1366                 return talloc_vasprintf(NULL, fmt, ap);
1367         }
1368
1369         tc = talloc_chunk_from_ptr(s);
1370
1371         s_len = tc->size - 1;
1372
1373         va_copy(ap2, ap);
1374         len = vsnprintf(&c, 1, fmt, ap2);
1375         va_end(ap2);
1376
1377         if (len <= 0) {
1378                 /* Either the vsnprintf failed or the format resulted in
1379                  * no characters being formatted. In the former case, we
1380                  * ought to return NULL, in the latter we ought to return
1381                  * the original string. Most current callers of this 
1382                  * function expect it to never return NULL.
1383                  */
1384                 return s;
1385         }
1386
1387         s = talloc_realloc(NULL, s, char, s_len + len+1);
1388         if (!s) return NULL;
1389
1390         va_copy(ap2, ap);
1391         vsnprintf(s+s_len, len+1, fmt, ap2);
1392         va_end(ap2);
1393         _talloc_set_name_const(s, s);
1394
1395         return s;
1396 }
1397
1398 /*
1399   Realloc @p s to append the formatted result of @p fmt and return @p
1400   s, which may have moved.  Good for gradually accumulating output
1401   into a string buffer.
1402  */
1403 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1404 {
1405         va_list ap;
1406
1407         va_start(ap, fmt);
1408         s = talloc_vasprintf_append(s, fmt, ap);
1409         va_end(ap);
1410         return s;
1411 }
1412
1413 /*
1414   alloc an array, checking for integer overflow in the array size
1415 */
1416 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1417 {
1418         void *p;
1419
1420         if (count >= MAX_TALLOC_SIZE/el_size) {
1421                 return NULL;
1422         }
1423         lock(ctx);
1424         p = _talloc_named_const(ctx, el_size * count, name);
1425         unlock();
1426         return p;
1427 }
1428
1429 /*
1430   alloc an zero array, checking for integer overflow in the array size
1431 */
1432 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1433 {
1434         void *p;
1435
1436         if (count >= MAX_TALLOC_SIZE/el_size) {
1437                 return NULL;
1438         }
1439         p = _talloc_zero(ctx, el_size * count, name);
1440         return p;
1441 }
1442
1443 /*
1444   realloc an array, checking for integer overflow in the array size
1445 */
1446 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1447 {
1448         if (count >= MAX_TALLOC_SIZE/el_size) {
1449                 return NULL;
1450         }
1451         return _talloc_realloc(ctx, ptr, el_size * count, name);
1452 }
1453
1454 /*
1455   a function version of talloc_realloc(), so it can be passed as a function pointer
1456   to libraries that want a realloc function (a realloc function encapsulates
1457   all the basic capabilities of an allocation library, which is why this is useful)
1458 */
1459 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1460 {
1461         return _talloc_realloc(context, ptr, size, NULL);
1462 }
1463
1464
1465 static int talloc_autofree_destructor(void *ptr)
1466 {
1467         autofree_context = NULL;
1468         return 0;
1469 }
1470
1471 static void talloc_autofree(void)
1472 {
1473         if (autofree_context && *autofree_context == getpid())
1474                 talloc_free(autofree_context);
1475 }
1476
1477 /*
1478   return a context which will be auto-freed on exit
1479   this is useful for reducing the noise in leak reports
1480 */
1481 void *talloc_autofree_context(void)
1482 {
1483         if (autofree_context == NULL || *autofree_context != getpid()) {
1484                 autofree_context = talloc(NULL, pid_t);
1485                 *autofree_context = getpid();
1486                 talloc_set_name_const(autofree_context, "autofree_context");
1487                 
1488                 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
1489                 atexit(talloc_autofree);
1490         }
1491         return autofree_context;
1492 }
1493
1494 size_t talloc_get_size(const void *context)
1495 {
1496         struct talloc_chunk *tc;
1497
1498         if (context == NULL)
1499                 return 0;
1500
1501         tc = talloc_chunk_from_ptr(context);
1502
1503         return tc->size;
1504 }
1505
1506 /*
1507   find a parent of this context that has the given name, if any
1508 */
1509 void *talloc_find_parent_byname(const void *context, const char *name)
1510 {
1511         struct talloc_chunk *tc;
1512
1513         if (context == NULL) {
1514                 return NULL;
1515         }
1516
1517         lock(context);
1518         tc = talloc_chunk_from_ptr(context);
1519         while (tc) {
1520                 if (tc->name && strcmp(tc->name, name) == 0) {
1521                         unlock();
1522                         return TC_PTR_FROM_CHUNK(tc);
1523                 }
1524                 while (tc && tc->prev) tc = tc->prev;
1525                 if (tc) {
1526                         tc = tc->parent;
1527                 }
1528         }
1529         unlock();
1530         return NULL;
1531 }
1532
1533 /*
1534   show the parentage of a context
1535 */
1536 void talloc_show_parents(const void *context, FILE *file)
1537 {
1538         struct talloc_chunk *tc;
1539
1540         if (context == NULL) {
1541                 fprintf(file, "talloc no parents for NULL\n");
1542                 return;
1543         }
1544
1545         lock(context);
1546         tc = talloc_chunk_from_ptr(context);
1547         fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1548         while (tc) {
1549                 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1550                 while (tc && tc->prev) tc = tc->prev;
1551                 if (tc) {
1552                         tc = tc->parent;
1553                 }
1554         }
1555         unlock();
1556         fflush(file);
1557 }
1558
1559 int talloc_is_parent(const void *context, const void *ptr)
1560 {
1561         int ret;
1562         lock(context);
1563         ret = _talloc_is_parent(context, ptr);
1564         unlock();
1565         return ret;
1566 }
1567
1568 void *talloc_add_external(const void *ctx,
1569                           void *(*realloc)(const void *, void *, size_t),
1570                           void (*lock)(const void *p),
1571                           void (*unlock)(void))
1572 {
1573         struct talloc_chunk *tc, *parent;
1574         void *p;
1575
1576         if (tc_external_realloc && tc_external_realloc != realloc)
1577                 TALLOC_ABORT("talloc_add_external realloc replaced");
1578         tc_external_realloc = realloc;
1579
1580         if (unlikely(ctx == NULL)) {
1581                 ctx = null_context;
1582                 parent = NULL;
1583         } else
1584                 parent = talloc_chunk_from_ptr(ctx);    
1585
1586         tc = tc_external_realloc(ctx, NULL, TC_HDR_SIZE);
1587         p = init_talloc(parent, tc, 0, 1);
1588         tc_lock = lock;
1589         tc_unlock = unlock;
1590
1591         return p;
1592 }