TODO: more talloc no_owner fixes fixes
authorStefan Metzmacher <metze@samba.org>
Wed, 15 Jul 2009 10:08:03 +0000 (12:08 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 15 Jul 2009 10:08:03 +0000 (12:08 +0200)
lib/talloc/talloc.c

index 4ed48fe59dcbb9b9d5018588f9789cb3287f5d99..f68b1eb5ece523583be18c44609959e6d7c5a7c4 100644 (file)
@@ -64,6 +64,7 @@
 #define TALLOC_FLAG_POOLMEM 0x08       /* This is allocated in a pool */
 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
 #define TALLOC_MAGIC_NO_OWNER ((void *)1)
+#define TALLOC_MAGIC_NO_OWNER_TC ((struct talloc_chunk *)1)
 
 /* by default we abort when given a bad pointer (such as when talloc_free() is called 
    on a pointer that came from malloc() */
@@ -216,10 +217,10 @@ do { \
        if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
 } while (0)
 
-static inline talloc_parent_is_no_owner(const void *ptr)
+static inline bool talloc_parent_is_no_owner(const void *ptr)
 {
        struct talloc_chunk *tc;
-       struct talloc_chunk *no_owner_tc = TALLOC_MAGIC_NO_OWNER;
+       struct talloc_chunk *no_owner_tc = TALLOC_MAGIC_NO_OWNER_TC;
 
        tc = talloc_chunk_from_ptr(ptr);
 
@@ -234,6 +235,9 @@ static inline talloc_parent_is_no_owner(const void *ptr)
        return false;
 }
 
+#define TALLOC_INVALID_PARENT(tc) \
+       ((((tc)->parent == NULL)||((tc)->parent == TALLOC_MAGIC_NO_OWNER_TC)))
+
 /*
   return the parent chunk of a pointer
 */
@@ -248,7 +252,7 @@ static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
        tc = talloc_chunk_from_ptr(ptr);
        while (tc->prev) tc=tc->prev;
 
-       if (unlikely(tc->parent == TALLOC_MAGIC_NO_OWNER)) {
+       if (unlikely(TALLOC_INVALID_PARENT(tc))) {
                return NULL;
        }
 
@@ -270,6 +274,20 @@ const char *talloc_parent_name(const void *ptr)
        return tc? tc->name : NULL;
 }
 
+static inline void talloc_remove_from_parent(struct talloc_chunk *tc)
+{
+       if (!TALLOC_INVALID_PARENT(tc)) {
+               _TLIST_REMOVE(tc->parent->child, tc);
+               if (tc->parent->child) {
+                       tc->parent->child->parent = tc->parent;
+               }
+       } else {
+               if (tc->prev) tc->prev->next = tc->next;
+               if (tc->next) tc->next->prev = tc->prev;
+       }
+//     tc->parent = tc->prec = tc->next = NULL;
+}
+
 /*
   A pool carries an in-pool object count count in the first 16 bytes.
   bytes. This is done to support talloc_steal() to a parent outside of the
@@ -623,15 +641,7 @@ static inline int _talloc_free(void *ptr)
                tc->destructor = NULL;
        }
 
-       if (tc->parent) {
-               _TLIST_REMOVE(tc->parent->child, tc);
-               if (tc->parent->child) {
-                       tc->parent->child->parent = tc->parent;
-               }
-       } else {
-               if (tc->prev) tc->prev->next = tc->next;
-               if (tc->next) tc->next->prev = tc->prev;
-       }
+       talloc_remove_from_parent(tc);
 
        _talloc_free_children(tc);
 
@@ -671,6 +681,7 @@ static inline int _talloc_free(void *ptr)
 void *_talloc_steal(const void *new_ctx, const void *ptr)
 {
        struct talloc_chunk *tc, *new_tc;
+       bool no_owner_null = false;
 
        if (unlikely(!ptr)) {
                return NULL;
@@ -678,11 +689,12 @@ void *_talloc_steal(const void *new_ctx, const void *ptr)
 
        if (unlikely(talloc_parent_is_no_owner(ptr) &&
                     new_ctx != no_owner_context)) {
-               talloc_abort_no_owner_free();
-               return NULL;
+//             talloc_abort_no_owner_free();
+//             return NULL;
        }
 
        if (unlikely(new_ctx == TALLOC_MAGIC_NO_OWNER)) {
+               no_owner_null = true;
                new_ctx = NULL;
        }
 
@@ -693,17 +705,12 @@ void *_talloc_steal(const void *new_ctx, const void *ptr)
        tc = talloc_chunk_from_ptr(ptr);
 
        if (unlikely(new_ctx == NULL)) {
-               if (tc->parent) {
-                       _TLIST_REMOVE(tc->parent->child, tc);
-                       if (tc->parent->child) {
-                               tc->parent->child->parent = tc->parent;
-                       }
-               } else {
-                       if (tc->prev) tc->prev->next = tc->next;
-                       if (tc->next) tc->next->prev = tc->prev;
-               }
-               
+               talloc_remove_from_parent(tc);
+
                tc->parent = tc->next = tc->prev = NULL;
+               if (unlikely(no_owner_null)) {
+                       tc->parent = TALLOC_MAGIC_NO_OWNER_TC;
+               }
                return discard_const_p(void, ptr);
        }
 
@@ -713,15 +720,7 @@ void *_talloc_steal(const void *new_ctx, const void *ptr)
                return discard_const_p(void, ptr);
        }
 
-       if (tc->parent) {
-               _TLIST_REMOVE(tc->parent->child, tc);
-               if (tc->parent->child) {
-                       tc->parent->child->parent = tc->parent;
-               }
-       } else {
-               if (tc->prev) tc->prev->next = tc->next;
-               if (tc->next) tc->next->prev = tc->prev;
-       }
+       talloc_remove_from_parent(tc);
 
        tc->parent = new_tc;
        if (new_tc->child) new_tc->child->parent = NULL;
@@ -767,8 +766,7 @@ static inline int talloc_unreference(const void *context, const void *ptr)
 */
 int talloc_unlink(const void *context, void *ptr)
 {
-       struct talloc_chunk *tc_p, *new_p;
-       void *new_parent;
+       struct talloc_chunk *tc_p;
 
        if (ptr == NULL) {
                return -1;
@@ -1123,7 +1121,7 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n
        if (malloced) {
                tc->flags &= ~TALLOC_FLAG_POOLMEM;
        }
-       if (tc->parent) {
+       if (!TALLOC_INVALID_PARENT(tc)) {
                tc->parent->child = tc;
        }
        if (tc->child) {
@@ -1822,6 +1820,9 @@ void *talloc_find_parent_byname(const void *context, const char *name)
                }
                while (tc && tc->prev) tc = tc->prev;
                if (tc) {
+                       if (TALLOC_INVALID_PARENT(tc)) {
+                               break;
+                       }
                        tc = tc->parent;
                }
        }
@@ -1846,6 +1847,10 @@ void talloc_show_parents(const void *context, FILE *file)
                fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
                while (tc && tc->prev) tc = tc->prev;
                if (tc) {
+                       if (tc->parent == TALLOC_MAGIC_NO_OWNER_TC) {
+                               fprintf(file, "\t'no_owner_context'\n");
+                               break;
+                       }
                        tc = tc->parent;
                }
        }
@@ -1868,6 +1873,9 @@ int talloc_is_parent(const void *context, const void *ptr)
                if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
                while (tc && tc->prev) tc = tc->prev;
                if (tc) {
+                       if (TALLOC_INVALID_PARENT(tc)) {
+                               break;
+                       }
                        tc = tc->parent;
                }
        }