]> git.ozlabs.org Git - ccan/blob - ccan/talloc/talloc.c
63423a50f5ec05e73aa1816910fdc82860fbb2d0
[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 0x7FFFFFFF
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                 struct talloc_chunk *old_parent = NULL;
542                 if (unlikely(tc->child->refs)) {
543                         struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
544                         if (p) new_parent = TC_PTR_FROM_CHUNK(p);
545                 }
546                 /* finding the parent here is potentially quite
547                    expensive, but the alternative, which is to change
548                    talloc to always have a valid tc->parent pointer,
549                    makes realloc more expensive where there are a
550                    large number of children.
551
552                    The reason we need the parent pointer here is that
553                    if _talloc_free_internal() fails due to references
554                    or a failing destructor we need to re-parent, but
555                    the free call can invalidate the prev pointer.
556                 */
557                 if (new_parent == null_context && (tc->child->refs || tc->child->destructor)) {
558                         old_parent = talloc_parent_chunk(ptr);
559                 }
560                 if (unlikely(_talloc_free(child) == -1)) {
561                         if (new_parent == null_context) {
562                                 struct talloc_chunk *p = old_parent;
563                                 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
564                         }
565                         __talloc_steal(new_parent, child);
566                 }
567         }
568
569         tc->flags |= TALLOC_FLAG_FREE;
570
571         if (unlikely(tc->flags & TALLOC_FLAG_EXT_ALLOC))
572                 tc_external_realloc(oldparent, tc, 0);
573         else
574                 free(tc);
575
576         return 0;
577 }
578
579 void *_talloc_steal(const void *new_ctx, const void *ptr)
580 {
581         void *p;
582
583         lock(new_ctx);
584         p = __talloc_steal(new_ctx, ptr);
585         unlock();
586         return p;
587 }
588
589 /*
590   remove a secondary reference to a pointer. This undo's what
591   talloc_reference() has done. The context and pointer arguments
592   must match those given to a talloc_reference()
593 */
594 static inline int talloc_unreference(const void *context, const void *ptr)
595 {
596         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
597         struct talloc_reference_handle *h;
598
599         if (unlikely(context == NULL)) {
600                 context = null_context;
601         }
602
603         for (h=tc->refs;h;h=h->next) {
604                 struct talloc_chunk *p = talloc_parent_chunk(h);
605                 if (p == NULL) {
606                         if (context == NULL) break;
607                 } else if (TC_PTR_FROM_CHUNK(p) == context) {
608                         break;
609                 }
610         }
611         if (h == NULL) {
612                 return -1;
613         }
614
615         return _talloc_free(h);
616 }
617
618 /*
619   remove a specific parent context from a pointer. This is a more
620   controlled varient of talloc_free()
621 */
622 int talloc_unlink(const void *context, void *ptr)
623 {
624         struct talloc_chunk *tc_p, *new_p;
625         void *new_parent;
626
627         if (ptr == NULL) {
628                 return -1;
629         }
630
631         if (context == NULL) {
632                 context = null_context;
633         }
634
635         lock(context);
636         if (talloc_unreference(context, ptr) == 0) {
637                 unlock();
638                 return 0;
639         }
640
641         if (context == NULL) {
642                 if (talloc_parent_chunk(ptr) != NULL) {
643                         unlock();
644                         return -1;
645                 }
646         } else {
647                 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
648                         unlock();
649                         return -1;
650                 }
651         }
652         
653         tc_p = talloc_chunk_from_ptr(ptr);
654
655         if (tc_p->refs == NULL) {
656                 int ret = _talloc_free(ptr);
657                 unlock();
658                 return ret;
659         }
660
661         new_p = talloc_parent_chunk(tc_p->refs);
662         if (new_p) {
663                 new_parent = TC_PTR_FROM_CHUNK(new_p);
664         } else {
665                 new_parent = NULL;
666         }
667
668         if (talloc_unreference(new_parent, ptr) != 0) {
669                 unlock();
670                 return -1;
671         }
672
673         __talloc_steal(new_parent, ptr);
674         unlock();
675
676         return 0;
677 }
678
679 /*
680   add a name to an existing pointer - va_list version
681 */
682 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_FMT(2,0);
683
684 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
685 {
686         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
687         tc->name = talloc_vasprintf(ptr, fmt, ap);
688         if (likely(tc->name)) {
689                 _talloc_set_name_const(tc->name, ".name");
690         }
691         return tc->name;
692 }
693
694 /*
695   add a name to an existing pointer
696 */
697 const char *talloc_set_name(const void *ptr, const char *fmt, ...)
698 {
699         const char *name;
700         va_list ap;
701         va_start(ap, fmt);
702         name = talloc_set_name_v(ptr, fmt, ap);
703         va_end(ap);
704         return name;
705 }
706
707
708 /*
709   create a named talloc pointer. Any talloc pointer can be named, and
710   talloc_named() operates just like talloc() except that it allows you
711   to name the pointer.
712 */
713 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
714 {
715         va_list ap;
716         void *ptr;
717         const char *name;
718
719         lock(context);
720         ptr = __talloc(context, size);
721         unlock();
722         if (unlikely(ptr == NULL)) return NULL;
723
724         va_start(ap, fmt);
725         name = talloc_set_name_v(ptr, fmt, ap);
726         va_end(ap);
727
728         if (unlikely(name == NULL)) {
729                 talloc_free(ptr);
730                 return NULL;
731         }
732
733         return ptr;
734 }
735
736 /*
737   return the name of a talloc ptr, or "UNNAMED"
738 */
739 const char *talloc_get_name(const void *ptr)
740 {
741         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
742         if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
743                 return ".reference";
744         }
745         if (likely(tc->name)) {
746                 return tc->name;
747         }
748         return "UNNAMED";
749 }
750
751
752 /*
753   check if a pointer has the given name. If it does, return the pointer,
754   otherwise return NULL
755 */
756 void *talloc_check_name(const void *ptr, const char *name)
757 {
758         const char *pname;
759         if (unlikely(ptr == NULL)) return NULL;
760         pname = talloc_get_name(ptr);
761         if (likely(pname == name || strcmp(pname, name) == 0)) {
762                 return discard_const_p(void, ptr);
763         }
764         return NULL;
765 }
766
767
768 /*
769   this is for compatibility with older versions of talloc
770 */
771 void *talloc_init(const char *fmt, ...)
772 {
773         va_list ap;
774         void *ptr;
775         const char *name;
776
777         /*
778          * samba3 expects talloc_report_depth_cb(NULL, ...)
779          * reports all talloc'ed memory, so we need to enable
780          * null_tracking
781          */
782         talloc_enable_null_tracking();
783
784         ptr = __talloc(NULL, 0);
785         if (unlikely(ptr == NULL)) return NULL;
786
787         va_start(ap, fmt);
788         name = talloc_set_name_v(ptr, fmt, ap);
789         va_end(ap);
790
791         if (unlikely(name == NULL)) {
792                 talloc_free(ptr);
793                 return NULL;
794         }
795
796         return ptr;
797 }
798
799 /* 
800    Allocate a bit of memory as a child of an existing pointer
801 */
802 void *_talloc(const void *context, size_t size)
803 {
804         return __talloc(context, size);
805 }
806
807 static int talloc_destroy_pointer(void ***pptr)
808 {
809         if ((uintptr_t)**pptr < getpagesize())
810                 TALLOC_ABORT("Double free or invalid talloc_set?");
811         /* Invalidate pointer so it can't be used again. */
812         **pptr = (void *)1;
813         return 0;
814 }
815
816 void _talloc_set(void *ptr, const void *ctx, size_t size, const char *name)
817 {
818         void ***child;
819         void *p;
820
821         p = talloc_named_const(ctx, size, name);
822         if (unlikely(!p))
823                 goto set_ptr;
824
825         child = talloc(p, void **);
826         if (unlikely(!child)) {
827                 talloc_free(p);
828                 p = NULL;
829                 goto set_ptr;
830         }
831         *child = ptr;
832         talloc_set_name_const(child, "talloc_set destructor");
833         talloc_set_destructor(child, talloc_destroy_pointer);
834
835 set_ptr:
836         /* memcpy rather than cast avoids aliasing problems. */
837         memcpy(ptr, &p, sizeof(p));
838 }
839
840 /*
841   externally callable talloc_set_name_const()
842 */
843 void talloc_set_name_const(const void *ptr, const char *name)
844 {
845         _talloc_set_name_const(ptr, name);
846 }
847
848 /*
849   create a named talloc pointer. Any talloc pointer can be named, and
850   talloc_named() operates just like talloc() except that it allows you
851   to name the pointer.
852 */
853 void *talloc_named_const(const void *context, size_t size, const char *name)
854 {
855         void *p;
856         lock(context);
857         p = _talloc_named_const(context, size, name);
858         unlock();
859         return p;
860 }
861
862 /* 
863    free a talloc pointer. This also frees all child pointers of this 
864    pointer recursively
865
866    return 0 if the memory is actually freed, otherwise -1. The memory
867    will not be freed if the ref_count is > 1 or the destructor (if
868    any) returns non-zero
869 */
870 int talloc_free(const void *ptr)
871 {
872         int saved_errno = errno, ret;
873
874         lock(ptr);
875         ret = _talloc_free(discard_const_p(void, ptr));
876         unlock();
877         if (ret == 0)
878                 errno = saved_errno;
879         return ret;
880 }
881
882
883
884 /*
885   A talloc version of realloc. The context argument is only used if
886   ptr is NULL
887 */
888 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
889 {
890         struct talloc_chunk *tc;
891         void *new_ptr;
892
893         /* size zero is equivalent to free() */
894         if (unlikely(size == 0)) {
895                 talloc_free(ptr);
896                 return NULL;
897         }
898
899         if (unlikely(size >= MAX_TALLOC_SIZE)) {
900                 return NULL;
901         }
902
903         /* realloc(NULL) is equivalent to malloc() */
904         if (ptr == NULL) {
905                 return talloc_named_const(context, size, name);
906         }
907
908         tc = talloc_chunk_from_ptr(ptr);
909
910         /* don't allow realloc on referenced pointers */
911         if (unlikely(tc->refs)) {
912                 return NULL;
913         }
914
915         lock(ptr);
916         if (unlikely(tc->flags & TALLOC_FLAG_EXT_ALLOC)) {
917                 /* need to get parent before setting free flag. */
918                 void *parent = talloc_parent_nolock(ptr);
919                 tc->flags |= TALLOC_FLAG_FREE;
920                 new_ptr = tc_external_realloc(parent, tc, size + TC_HDR_SIZE);
921         } else {
922                 /* by resetting magic we catch users of the old memory */
923                 tc->flags |= TALLOC_FLAG_FREE;
924
925 #if ALWAYS_REALLOC
926                 new_ptr = malloc(size + TC_HDR_SIZE);
927                 if (new_ptr) {
928                         memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
929                         free(tc);
930                 }
931 #else
932                 new_ptr = realloc(tc, size + TC_HDR_SIZE);
933 #endif
934         }
935
936         if (unlikely(!new_ptr)) {       
937                 tc->flags &= ~TALLOC_FLAG_FREE; 
938                 unlock();
939                 return NULL; 
940         }
941
942         tc = (struct talloc_chunk *)new_ptr;
943         tc->flags &= ~TALLOC_FLAG_FREE; 
944         if (tc->parent) {
945                 tc->parent->child = tc;
946         }
947         if (tc->child) {
948                 tc->child->parent = tc;
949         }
950
951         if (tc->prev) {
952                 tc->prev->next = tc;
953         }
954         if (tc->next) {
955                 tc->next->prev = tc;
956         }
957
958         tc->size = size;
959         _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
960         unlock();
961
962         return TC_PTR_FROM_CHUNK(tc);
963 }
964
965 /*
966   a wrapper around talloc_steal() for situations where you are moving a pointer
967   between two structures, and want the old pointer to be set to NULL
968 */
969 void *_talloc_move(const void *new_ctx, const void *_pptr)
970 {
971         const void **pptr = discard_const_p(const void *,_pptr);
972         void *ret = _talloc_steal(new_ctx, *pptr);
973         (*pptr) = NULL;
974         return ret;
975 }
976
977 /*
978   return the total size of a talloc pool (subtree)
979 */
980 static size_t _talloc_total_size(const void *ptr)
981 {
982         size_t total = 0;
983         struct talloc_chunk *c, *tc;
984
985         tc = talloc_chunk_from_ptr(ptr);
986
987         if (tc->flags & TALLOC_FLAG_LOOP) {
988                 return 0;
989         }
990
991         tc->flags |= TALLOC_FLAG_LOOP;
992
993         total = tc->size;
994         for (c=tc->child;c;c=c->next) {
995                 total += _talloc_total_size(TC_PTR_FROM_CHUNK(c));
996         }
997
998         tc->flags &= ~TALLOC_FLAG_LOOP;
999
1000         return total;
1001 }
1002
1003 size_t talloc_total_size(const void *ptr)
1004 {
1005         size_t total;
1006
1007         if (ptr == NULL) {
1008                 ptr = null_context;
1009         }
1010         if (ptr == NULL) {
1011                 return 0;
1012         }
1013
1014         lock(ptr);
1015         total = _talloc_total_size(ptr);
1016         unlock();
1017         return total;
1018 }       
1019
1020 /*
1021   return the total number of blocks in a talloc pool (subtree)
1022 */
1023 static size_t _talloc_total_blocks(const void *ptr)
1024 {
1025         size_t total = 0;
1026         struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
1027
1028         if (tc->flags & TALLOC_FLAG_LOOP) {
1029                 return 0;
1030         }
1031
1032         tc->flags |= TALLOC_FLAG_LOOP;
1033
1034         total++;
1035         for (c=tc->child;c;c=c->next) {
1036                 total += _talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
1037         }
1038
1039         tc->flags &= ~TALLOC_FLAG_LOOP;
1040
1041         return total;
1042 }
1043
1044 size_t talloc_total_blocks(const void *ptr)
1045 {
1046         size_t total;
1047
1048         lock(ptr);
1049         total = _talloc_total_blocks(ptr);
1050         unlock();
1051
1052         return total;
1053 }
1054
1055 static size_t _talloc_reference_count(const void *ptr)
1056 {
1057         struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1058         struct talloc_reference_handle *h;
1059         size_t ret = 0;
1060
1061         for (h=tc->refs;h;h=h->next) {
1062                 ret++;
1063         }
1064         return ret;
1065 }
1066
1067 /*
1068   return the number of external references to a pointer
1069 */
1070 size_t talloc_reference_count(const void *ptr)
1071 {
1072         size_t ret;
1073
1074         lock(talloc_chunk_from_ptr(ptr));
1075         ret = _talloc_reference_count(ptr);
1076         unlock();
1077         return ret;
1078 }
1079
1080 /*
1081   report on memory usage by all children of a pointer, giving a full tree view
1082 */
1083 static void _talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1084                             void (*callback)(const void *ptr,
1085                                              int depth, int max_depth,
1086                                              int is_ref,
1087                                              void *private_data),
1088                             void *private_data)
1089 {
1090         struct talloc_chunk *c, *tc;
1091
1092         tc = talloc_chunk_from_ptr(ptr);
1093
1094         if (tc->flags & TALLOC_FLAG_LOOP) {
1095                 return;
1096         }
1097
1098         callback(ptr, depth, max_depth, 0, private_data);
1099
1100         if (max_depth >= 0 && depth >= max_depth) {
1101                 return;
1102         }
1103
1104         tc->flags |= TALLOC_FLAG_LOOP;
1105         for (c=tc->child;c;c=c->next) {
1106                 if (c->name == TALLOC_MAGIC_REFERENCE) {
1107                         struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1108                         callback(h->ptr, depth + 1, max_depth, 1, private_data);
1109                 } else {
1110                         _talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1111                 }
1112         }
1113         tc->flags &= ~TALLOC_FLAG_LOOP;
1114 }
1115
1116 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1117                             void (*callback)(const void *ptr,
1118                                              int depth, int max_depth,
1119                                              int is_ref,
1120                                              void *private_data),
1121                             void *private_data)
1122 {
1123         if (ptr == NULL) {
1124                 ptr = null_context;
1125         }
1126         if (ptr == NULL) return;
1127
1128         lock(ptr);
1129         _talloc_report_depth_cb(ptr, depth, max_depth, callback, private_data);
1130         unlock();
1131 }
1132
1133 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1134 {
1135         const char *name = talloc_get_name(ptr);
1136         FILE *f = (FILE *)_f;
1137
1138         if (is_ref) {
1139                 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1140                 return;
1141         }
1142
1143         if (depth == 0) {
1144                 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", 
1145                         (max_depth < 0 ? "full " :""), name,
1146                         (unsigned long)_talloc_total_size(ptr),
1147                         (unsigned long)_talloc_total_blocks(ptr));
1148                 return;
1149         }
1150
1151         fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", 
1152                 depth*4, "",
1153                 name,
1154                 (unsigned long)_talloc_total_size(ptr),
1155                 (unsigned long)_talloc_total_blocks(ptr),
1156                 (int)_talloc_reference_count(ptr), ptr);
1157
1158 #if 0
1159         fprintf(f, "content: ");
1160         if (talloc_total_size(ptr)) {
1161                 int tot = talloc_total_size(ptr);
1162                 int i;
1163
1164                 for (i = 0; i < tot; i++) {
1165                         if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1166                                 fprintf(f, "%c", ((char *)ptr)[i]);
1167                         } else {
1168                                 fprintf(f, "~%02x", ((char *)ptr)[i]);
1169                         }
1170                 }
1171         }
1172         fprintf(f, "\n");
1173 #endif
1174 }
1175
1176 /*
1177   report on memory usage by all children of a pointer, giving a full tree view
1178 */
1179 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1180 {
1181         talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1182         fflush(f);
1183 }
1184
1185 /*
1186   report on memory usage by all children of a pointer, giving a full tree view
1187 */
1188 void talloc_report_full(const void *ptr, FILE *f)
1189 {
1190         talloc_report_depth_file(ptr, 0, -1, f);
1191 }
1192
1193 /*
1194   report on memory usage by all children of a pointer
1195 */
1196 void talloc_report(const void *ptr, FILE *f)
1197 {
1198         talloc_report_depth_file(ptr, 0, 1, f);
1199 }
1200
1201 /*
1202   report on any memory hanging off the null context
1203 */
1204 static void talloc_report_null(void)
1205 {
1206         if (talloc_total_size(null_context) != 0) {
1207                 talloc_report(null_context, stderr);
1208         }
1209 }
1210
1211 /*
1212   report on any memory hanging off the null context
1213 */
1214 static void talloc_report_null_full(void)
1215 {
1216         if (talloc_total_size(null_context) != 0) {
1217                 talloc_report_full(null_context, stderr);
1218         }
1219 }
1220
1221 /*
1222   enable tracking of the NULL context
1223 */
1224 void talloc_enable_null_tracking(void)
1225 {
1226         if (null_context == NULL) {
1227                 null_context = _talloc_named_const(NULL, 0, "null_context");
1228         }
1229 }
1230
1231 /*
1232   disable tracking of the NULL context
1233 */
1234 void talloc_disable_null_tracking(void)
1235 {
1236         _talloc_free(null_context);
1237         null_context = NULL;
1238 }
1239
1240 /*
1241   enable leak reporting on exit
1242 */
1243 void talloc_enable_leak_report(void)
1244 {
1245         talloc_enable_null_tracking();
1246         atexit(talloc_report_null);
1247 }
1248
1249 /*
1250   enable full leak reporting on exit
1251 */
1252 void talloc_enable_leak_report_full(void)
1253 {
1254         talloc_enable_null_tracking();
1255         atexit(talloc_report_null_full);
1256 }
1257
1258 /* 
1259    talloc and zero memory. 
1260 */
1261 void *_talloc_zero(const void *ctx, size_t size, const char *name)
1262 {
1263         void *p;
1264
1265         lock(ctx);
1266         p = _talloc_named_const(ctx, size, name);
1267         unlock();
1268
1269         if (p) {
1270                 memset(p, '\0', size);
1271         }
1272
1273         return p;
1274 }
1275
1276 /*
1277   memdup with a talloc. 
1278 */
1279 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
1280 {
1281         void *newp;
1282
1283         lock(t);
1284         newp = _talloc_named_const(t, size, name);
1285         unlock();
1286
1287         if (likely(newp)) {
1288                 memcpy(newp, p, size);
1289         }
1290
1291         return newp;
1292 }
1293
1294 /*
1295   strdup with a talloc 
1296 */
1297 char *talloc_strdup(const void *t, const char *p)
1298 {
1299         char *ret;
1300         if (!p) {
1301                 return NULL;
1302         }
1303         ret = (char *)talloc_memdup(t, p, strlen(p) + 1);
1304         if (likely(ret)) {
1305                 _talloc_set_name_const(ret, ret);
1306         }
1307         return ret;
1308 }
1309
1310 /*
1311  append to a talloced string 
1312 */
1313 char *talloc_append_string(char *orig, const char *append)
1314 {
1315         char *ret;
1316         size_t olen = strlen(orig);
1317         size_t alenz;
1318
1319         if (!append)
1320                 return orig;
1321
1322         alenz = strlen(append) + 1;
1323
1324         ret = talloc_realloc(NULL, orig, char, olen + alenz);
1325         if (!ret)
1326                 return NULL;
1327
1328         /* append the string with the trailing \0 */
1329         memcpy(&ret[olen], append, alenz);
1330
1331         _talloc_set_name_const(ret, ret);
1332
1333         return ret;
1334 }
1335
1336 /*
1337   strndup with a talloc 
1338 */
1339 char *talloc_strndup(const void *t, const char *p, size_t n)
1340 {
1341         size_t len;
1342         char *ret;
1343
1344         for (len=0; len<n && p[len]; len++) ;
1345
1346         lock(t);
1347         ret = (char *)__talloc(t, len + 1);
1348         unlock();
1349         if (!ret) { return NULL; }
1350         memcpy(ret, p, len);
1351         ret[len] = 0;
1352         _talloc_set_name_const(ret, ret);
1353         return ret;
1354 }
1355
1356 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
1357 {       
1358         int len;
1359         char *ret;
1360         va_list ap2;
1361         char c;
1362         
1363         /* this call looks strange, but it makes it work on older solaris boxes */
1364         va_copy(ap2, ap);
1365         len = vsnprintf(&c, 1, fmt, ap2);
1366         va_end(ap2);
1367         if (len < 0) {
1368                 return NULL;
1369         }
1370
1371         lock(t);
1372         ret = (char *)__talloc(t, len+1);
1373         unlock();
1374         if (ret) {
1375                 va_copy(ap2, ap);
1376                 vsnprintf(ret, len+1, fmt, ap2);
1377                 va_end(ap2);
1378                 _talloc_set_name_const(ret, ret);
1379         }
1380
1381         return ret;
1382 }
1383
1384
1385 /*
1386   Perform string formatting, and return a pointer to newly allocated
1387   memory holding the result, inside a memory pool.
1388  */
1389 char *talloc_asprintf(const void *t, const char *fmt, ...)
1390 {
1391         va_list ap;
1392         char *ret;
1393
1394         va_start(ap, fmt);
1395         ret = talloc_vasprintf(t, fmt, ap);
1396         va_end(ap);
1397         return ret;
1398 }
1399
1400
1401 /**
1402  * Realloc @p s to append the formatted result of @p fmt and @p ap,
1403  * and return @p s, which may have moved.  Good for gradually
1404  * accumulating output into a string buffer.
1405  **/
1406 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
1407 {       
1408         struct talloc_chunk *tc;
1409         int len, s_len;
1410         va_list ap2;
1411         char c;
1412
1413         if (s == NULL) {
1414                 return talloc_vasprintf(NULL, fmt, ap);
1415         }
1416
1417         tc = talloc_chunk_from_ptr(s);
1418
1419         s_len = tc->size - 1;
1420
1421         va_copy(ap2, ap);
1422         len = vsnprintf(&c, 1, fmt, ap2);
1423         va_end(ap2);
1424
1425         if (len <= 0) {
1426                 /* Either the vsnprintf failed or the format resulted in
1427                  * no characters being formatted. In the former case, we
1428                  * ought to return NULL, in the latter we ought to return
1429                  * the original string. Most current callers of this 
1430                  * function expect it to never return NULL.
1431                  */
1432                 return s;
1433         }
1434
1435         s = talloc_realloc(NULL, s, char, s_len + len+1);
1436         if (!s) return NULL;
1437
1438         va_copy(ap2, ap);
1439         vsnprintf(s+s_len, len+1, fmt, ap2);
1440         va_end(ap2);
1441         _talloc_set_name_const(s, s);
1442
1443         return s;
1444 }
1445
1446 /*
1447   Realloc @p s to append the formatted result of @p fmt and return @p
1448   s, which may have moved.  Good for gradually accumulating output
1449   into a string buffer.
1450  */
1451 char *talloc_asprintf_append(char *s, const char *fmt, ...)
1452 {
1453         va_list ap;
1454
1455         va_start(ap, fmt);
1456         s = talloc_vasprintf_append(s, fmt, ap);
1457         va_end(ap);
1458         return s;
1459 }
1460
1461 /*
1462   alloc an array, checking for integer overflow in the array size
1463 */
1464 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1465 {
1466         void *p;
1467
1468         if (count >= MAX_TALLOC_SIZE/el_size) {
1469                 return NULL;
1470         }
1471         lock(ctx);
1472         p = _talloc_named_const(ctx, el_size * count, name);
1473         unlock();
1474         return p;
1475 }
1476
1477 /*
1478   alloc an zero array, checking for integer overflow in the array size
1479 */
1480 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
1481 {
1482         void *p;
1483
1484         if (count >= MAX_TALLOC_SIZE/el_size) {
1485                 return NULL;
1486         }
1487         p = _talloc_zero(ctx, el_size * count, name);
1488         return p;
1489 }
1490
1491 /*
1492   realloc an array, checking for integer overflow in the array size
1493 */
1494 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
1495 {
1496         if (count >= MAX_TALLOC_SIZE/el_size) {
1497                 return NULL;
1498         }
1499         return _talloc_realloc(ctx, ptr, el_size * count, name);
1500 }
1501
1502 /*
1503   a function version of talloc_realloc(), so it can be passed as a function pointer
1504   to libraries that want a realloc function (a realloc function encapsulates
1505   all the basic capabilities of an allocation library, which is why this is useful)
1506 */
1507 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
1508 {
1509         return _talloc_realloc(context, ptr, size, NULL);
1510 }
1511
1512
1513 static int talloc_autofree_destructor(void *ptr)
1514 {
1515         autofree_context = NULL;
1516         return 0;
1517 }
1518
1519 static void talloc_autofree(void)
1520 {
1521         if (autofree_context && *autofree_context == getpid())
1522                 talloc_free(autofree_context);
1523 }
1524
1525 /*
1526   return a context which will be auto-freed on exit
1527   this is useful for reducing the noise in leak reports
1528 */
1529 void *talloc_autofree_context(void)
1530 {
1531         if (autofree_context == NULL || *autofree_context != getpid()) {
1532                 autofree_context = talloc(NULL, pid_t);
1533                 *autofree_context = getpid();
1534                 talloc_set_name_const(autofree_context, "autofree_context");
1535                 
1536                 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
1537                 atexit(talloc_autofree);
1538         }
1539         return autofree_context;
1540 }
1541
1542 size_t talloc_get_size(const void *context)
1543 {
1544         struct talloc_chunk *tc;
1545
1546         if (context == NULL)
1547                 return 0;
1548
1549         tc = talloc_chunk_from_ptr(context);
1550
1551         return tc->size;
1552 }
1553
1554 /*
1555   find a parent of this context that has the given name, if any
1556 */
1557 void *talloc_find_parent_byname(const void *context, const char *name)
1558 {
1559         struct talloc_chunk *tc;
1560
1561         if (context == NULL) {
1562                 return NULL;
1563         }
1564
1565         lock(context);
1566         tc = talloc_chunk_from_ptr(context);
1567         while (tc) {
1568                 if (tc->name && strcmp(tc->name, name) == 0) {
1569                         unlock();
1570                         return TC_PTR_FROM_CHUNK(tc);
1571                 }
1572                 while (tc && tc->prev) tc = tc->prev;
1573                 if (tc) {
1574                         tc = tc->parent;
1575                 }
1576         }
1577         unlock();
1578         return NULL;
1579 }
1580
1581 /*
1582   show the parentage of a context
1583 */
1584 void talloc_show_parents(const void *context, FILE *file)
1585 {
1586         struct talloc_chunk *tc;
1587
1588         if (context == NULL) {
1589                 fprintf(file, "talloc no parents for NULL\n");
1590                 return;
1591         }
1592
1593         lock(context);
1594         tc = talloc_chunk_from_ptr(context);
1595         fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
1596         while (tc) {
1597                 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
1598                 while (tc && tc->prev) tc = tc->prev;
1599                 if (tc) {
1600                         tc = tc->parent;
1601                 }
1602         }
1603         unlock();
1604         fflush(file);
1605 }
1606
1607 int talloc_is_parent(const void *context, const void *ptr)
1608 {
1609         int ret;
1610         lock(context);
1611         ret = _talloc_is_parent(context, ptr);
1612         unlock();
1613         return ret;
1614 }
1615
1616 void *talloc_add_external(const void *ctx,
1617                           void *(*realloc)(const void *, void *, size_t),
1618                           void (*lock)(const void *p),
1619                           void (*unlock)(void))
1620 {
1621         struct talloc_chunk *tc, *parent;
1622         void *p;
1623
1624         if (tc_external_realloc && tc_external_realloc != realloc)
1625                 TALLOC_ABORT("talloc_add_external realloc replaced");
1626         tc_external_realloc = realloc;
1627
1628         if (unlikely(ctx == NULL)) {
1629                 ctx = null_context;
1630                 parent = NULL;
1631         } else
1632                 parent = talloc_chunk_from_ptr(ctx);    
1633
1634         tc = tc_external_realloc(ctx, NULL, TC_HDR_SIZE);
1635         p = init_talloc(parent, tc, 0, 1);
1636         tc_lock = lock;
1637         tc_unlock = unlock;
1638
1639         return p;
1640 }