Ignore:
Timestamp:
Nov 14, 2012, 12:59:34 PM (12 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to 3.6.0

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified vendor/current/lib/talloc/talloc.c

    r414 r740  
    4646#endif
    4747
     48/* Special macros that are no-ops except when run under Valgrind on
     49 * x86.  They've moved a little bit from valgrind 1.0.4 to 1.9.4 */
     50#ifdef HAVE_VALGRIND_MEMCHECK_H
     51        /* memcheck.h includes valgrind.h */
     52#include <valgrind/memcheck.h>
     53#elif defined(HAVE_VALGRIND_H)
     54#include <valgrind.h>
     55#endif
     56
    4857/* use this to force every realloc to change the pointer, to stress test
    4958   code that might not cope */
     
    104113static void *null_context;
    105114static void *autofree_context;
     115
     116/* used to enable fill of memory on free, which can be useful for
     117 * catching use after free errors when valgrind is too slow
     118 */
     119static struct {
     120        bool initialised;
     121        bool enabled;
     122        uint8_t fill_value;
     123} talloc_fill;
     124
     125#define TALLOC_FILL_ENV "TALLOC_FREE_FILL"
     126
     127/*
     128 * do not wipe the header, to allow the
     129 * double-free logic to still work
     130 */
     131#define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \
     132        if (unlikely(talloc_fill.enabled)) { \
     133                size_t _flen = (_tc)->size; \
     134                char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
     135                memset(_fptr, talloc_fill.fill_value, _flen); \
     136        } \
     137} while (0)
     138
     139#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
     140/* Mark the whole chunk as not accessable */
     141#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \
     142        size_t _flen = TC_HDR_SIZE + (_tc)->size; \
     143        char *_fptr = (char *)(_tc); \
     144        VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
     145} while(0)
     146#else
     147#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0)
     148#endif
     149
     150#define TC_INVALIDATE_FULL_CHUNK(_tc) do { \
     151        TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \
     152        TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \
     153} while (0)
     154
     155#define TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
     156        if (unlikely(talloc_fill.enabled)) { \
     157                size_t _flen = (_tc)->size - (_new_size); \
     158                char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
     159                _fptr += (_new_size); \
     160                memset(_fptr, talloc_fill.fill_value, _flen); \
     161        } \
     162} while (0)
     163
     164#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
     165/* Mark the unused bytes not accessable */
     166#define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
     167        size_t _flen = (_tc)->size - (_new_size); \
     168        char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
     169        _fptr += (_new_size); \
     170        VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
     171} while (0)
     172#else
     173#define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
     174#endif
     175
     176#define TC_INVALIDATE_SHRINK_CHUNK(_tc, _new_size) do { \
     177        TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size); \
     178        TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
     179} while (0)
     180
     181#define TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
     182        if (unlikely(talloc_fill.enabled)) { \
     183                size_t _flen = (_tc)->size - (_new_size); \
     184                char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
     185                _fptr += (_new_size); \
     186                memset(_fptr, talloc_fill.fill_value, _flen); \
     187        } \
     188} while (0)
     189
     190#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
     191/* Mark the unused bytes as undefined */
     192#define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
     193        size_t _flen = (_tc)->size - (_new_size); \
     194        char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
     195        _fptr += (_new_size); \
     196        VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
     197} while (0)
     198#else
     199#define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
     200#endif
     201
     202#define TC_UNDEFINE_SHRINK_CHUNK(_tc, _new_size) do { \
     203        TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size); \
     204        TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
     205} while (0)
     206
     207#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
     208/* Mark the new bytes as undefined */
     209#define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { \
     210        size_t _old_used = TC_HDR_SIZE + (_tc)->size; \
     211        size_t _new_used = TC_HDR_SIZE + (_new_size); \
     212        size_t _flen = _new_used - _old_used; \
     213        char *_fptr = _old_used + (char *)(_tc); \
     214        VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
     215} while (0)
     216#else
     217#define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
     218#endif
     219
     220#define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \
     221        TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \
     222} while (0)
    106223
    107224struct talloc_reference_handle {
     
    137254
    138255/* 16 byte alignment seems to keep everyone happy */
    139 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
     256#define TC_ALIGN16(s) (((s)+15)&~15)
     257#define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
    140258#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
    141259
    142 int talloc_version_major(void)
     260_PUBLIC_ int talloc_version_major(void)
    143261{
    144262        return TALLOC_VERSION_MAJOR;
    145263}
    146264
    147 int talloc_version_minor(void)
     265_PUBLIC_ int talloc_version_minor(void)
    148266{
    149267        return TALLOC_VERSION_MINOR;
     
    152270static void (*talloc_log_fn)(const char *message);
    153271
    154 void talloc_set_log_fn(void (*log_fn)(const char *message))
     272_PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
    155273{
    156274        talloc_log_fn = log_fn;
     
    180298}
    181299
    182 void talloc_set_log_stderr(void)
     300_PUBLIC_ void talloc_set_log_stderr(void)
    183301{
    184302        talloc_set_log_fn(talloc_log_stderr);
     
    187305static void (*talloc_abort_fn)(const char *reason);
    188306
    189 void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
     307_PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
    190308{
    191309        talloc_abort_fn = abort_fn;
     
    214332}
    215333
    216 static void talloc_abort_double_free(void)
    217 {
    218         talloc_abort("Bad talloc magic value - double free");
     334static void talloc_abort_access_after_free(void)
     335{
     336        talloc_abort("Bad talloc magic value - access after free");
    219337}
    220338
     
    236354
    237355                if (tc->flags & TALLOC_FLAG_FREE) {
    238                         talloc_log("talloc: double free error - first free may be at %s\n", tc->name);
    239                         talloc_abort_double_free();
     356                        talloc_log("talloc: access after free error - first free may be at %s\n", tc->name);
     357                        talloc_abort_access_after_free();
    240358                        return NULL;
    241359                } else {
     
    292410}
    293411
    294 void *talloc_parent(const void *ptr)
     412_PUBLIC_ void *talloc_parent(const void *ptr)
    295413{
    296414        struct talloc_chunk *tc = talloc_parent_chunk(ptr);
     
    301419  find parents name
    302420*/
    303 const char *talloc_parent_name(const void *ptr)
     421_PUBLIC_ const char *talloc_parent_name(const void *ptr)
    304422{
    305423        struct talloc_chunk *tc = talloc_parent_chunk(ptr);
     
    322440#define TALLOC_POOL_HDR_SIZE 16
    323441
     442#define TC_POOL_SPACE_LEFT(_pool_tc) \
     443        PTR_DIFF(TC_HDR_SIZE + (_pool_tc)->size + (char *)(_pool_tc), \
     444                 (_pool_tc)->pool)
     445
     446#define TC_POOL_FIRST_CHUNK(_pool_tc) \
     447        ((void *)(TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE + (char *)(_pool_tc)))
     448
     449#define TC_POOLMEM_CHUNK_SIZE(_tc) \
     450        TC_ALIGN16(TC_HDR_SIZE + (_tc)->size)
     451
     452#define TC_POOLMEM_NEXT_CHUNK(_tc) \
     453        ((void *)(TC_POOLMEM_CHUNK_SIZE(tc) + (char*)(_tc)))
     454
     455/* Mark the whole remaining pool as not accessable */
     456#define TC_INVALIDATE_FILL_POOL(_pool_tc) do { \
     457        if (unlikely(talloc_fill.enabled)) { \
     458                size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \
     459                char *_fptr = (char *)(_pool_tc)->pool; \
     460                memset(_fptr, talloc_fill.fill_value, _flen); \
     461        } \
     462} while(0)
     463
     464#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
     465/* Mark the whole remaining pool as not accessable */
     466#define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { \
     467        size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \
     468        char *_fptr = (char *)(_pool_tc)->pool; \
     469        VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
     470} while(0)
     471#else
     472#define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { } while (0)
     473#endif
     474
     475#define TC_INVALIDATE_POOL(_pool_tc) do { \
     476        TC_INVALIDATE_FILL_POOL(_pool_tc); \
     477        TC_INVALIDATE_VALGRIND_POOL(_pool_tc); \
     478} while (0)
     479
    324480static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc)
    325481{
    326         return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk));
     482        return (unsigned int *)((char *)tc + TC_HDR_SIZE);
    327483}
    328484
     
    354510        }
    355511
    356         space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size)
    357                 - ((char *)pool_ctx->pool);
     512        space_left = TC_POOL_SPACE_LEFT(pool_ctx);
    358513
    359514        /*
    360515         * Align size to 16 bytes
    361516         */
    362         chunk_size = ((size + 15) & ~15);
     517        chunk_size = TC_ALIGN16(size);
    363518
    364519        if (space_left < chunk_size) {
     
    439594 */
    440595
    441 void *talloc_pool(const void *context, size_t size)
     596_PUBLIC_ void *talloc_pool(const void *context, size_t size)
    442597{
    443598        void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE);
     
    451606
    452607        tc->flags |= TALLOC_FLAG_POOL;
    453         tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE;
     608        tc->pool = TC_POOL_FIRST_CHUNK(tc);
    454609
    455610        *talloc_pool_objectcount(tc) = 1;
    456611
    457 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
    458         VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size);
    459 #endif
     612        TC_INVALIDATE_POOL(tc);
    460613
    461614        return result;
     
    468621  be continued to be used
    469622*/
    470 void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
     623_PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
    471624{
    472625        struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
     
    477630  increase the reference count on a piece of memory.
    478631*/
    479 int talloc_increase_ref_count(const void *ptr)
     632_PUBLIC_ int talloc_increase_ref_count(const void *ptr)
    480633{
    481634        if (unlikely(!talloc_reference(null_context, ptr))) {
     
    533686  and in either order
    534687*/
    535 void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
     688_PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
    536689{
    537690        struct talloc_chunk *tc;
     
    557710static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
    558711
     712static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
     713                                        const char *location)
     714{
     715        struct talloc_chunk *pool;
     716        void *next_tc;
     717        unsigned int *pool_object_count;
     718
     719        pool = (struct talloc_chunk *)tc->pool;
     720        next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
     721
     722        tc->flags |= TALLOC_FLAG_FREE;
     723
     724        /* we mark the freed memory with where we called the free
     725         * from. This means on a double free error we can report where
     726         * the first free came from
     727         */
     728        tc->name = location;
     729
     730        TC_INVALIDATE_FULL_CHUNK(tc);
     731
     732        pool_object_count = talloc_pool_objectcount(pool);
     733
     734        if (unlikely(*pool_object_count == 0)) {
     735                talloc_abort("Pool object count zero!");
     736                return;
     737        }
     738
     739        *pool_object_count -= 1;
     740
     741        if (unlikely(*pool_object_count == 1 && !(pool->flags & TALLOC_FLAG_FREE))) {
     742                /*
     743                 * if there is just one object left in the pool
     744                 * and pool->flags does not have TALLOC_FLAG_FREE,
     745                 * it means this is the pool itself and
     746                 * the rest is available for new objects
     747                 * again.
     748                 */
     749                pool->pool = TC_POOL_FIRST_CHUNK(pool);
     750                TC_INVALIDATE_POOL(pool);
     751        } else if (unlikely(*pool_object_count == 0)) {
     752                /*
     753                 * we mark the freed memory with where we called the free
     754                 * from. This means on a double free error we can report where
     755                 * the first free came from
     756                 */
     757                pool->name = location;
     758
     759                TC_INVALIDATE_FULL_CHUNK(pool);
     760                free(pool);
     761        } else if (pool->pool == next_tc) {
     762                /*
     763                 * if pool->pool still points to end of
     764                 * 'tc' (which is stored in the 'next_tc' variable),
     765                 * we can reclaim the memory of 'tc'.
     766                 */
     767                pool->pool = tc;
     768        }
     769}
     770
     771static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
     772                                                  void *ptr,
     773                                                  const char *location);
     774
    559775/*
    560776   internal talloc_free call
     
    568784        }
    569785
     786        /* possibly initialised the talloc fill value */
     787        if (unlikely(!talloc_fill.initialised)) {
     788                const char *fill = getenv(TALLOC_FILL_ENV);
     789                if (fill != NULL) {
     790                        talloc_fill.enabled = true;
     791                        talloc_fill.fill_value = strtoul(fill, NULL, 0);
     792                }
     793                talloc_fill.initialised = true;
     794        }
     795
    570796        tc = talloc_chunk_from_ptr(ptr);
    571797
    572798        if (unlikely(tc->refs)) {
    573799                int is_child;
    574                 /* check this is a reference from a child or grantchild
    575                  * back to it's parent or grantparent
     800                /* check if this is a reference from a child or
     801                 * grandchild back to it's parent or grandparent
    576802                 *
    577803                 * in that case we need to remove the reference and
     
    617843        tc->flags |= TALLOC_FLAG_LOOP;
    618844
    619         while (tc->child) {
    620                 /* we need to work out who will own an abandoned child
    621                    if it cannot be freed. In priority order, the first
    622                    choice is owner of any remaining reference to this
    623                    pointer, the second choice is our parent, and the
    624                    final choice is the null context. */
    625                 void *child = TC_PTR_FROM_CHUNK(tc->child);
    626                 const void *new_parent = null_context;
    627                 if (unlikely(tc->child->refs)) {
    628                         struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
    629                         if (p) new_parent = TC_PTR_FROM_CHUNK(p);
    630                 }
    631                 if (unlikely(_talloc_free_internal(child, location) == -1)) {
    632                         if (new_parent == null_context) {
    633                                 struct talloc_chunk *p = talloc_parent_chunk(ptr);
    634                                 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
    635                         }
    636                         _talloc_steal_internal(new_parent, child);
    637                 }
    638         }
     845        _talloc_free_children_internal(tc, ptr, location);
    639846
    640847        tc->flags |= TALLOC_FLAG_FREE;
     
    646853        tc->name = location;
    647854
    648         if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) {
    649                 struct talloc_chunk *pool;
     855        if (tc->flags & TALLOC_FLAG_POOL) {
    650856                unsigned int *pool_object_count;
    651857
    652                 pool = (tc->flags & TALLOC_FLAG_POOL)
    653                         ? tc : (struct talloc_chunk *)tc->pool;
    654 
    655                 pool_object_count = talloc_pool_objectcount(pool);
    656 
    657                 if (*pool_object_count == 0) {
     858                pool_object_count = talloc_pool_objectcount(tc);
     859
     860                if (unlikely(*pool_object_count == 0)) {
    658861                        talloc_abort("Pool object count zero!");
    659862                        return 0;
     
    662865                *pool_object_count -= 1;
    663866
    664                 if (*pool_object_count == 0) {
    665                         free(pool);
    666                 }
    667         }
    668         else {
     867                if (unlikely(*pool_object_count == 0)) {
     868                        TC_INVALIDATE_FULL_CHUNK(tc);
     869                        free(tc);
     870                }
     871        } else if (tc->flags & TALLOC_FLAG_POOLMEM) {
     872                _talloc_free_poolmem(tc, location);
     873        } else {
     874                TC_INVALIDATE_FULL_CHUNK(tc);
    669875                free(tc);
    670876        }
     
    734940   passing NULL as ptr will always return NULL with no side effects.
    735941*/
    736 void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
     942_PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
    737943{
    738944        struct talloc_chunk *tc;
     
    755961                }
    756962        }
     963
     964#if 0
     965        /* this test is probably too expensive to have on in the
     966           normal build, but it useful for debugging */
     967        if (talloc_is_parent(new_ctx, ptr)) {
     968                talloc_log("WARNING: stealing into talloc child at %s\n", location);
     969        }
     970#endif
    757971       
    758972        return _talloc_steal_internal(new_ctx, ptr);
     
    766980   The old parent can be either a reference or a parent
    767981*/
    768 void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
     982_PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
    769983{
    770984        struct talloc_chunk *tc;
     
    8261040  controlled varient of talloc_free()
    8271041*/
    828 int talloc_unlink(const void *context, void *ptr)
     1042_PUBLIC_ int talloc_unlink(const void *context, void *ptr)
    8291043{
    8301044        struct talloc_chunk *tc_p, *new_p;
     
    8931107  add a name to an existing pointer
    8941108*/
    895 const char *talloc_set_name(const void *ptr, const char *fmt, ...)
     1109_PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
    8961110{
    8971111        const char *name;
     
    9091123  to name the pointer.
    9101124*/
    911 void *talloc_named(const void *context, size_t size, const char *fmt, ...)
     1125_PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
    9121126{
    9131127        va_list ap;
     
    9331147  return the name of a talloc ptr, or "UNNAMED"
    9341148*/
    935 const char *talloc_get_name(const void *ptr)
     1149_PUBLIC_ const char *talloc_get_name(const void *ptr)
    9361150{
    9371151        struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
     
    9501164  otherwise return NULL
    9511165*/
    952 void *talloc_check_name(const void *ptr, const char *name)
     1166_PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
    9531167{
    9541168        const char *pname;
     
    9791193}
    9801194
    981 void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
     1195_PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
    9821196{
    9831197        const char *pname;
     
    10001214  this is for compatibility with older versions of talloc
    10011215*/
    1002 void *talloc_init(const char *fmt, ...)
     1216_PUBLIC_ void *talloc_init(const char *fmt, ...)
    10031217{
    10041218        va_list ap;
     
    10061220        const char *name;
    10071221
    1008         /*
    1009          * samba3 expects talloc_report_depth_cb(NULL, ...)
    1010          * reports all talloc'ed memory, so we need to enable
    1011          * null_tracking
    1012          */
    1013         talloc_enable_null_tracking();
    1014 
    10151222        ptr = __talloc(NULL, 0);
    10161223        if (unlikely(ptr == NULL)) return NULL;
     
    10281235}
    10291236
    1030 /*
    1031   this is a replacement for the Samba3 talloc_destroy_pool functionality. It
    1032   should probably not be used in new code. It's in here to keep the talloc
    1033   code consistent across Samba 3 and 4.
    1034 */
    1035 void talloc_free_children(void *ptr)
    1036 {
    1037         struct talloc_chunk *tc;
    1038 
    1039         if (unlikely(ptr == NULL)) {
    1040                 return;
    1041         }
    1042 
    1043         tc = talloc_chunk_from_ptr(ptr);
    1044 
     1237static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
     1238                                                  void *ptr,
     1239                                                  const char *location)
     1240{
    10451241        while (tc->child) {
    10461242                /* we need to work out who will own an abandoned child
     
    10511247                void *child = TC_PTR_FROM_CHUNK(tc->child);
    10521248                const void *new_parent = null_context;
     1249                struct talloc_chunk *old_parent = NULL;
    10531250                if (unlikely(tc->child->refs)) {
    10541251                        struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
    10551252                        if (p) new_parent = TC_PTR_FROM_CHUNK(p);
    10561253                }
    1057                 if (unlikely(talloc_free(child) == -1)) {
     1254                /* finding the parent here is potentially quite
     1255                   expensive, but the alternative, which is to change
     1256                   talloc to always have a valid tc->parent pointer,
     1257                   makes realloc more expensive where there are a
     1258                   large number of children.
     1259
     1260                   The reason we need the parent pointer here is that
     1261                   if _talloc_free_internal() fails due to references
     1262                   or a failing destructor we need to re-parent, but
     1263                   the free call can invalidate the prev pointer.
     1264                */
     1265                if (new_parent == null_context && (tc->child->refs || tc->child->destructor)) {
     1266                        old_parent = talloc_parent_chunk(ptr);
     1267                }
     1268                if (unlikely(_talloc_free_internal(child, location) == -1)) {
    10581269                        if (new_parent == null_context) {
    1059                                 struct talloc_chunk *p = talloc_parent_chunk(ptr);
     1270                                struct talloc_chunk *p = old_parent;
    10601271                                if (p) new_parent = TC_PTR_FROM_CHUNK(p);
    10611272                        }
     
    10631274                }
    10641275        }
    1065 
    1066         if ((tc->flags & TALLOC_FLAG_POOL)
    1067             && (*talloc_pool_objectcount(tc) == 1)) {
    1068                 tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE);
    1069 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
    1070                 VALGRIND_MAKE_MEM_NOACCESS(
    1071                         tc->pool, tc->size - TALLOC_POOL_HDR_SIZE);
    1072 #endif
    1073         }
     1276}
     1277
     1278/*
     1279  this is a replacement for the Samba3 talloc_destroy_pool functionality. It
     1280  should probably not be used in new code. It's in here to keep the talloc
     1281  code consistent across Samba 3 and 4.
     1282*/
     1283_PUBLIC_ void talloc_free_children(void *ptr)
     1284{
     1285        struct talloc_chunk *tc;
     1286
     1287        if (unlikely(ptr == NULL)) {
     1288                return;
     1289        }
     1290
     1291        tc = talloc_chunk_from_ptr(ptr);
     1292
     1293        _talloc_free_children_internal(tc, ptr, __location__);
    10741294}
    10751295
     
    10771297   Allocate a bit of memory as a child of an existing pointer
    10781298*/
    1079 void *_talloc(const void *context, size_t size)
     1299_PUBLIC_ void *_talloc(const void *context, size_t size)
    10801300{
    10811301        return __talloc(context, size);
     
    10851305  externally callable talloc_set_name_const()
    10861306*/
    1087 void talloc_set_name_const(const void *ptr, const char *name)
     1307_PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
    10881308{
    10891309        _talloc_set_name_const(ptr, name);
     
    10951315  to name the pointer.
    10961316*/
    1097 void *talloc_named_const(const void *context, size_t size, const char *name)
     1317_PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
    10981318{
    10991319        return _talloc_named_const(context, size, name);
     
    11081328   any) returns non-zero
    11091329*/
    1110 int _talloc_free(void *ptr, const char *location)
     1330_PUBLIC_ int _talloc_free(void *ptr, const char *location)
    11111331{
    11121332        struct talloc_chunk *tc;
     
    11211341                struct talloc_reference_handle *h;
    11221342
     1343                if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
     1344                        /* in this case we do know which parent should
     1345                           get this pointer, as there is really only
     1346                           one parent */
     1347                        return talloc_unlink(null_context, ptr);
     1348                }
     1349
    11231350                talloc_log("ERROR: talloc_free with references at %s\n",
    11241351                           location);
     
    11401367  ptr is NULL
    11411368*/
    1142 void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
     1369_PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
    11431370{
    11441371        struct talloc_chunk *tc;
    11451372        void *new_ptr;
    11461373        bool malloced = false;
     1374        struct talloc_chunk *pool_tc = NULL;
    11471375
    11481376        /* size zero is equivalent to free() */
     
    11731401        }
    11741402
     1403        /* don't let anybody try to realloc a talloc_pool */
     1404        if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
     1405                pool_tc = (struct talloc_chunk *)tc->pool;
     1406        }
     1407
     1408#if (ALWAYS_REALLOC == 0)
    11751409        /* don't shrink if we have less than 1k to gain */
    1176         if ((size < tc->size) && ((tc->size - size) < 1024)) {
    1177                 tc->size = size;
     1410        if (size < tc->size) {
     1411                if (pool_tc) {
     1412                        void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
     1413                        TC_INVALIDATE_SHRINK_CHUNK(tc, size);
     1414                        tc->size = size;
     1415                        if (next_tc == pool_tc->pool) {
     1416                                pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc);
     1417                        }
     1418                        return ptr;
     1419                } else if ((tc->size - size) < 1024) {
     1420                        /*
     1421                         * if we call TC_INVALIDATE_SHRINK_CHUNK() here
     1422                         * we would need to call TC_UNDEFINE_GROW_CHUNK()
     1423                         * after each realloc call, which slows down
     1424                         * testing a lot :-(.
     1425                         *
     1426                         * That is why we only mark memory as undefined here.
     1427                         */
     1428                        TC_UNDEFINE_SHRINK_CHUNK(tc, size);
     1429
     1430                        /* do not shrink if we have less than 1k to gain */
     1431                        tc->size = size;
     1432                        return ptr;
     1433                }
     1434        } else if (tc->size == size) {
     1435                /*
     1436                 * do not change the pointer if it is exactly
     1437                 * the same size.
     1438                 */
    11781439                return ptr;
    11791440        }
     1441#endif
    11801442
    11811443        /* by resetting magic we catch users of the old memory */
     
    11831445
    11841446#if ALWAYS_REALLOC
    1185         new_ptr = malloc(size + TC_HDR_SIZE);
    1186         if (new_ptr) {
    1187                 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
    1188                 free(tc);
    1189         }
    1190 #else
    1191         if (tc->flags & TALLOC_FLAG_POOLMEM) {
    1192 
     1447        if (pool_tc) {
    11931448                new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
    1194                 *talloc_pool_objectcount((struct talloc_chunk *)
    1195                                          (tc->pool)) -= 1;
     1449                *talloc_pool_objectcount(pool_tc) -= 1;
    11961450
    11971451                if (new_ptr == NULL) {
     
    12021456                if (new_ptr) {
    12031457                        memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
     1458                        TC_INVALIDATE_FULL_CHUNK(tc);
     1459                }
     1460        } else {
     1461                new_ptr = malloc(size + TC_HDR_SIZE);
     1462                if (new_ptr) {
     1463                        memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
     1464                        free(tc);
     1465                }
     1466        }
     1467#else
     1468        if (pool_tc) {
     1469                void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
     1470                size_t old_chunk_size = TC_POOLMEM_CHUNK_SIZE(tc);
     1471                size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
     1472                size_t space_needed;
     1473                size_t space_left;
     1474                unsigned int chunk_count = *talloc_pool_objectcount(pool_tc);
     1475
     1476                if (!(pool_tc->flags & TALLOC_FLAG_FREE)) {
     1477                        chunk_count -= 1;
     1478                }
     1479
     1480                if (chunk_count == 1) {
     1481                        /*
     1482                         * optimize for the case where 'tc' is the only
     1483                         * chunk in the pool.
     1484                         */
     1485                        space_needed = new_chunk_size;
     1486                        space_left = pool_tc->size - TALLOC_POOL_HDR_SIZE;
     1487
     1488                        if (space_left >= space_needed) {
     1489                                size_t old_used = TC_HDR_SIZE + tc->size;
     1490                                size_t new_used = TC_HDR_SIZE + size;
     1491                                pool_tc->pool = TC_POOL_FIRST_CHUNK(pool_tc);
     1492#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
     1493                                /*
     1494                                 * we need to prepare the memmove into
     1495                                 * the unaccessable area.
     1496                                 */
     1497                                {
     1498                                        size_t diff = PTR_DIFF(tc, pool_tc->pool);
     1499                                        size_t flen = MIN(diff, old_used);
     1500                                        char *fptr = (char *)pool_tc->pool;
     1501                                        VALGRIND_MAKE_MEM_UNDEFINED(fptr, flen);
     1502                                }
     1503#endif
     1504                                memmove(pool_tc->pool, tc, old_used);
     1505                                new_ptr = pool_tc->pool;
     1506
     1507                                tc = (struct talloc_chunk *)new_ptr;
     1508                                TC_UNDEFINE_GROW_CHUNK(tc, size);
     1509
     1510                                /*
     1511                                 * first we do not align the pool pointer
     1512                                 * because we want to invalidate the padding
     1513                                 * too.
     1514                                 */
     1515                                pool_tc->pool = new_used + (char *)new_ptr;
     1516                                TC_INVALIDATE_POOL(pool_tc);
     1517
     1518                                /* now the aligned pointer */
     1519                                pool_tc->pool = new_chunk_size + (char *)new_ptr;
     1520                                goto got_new_ptr;
     1521                        }
     1522
     1523                        next_tc = NULL;
     1524                }
     1525
     1526                if (new_chunk_size == old_chunk_size) {
     1527                        TC_UNDEFINE_GROW_CHUNK(tc, size);
     1528                        tc->flags &= ~TALLOC_FLAG_FREE;
     1529                        tc->size = size;
     1530                        return ptr;
     1531                }
     1532
     1533                if (next_tc == pool_tc->pool) {
     1534                        /*
     1535                         * optimize for the case where 'tc' is the last
     1536                         * chunk in the pool.
     1537                         */
     1538                        space_needed = new_chunk_size - old_chunk_size;
     1539                        space_left = TC_POOL_SPACE_LEFT(pool_tc);
     1540
     1541                        if (space_left >= space_needed) {
     1542                                TC_UNDEFINE_GROW_CHUNK(tc, size);
     1543                                tc->flags &= ~TALLOC_FLAG_FREE;
     1544                                tc->size = size;
     1545                                pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc);
     1546                                return ptr;
     1547                        }
     1548                }
     1549
     1550                new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
     1551
     1552                if (new_ptr == NULL) {
     1553                        new_ptr = malloc(TC_HDR_SIZE+size);
     1554                        malloced = true;
     1555                }
     1556
     1557                if (new_ptr) {
     1558                        memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
     1559
     1560                        _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
    12041561                }
    12051562        }
     
    12071564                new_ptr = realloc(tc, size + TC_HDR_SIZE);
    12081565        }
     1566got_new_ptr:
    12091567#endif
    12101568        if (unlikely(!new_ptr)) {       
     
    12421600  between two structures, and want the old pointer to be set to NULL
    12431601*/
    1244 void *_talloc_move(const void *new_ctx, const void *_pptr)
     1602_PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
    12451603{
    12461604        const void **pptr = discard_const_p(const void *,_pptr);
     
    12531611  return the total size of a talloc pool (subtree)
    12541612*/
    1255 size_t talloc_total_size(const void *ptr)
     1613_PUBLIC_ size_t talloc_total_size(const void *ptr)
    12561614{
    12571615        size_t total = 0;
     
    12881646  return the total number of blocks in a talloc pool (subtree)
    12891647*/
    1290 size_t talloc_total_blocks(const void *ptr)
     1648_PUBLIC_ size_t talloc_total_blocks(const void *ptr)
    12911649{
    12921650        size_t total = 0;
     
    13211679  return the number of external references to a pointer
    13221680*/
    1323 size_t talloc_reference_count(const void *ptr)
     1681_PUBLIC_ size_t talloc_reference_count(const void *ptr)
    13241682{
    13251683        struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
     
    13361694  report on memory usage by all children of a pointer, giving a full tree view
    13371695*/
    1338 void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
     1696_PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
    13391697                            void (*callback)(const void *ptr,
    13401698                                             int depth, int max_depth,
     
    14201778  report on memory usage by all children of a pointer, giving a full tree view
    14211779*/
    1422 void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
     1780_PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
    14231781{
    14241782        if (f) {
     
    14311789  report on memory usage by all children of a pointer, giving a full tree view
    14321790*/
    1433 void talloc_report_full(const void *ptr, FILE *f)
     1791_PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
    14341792{
    14351793        talloc_report_depth_file(ptr, 0, -1, f);
     
    14391797  report on memory usage by all children of a pointer
    14401798*/
    1441 void talloc_report(const void *ptr, FILE *f)
     1799_PUBLIC_ void talloc_report(const void *ptr, FILE *f)
    14421800{
    14431801        talloc_report_depth_file(ptr, 0, 1, f);
     
    14671825  enable tracking of the NULL context
    14681826*/
    1469 void talloc_enable_null_tracking(void)
     1827_PUBLIC_ void talloc_enable_null_tracking(void)
    14701828{
    14711829        if (null_context == NULL) {
     
    14811839  into the NULL context. This is needed for the talloc testsuite
    14821840*/
    1483 void talloc_enable_null_tracking_no_autofree(void)
     1841_PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
    14841842{
    14851843        if (null_context == NULL) {
     
    14911849  disable tracking of the NULL context
    14921850*/
    1493 void talloc_disable_null_tracking(void)
     1851_PUBLIC_ void talloc_disable_null_tracking(void)
    14941852{
    14951853        if (null_context != NULL) {
     
    15161874  enable leak reporting on exit
    15171875*/
    1518 void talloc_enable_leak_report(void)
     1876_PUBLIC_ void talloc_enable_leak_report(void)
    15191877{
    15201878        talloc_enable_null_tracking();
     
    15251883  enable full leak reporting on exit
    15261884*/
    1527 void talloc_enable_leak_report_full(void)
     1885_PUBLIC_ void talloc_enable_leak_report_full(void)
    15281886{
    15291887        talloc_enable_null_tracking();
     
    15341892   talloc and zero memory.
    15351893*/
    1536 void *_talloc_zero(const void *ctx, size_t size, const char *name)
     1894_PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
    15371895{
    15381896        void *p = _talloc_named_const(ctx, size, name);
     
    15481906  memdup with a talloc.
    15491907*/
    1550 void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
     1908_PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
    15511909{
    15521910        void *newp = _talloc_named_const(t, size, name);
     
    15761934  strdup with a talloc
    15771935*/
    1578 char *talloc_strdup(const void *t, const char *p)
     1936_PUBLIC_ char *talloc_strdup(const void *t, const char *p)
    15791937{
    15801938        if (unlikely(!p)) return NULL;
     
    15851943  strndup with a talloc
    15861944*/
    1587 char *talloc_strndup(const void *t, const char *p, size_t n)
     1945_PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
    15881946{
    15891947        if (unlikely(!p)) return NULL;
     
    16101968 * Appends at the end of the string.
    16111969 */
    1612 char *talloc_strdup_append(char *s, const char *a)
     1970_PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
    16131971{
    16141972        if (unlikely(!s)) {
     
    16271985 * not the end of the string.
    16281986 */
    1629 char *talloc_strdup_append_buffer(char *s, const char *a)
     1987_PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
    16301988{
    16311989        size_t slen;
     
    16502008 * Appends at the end of the string.
    16512009 */
    1652 char *talloc_strndup_append(char *s, const char *a, size_t n)
     2010_PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
    16532011{
    16542012        if (unlikely(!s)) {
     
    16672025 * not the end of the string.
    16682026 */
    1669 char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
     2027_PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
    16702028{
    16712029        size_t slen;
     
    16952053#endif
    16962054
    1697 char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
     2055_PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
    16982056{
    16992057        int len;
     
    17262084  memory holding the result, inside a memory pool.
    17272085 */
    1728 char *talloc_asprintf(const void *t, const char *fmt, ...)
     2086_PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
    17292087{
    17302088        va_list ap;
     
    17792137 * of the string.
    17802138 **/
    1781 char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
     2139_PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
    17822140{
    17832141        if (unlikely(!s)) {
     
    17932151 * end of the talloc'ed buffer, not the end of the string.
    17942152 **/
    1795 char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
     2153_PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
    17962154{
    17972155        size_t slen;
     
    18142172  into a string buffer.
    18152173 */
    1816 char *talloc_asprintf_append(char *s, const char *fmt, ...)
     2174_PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
    18172175{
    18182176        va_list ap;
     
    18292187  into a buffer.
    18302188 */
    1831 char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
     2189_PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
    18322190{
    18332191        va_list ap;
     
    18422200  alloc an array, checking for integer overflow in the array size
    18432201*/
    1844 void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
     2202_PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
    18452203{
    18462204        if (count >= MAX_TALLOC_SIZE/el_size) {
     
    18532211  alloc an zero array, checking for integer overflow in the array size
    18542212*/
    1855 void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
     2213_PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
    18562214{
    18572215        if (count >= MAX_TALLOC_SIZE/el_size) {
     
    18642222  realloc an array, checking for integer overflow in the array size
    18652223*/
    1866 void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
     2224_PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
    18672225{
    18682226        if (count >= MAX_TALLOC_SIZE/el_size) {
     
    18772235  all the basic capabilities of an allocation library, which is why this is useful)
    18782236*/
    1879 void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
     2237_PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
    18802238{
    18812239        return _talloc_realloc(context, ptr, size, NULL);
     
    18982256  this is useful for reducing the noise in leak reports
    18992257*/
    1900 void *talloc_autofree_context(void)
     2258_PUBLIC_ void *talloc_autofree_context(void)
    19012259{
    19022260        if (autofree_context == NULL) {
     
    19082266}
    19092267
    1910 size_t talloc_get_size(const void *context)
     2268_PUBLIC_ size_t talloc_get_size(const void *context)
    19112269{
    19122270        struct talloc_chunk *tc;
     
    19272285  find a parent of this context that has the given name, if any
    19282286*/
    1929 void *talloc_find_parent_byname(const void *context, const char *name)
     2287_PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
    19302288{
    19312289        struct talloc_chunk *tc;
     
    19512309  show the parentage of a context
    19522310*/
    1953 void talloc_show_parents(const void *context, FILE *file)
     2311_PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
    19542312{
    19552313        struct talloc_chunk *tc;
     
    19752333  return 1 if ptr is a parent of context
    19762334*/
    1977 int talloc_is_parent(const void *context, const void *ptr)
     2335static int _talloc_is_parent(const void *context, const void *ptr, int depth)
    19782336{
    19792337        struct talloc_chunk *tc;
     
    19842342
    19852343        tc = talloc_chunk_from_ptr(context);
    1986         while (tc) {
     2344        while (tc && depth > 0) {
    19872345                if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
    19882346                while (tc && tc->prev) tc = tc->prev;
    19892347                if (tc) {
    19902348                        tc = tc->parent;
     2349                        depth--;
    19912350                }
    19922351        }
    19932352        return 0;
    19942353}
     2354
     2355/*
     2356  return 1 if ptr is a parent of context
     2357*/
     2358_PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
     2359{
     2360        return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
     2361}
Note: See TracChangeset for help on using the changeset viewer.