From: Rusty Russell Date: Tue, 25 Oct 2011 00:51:33 +0000 (+1030) Subject: talloc: talloc_may_reference X-Git-Url: http://git.samba.org/?p=rusty%2Fsamba.git;a=commitdiff_plain;h=7b1674617330f31526040f062ea134a9b3d8d496 talloc: talloc_may_reference A new flag allows us to mark objects which will/may be referenced in future. You shouldn't try to treat these as a non-reference-counted object, even if it's currently only got one reference. This makes us clean up the hardcoded constants for flag bits, and also bump the minor number since we've changed talloc flags. Signed-off-byL Rusty Russell --- diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c index 5ea07918cfd..41684dfee18 100644 --- a/lib/talloc/talloc.c +++ b/lib/talloc/talloc.c @@ -58,19 +58,30 @@ code that might not cope */ #define ALWAYS_REALLOC 0 +/* How many bottom bits of flags are not magic value */ +#define TALLOC_FLAG_BITS 5 + +#define TALLOC_FLAG_BITMASK ((1 << TALLOC_FLAG_BITS)-1) +#define TALLOC_MAGIC_BITMASK (~TALLOC_FLAG_BITMASK) + +#define TALLOC_MAGIC_MAJOR_SHIFT (7 + TALLOC_FLAG_BITS) +#define TALLOC_MAGIC_MINOR_SHIFT TALLOC_FLAG_BITS + +#define TALLOC_MAGIC_BASE_BITMASK (~(1 << TALLOC_MAGIC_MAJOR_SHIFT)) #define MAX_TALLOC_SIZE 0x10000000 -#define TALLOC_MAGIC_BASE 0xe814ec70 +#define TALLOC_MAGIC_BASE 0xe814ec60 #define TALLOC_MAGIC ( \ TALLOC_MAGIC_BASE + \ - (TALLOC_VERSION_MAJOR << 12) + \ - (TALLOC_VERSION_MINOR << 4) \ + (TALLOC_VERSION_MAJOR << TALLOC_MAGIC_MAJOR_SHIFT) + \ + (TALLOC_VERSION_MINOR << TALLOC_MAGIC_MINOR_SHIFT) \ ) #define TALLOC_FLAG_FREE 0x01 #define TALLOC_FLAG_LOOP 0x02 #define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */ #define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */ +#define TALLOC_FLAG_MAY_REF 0x10 /* Warn as if this has multiple references */ #define TALLOC_MAGIC_REFERENCE ((const char *)1) /* by default we abort when given a bad pointer (such as when talloc_free() is called @@ -323,8 +334,8 @@ static void talloc_abort(const char *reason) static void talloc_abort_magic(unsigned magic) { unsigned striped = magic - TALLOC_MAGIC_BASE; - unsigned major = (striped & 0xFFFFF000) >> 12; - unsigned minor = (striped & 0x00000FF0) >> 4; + unsigned major = (striped >> TALLOC_MAGIC_MAJOR_SHIFT); + unsigned minor = ((striped & ((1 << TALLOC_MAGIC_MAJOR_SHIFT)-1)) >> TALLOC_MAGIC_MINOR_SHIFT); talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n", magic, major, minor, TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR); @@ -346,9 +357,9 @@ static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) { const char *pp = (const char *)ptr; struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE); - if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) { - if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) { - talloc_abort_magic(tc->flags & (~0xF)); + if (unlikely((tc->flags & (TALLOC_FLAG_FREE | TALLOC_MAGIC_BITMASK)) != TALLOC_MAGIC)) { + if ((tc->flags & TALLOC_MAGIC_BITMASK) == TALLOC_MAGIC_BASE) { + talloc_abort_magic(tc->flags & TALLOC_MAGIC_BITMASK); return NULL; } @@ -412,6 +423,10 @@ static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr) _PUBLIC_ void *talloc_parent(const void *ptr) { struct talloc_chunk *tc = talloc_parent_chunk(ptr); + + if (ptr && talloc_chunk_from_ptr(ptr)->flags & TALLOC_FLAG_MAY_REF) { + talloc_log("talloc_parent on may_reference pointer"); + } return tc? TC_PTR_FROM_CHUNK(tc) : NULL; } @@ -421,6 +436,10 @@ _PUBLIC_ void *talloc_parent(const void *ptr) _PUBLIC_ const char *talloc_parent_name(const void *ptr) { struct talloc_chunk *tc = talloc_parent_chunk(ptr); + + if (ptr && talloc_chunk_from_ptr(ptr)->flags & TALLOC_FLAG_MAY_REF) { + talloc_log("talloc_parent_name on may_reference pointer"); + } return tc? tc->name : NULL; } @@ -936,6 +955,18 @@ static void *_talloc_steal_internal(const void *new_ctx, const void *ptr) return discard_const_p(void, ptr); } +static void log_references(const char *fmt, const char *location, + struct talloc_chunk *tc) +{ + struct talloc_reference_handle *h; + + talloc_log(fmt, location); + + for (h=tc->refs; h; h=h->next) { + talloc_log("\treference at %s\n", h->location); + } +} + /* move a lump of memory from one talloc context to another return the ptr on success, or NULL if it could not be transferred. @@ -952,15 +983,11 @@ _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const cha tc = talloc_chunk_from_ptr(ptr); if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) { - struct talloc_reference_handle *h; - - talloc_log("WARNING: talloc_steal with references at %s\n", - location); - - for (h=tc->refs; h; h=h->next) { - talloc_log("\treference at %s\n", - h->location); - } + log_references("WARNING: talloc_steal with references at %s\n", + location, tc); + } else if (tc->flags & TALLOC_FLAG_MAY_REF) { + log_references("WARNING: talloc_steal on may_reference ptr at %s\n", + location, tc); } #if 0 @@ -1346,6 +1373,11 @@ _PUBLIC_ int _talloc_free(void *ptr, const char *location) } tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_MAY_REF) { + log_references("ERROR: talloc_free with may_reference at %s\n", + location, tc); + } if (unlikely(tc->refs != NULL)) { struct talloc_reference_handle *h; @@ -1357,13 +1389,8 @@ _PUBLIC_ int _talloc_free(void *ptr, const char *location) return talloc_unlink(null_context, ptr); } - talloc_log("ERROR: talloc_free with references at %s\n", - location); - - for (h=tc->refs; h; h=h->next) { - talloc_log("\treference at %s\n", - h->location); - } + log_references("ERROR: talloc_free with references at %s\n", + location, tc); return -1; } @@ -2369,3 +2396,12 @@ _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr) { return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH); } + +_PUBLIC_ void *talloc_may_reference(const void *ptr) +{ + struct talloc_chunk *tc; + + tc = talloc_chunk_from_ptr(ptr); + tc->flags |= TALLOC_FLAG_MAY_REF; + return discard_const_p(void, ptr); +} diff --git a/lib/talloc/talloc.h b/lib/talloc/talloc.h index 96c7e2467c2..cedc8d50f02 100644 --- a/lib/talloc/talloc.h +++ b/lib/talloc/talloc.h @@ -43,7 +43,7 @@ extern "C" { */ #define TALLOC_VERSION_MAJOR 2 -#define TALLOC_VERSION_MINOR 0 +#define TALLOC_VERSION_MINOR 1 int talloc_version_major(void); int talloc_version_minor(void); @@ -933,6 +933,32 @@ void *talloc_reference(const void *ctx, const void *ptr); void *_talloc_reference_loc(const void *context, const void *ptr, const char *location); #endif +/** + * @brief Mark a talloc pointer as being referencable. + * + * The talloc_may_reference() function marks ptr as having future + * references. As referenced (aka multi-parent) objects need to be + * handled differently, this helps debugging: you will get a warning + * from talloc_steal() and talloc_free() even if there is only a + * single (or NULL) parent. + * + * It will also warn on talloc_parent() or talloc_parent_name() on + * such pointers. + * + * @param[in] ptr The pointer you may create an additional parent for. + * + * Example: + * @code + * unsigned int *a; + * // We may reference this later; be careful! + * a = talloc(NULL, unsigned int); + * talloc_may_reference(a); + * @endcode + * + * @see talloc_reference() + */ +void *talloc_may_reference(const void *ptr); + /** * @brief Remove a specific parent from a talloc chunk. * diff --git a/lib/talloc/wscript b/lib/talloc/wscript index dd83e16a423..44e7f2b224d 100644 --- a/lib/talloc/wscript +++ b/lib/talloc/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'talloc' -VERSION = '2.0.7' +VERSION = '2.1.0' blddir = 'bin'