Improve qp-trie refcount debugging
Add some qp-trie tracing macros which can be enabled by a developer. These print a message when a leaf is attached or detached, indicating which part of the qp-trie implementation did so. The refcount methods must now return the refcount value so it can be printed by the trace macros.
This commit is contained in:
@@ -57,18 +57,19 @@ static struct {
|
|||||||
dns_qpkey_t ascii;
|
dns_qpkey_t ascii;
|
||||||
} item[256 * 256 / 4];
|
} item[256 * 256 / 4];
|
||||||
|
|
||||||
static void
|
static uint32_t
|
||||||
fuzz_attach(void *ctx, void *pval, uint32_t ival) {
|
fuzz_attach(void *ctx, void *pval, uint32_t ival) {
|
||||||
assert(ctx == NULL);
|
assert(ctx == NULL);
|
||||||
assert(pval == &item[ival]);
|
assert(pval == &item[ival]);
|
||||||
item[ival].refcount++;
|
return (item[ival].refcount++);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static uint32_t
|
||||||
fuzz_detach(void *ctx, void *pval, uint32_t ival) {
|
fuzz_detach(void *ctx, void *pval, uint32_t ival) {
|
||||||
assert(ctx == NULL);
|
assert(ctx == NULL);
|
||||||
assert(pval == &item[ival]);
|
assert(pval == &item[ival]);
|
||||||
item[ival].refcount--;
|
assert(item[ival].refcount > 0);
|
||||||
|
return (item[ival].refcount--);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
|
|||||||
@@ -180,8 +180,9 @@ typedef uint8_t dns_qpkey_t[512];
|
|||||||
* The `attach` and `detach` methods adjust reference counts on value
|
* The `attach` and `detach` methods adjust reference counts on value
|
||||||
* objects. They support copy-on-write and safe memory reclamation
|
* objects. They support copy-on-write and safe memory reclamation
|
||||||
* needed for multi-version concurrency. The methods are only called
|
* needed for multi-version concurrency. The methods are only called
|
||||||
* when the `dns_qpmulti_t` mutex is held, so they only need to use
|
* when the `dns_qpmulti_t` mutex is held. For tracing purposes, they
|
||||||
* atomic ops if the refcounts are used by code other than the qp-trie.
|
* should return the same value as `isc_refcount_increment()` or
|
||||||
|
* `isc_refcount_decrement()`, respectively
|
||||||
*
|
*
|
||||||
* Note: When a value object reference count is greater than one, the
|
* Note: When a value object reference count is greater than one, the
|
||||||
* object is in use by concurrent readers so it must not be modified. A
|
* object is in use by concurrent readers so it must not be modified. A
|
||||||
@@ -199,8 +200,8 @@ typedef uint8_t dns_qpkey_t[512];
|
|||||||
* readable identifier into `buf` which has max length `size`.
|
* readable identifier into `buf` which has max length `size`.
|
||||||
*/
|
*/
|
||||||
typedef struct dns_qpmethods {
|
typedef struct dns_qpmethods {
|
||||||
void (*attach)(void *uctx, void *pval, uint32_t ival);
|
uint32_t (*attach)(void *uctx, void *pval, uint32_t ival);
|
||||||
void (*detach)(void *uctx, void *pval, uint32_t ival);
|
uint32_t (*detach)(void *uctx, void *pval, uint32_t ival);
|
||||||
size_t (*makekey)(dns_qpkey_t key, void *uctx, void *pval,
|
size_t (*makekey)(dns_qpkey_t key, void *uctx, void *pval,
|
||||||
uint32_t ival);
|
uint32_t ival);
|
||||||
void (*triename)(void *uctx, char *buf, size_t size);
|
void (*triename)(void *uctx, char *buf, size_t size);
|
||||||
|
|||||||
@@ -890,6 +890,34 @@ unpack_reader(dns_qpreader_t *qp, qp_node_t *reader) {
|
|||||||
* method invocation helpers
|
* method invocation helpers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
#define attach_leaf(qp, n) \
|
||||||
|
do { \
|
||||||
|
uint32_t iv = leaf_ival(n); \
|
||||||
|
void *pv = leaf_pval(n); \
|
||||||
|
uint32_t r = qp->methods->attach(qp->uctx, pv, iv); \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"%s:%u:%s():t%u qp %p node %p leaf %p %u " \
|
||||||
|
"(%u -> %u)\n", \
|
||||||
|
__FILE__, __LINE__, __func__, isc_tid(), qp, n, pv, \
|
||||||
|
iv, r, r + 1); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define detach_leaf(qp, n) \
|
||||||
|
do { \
|
||||||
|
uint32_t iv = leaf_ival(n); \
|
||||||
|
void *pv = leaf_pval(n); \
|
||||||
|
uint32_t r = qp->methods->detach(qp->uctx, pv, iv); \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"%s:%u:%s():t%u qp %p node %p leaf %p %u " \
|
||||||
|
"(%u -> %u)\n", \
|
||||||
|
__FILE__, __LINE__, __func__, isc_tid(), qp, n, pv, \
|
||||||
|
iv, r, r - 1); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
attach_leaf(dns_qpreadable_t qpr, qp_node_t *n) {
|
attach_leaf(dns_qpreadable_t qpr, qp_node_t *n) {
|
||||||
dns_qpreader_t *qp = dns_qpreader(qpr);
|
dns_qpreader_t *qp = dns_qpreader(qpr);
|
||||||
@@ -902,6 +930,8 @@ detach_leaf(dns_qpreadable_t qpr, qp_node_t *n) {
|
|||||||
qp->methods->detach(qp->uctx, leaf_pval(n), leaf_ival(n));
|
qp->methods->detach(qp->uctx, leaf_pval(n), leaf_ival(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline size_t
|
static inline size_t
|
||||||
leaf_qpkey(dns_qpreadable_t qpr, qp_node_t *n, dns_qpkey_t key) {
|
leaf_qpkey(dns_qpreadable_t qpr, qp_node_t *n, dns_qpkey_t key) {
|
||||||
dns_qpreader_t *qp = dns_qpreader(qpr);
|
dns_qpreader_t *qp = dns_qpreader(qpr);
|
||||||
|
|||||||
@@ -37,10 +37,11 @@ struct {
|
|||||||
dns_fixedname_t fixed;
|
dns_fixedname_t fixed;
|
||||||
} item[1024 * 1024];
|
} item[1024 * 1024];
|
||||||
|
|
||||||
static void
|
static uint32_t
|
||||||
item_check(void *ctx, void *pval, uint32_t ival) {
|
item_check(void *ctx, void *pval, uint32_t ival) {
|
||||||
UNUSED(ctx);
|
UNUSED(ctx);
|
||||||
assert(pval == &item[ival]);
|
assert(pval == &item[ival]);
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
|
|||||||
@@ -95,17 +95,19 @@ qpkey_from_smallname(dns_qpkey_t key, void *ctx, void *pval, uint32_t ival) {
|
|||||||
return (dns_qpkey_fromname(key, &name));
|
return (dns_qpkey_fromname(key, &name));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static uint32_t
|
||||||
smallname_attach(void *ctx, void *pval, uint32_t ival) {
|
smallname_attach(void *ctx, void *pval, uint32_t ival) {
|
||||||
UNUSED(ctx);
|
UNUSED(ctx);
|
||||||
isc_refcount_increment0(smallname_refcount(pval, ival));
|
return (isc_refcount_increment0(smallname_refcount(pval, ival)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static uint32_t
|
||||||
smallname_detach(void *ctx, void *pval, uint32_t ival) {
|
smallname_detach(void *ctx, void *pval, uint32_t ival) {
|
||||||
if (isc_refcount_decrement(smallname_refcount(pval, ival)) == 1) {
|
uint32_t refs = isc_refcount_decrement(smallname_refcount(pval, ival));
|
||||||
|
if (refs == 1) {
|
||||||
isc_mem_free(ctx, pval);
|
isc_mem_free(ctx, pval);
|
||||||
}
|
}
|
||||||
|
return (refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -89,11 +89,12 @@ static struct {
|
|||||||
dns_qpkey_t key;
|
dns_qpkey_t key;
|
||||||
} *item;
|
} *item;
|
||||||
|
|
||||||
static void
|
static uint32_t
|
||||||
item_refcount(void *ctx, void *pval, uint32_t ival) {
|
item_refcount(void *ctx, void *pval, uint32_t ival) {
|
||||||
UNUSED(ctx);
|
UNUSED(ctx);
|
||||||
UNUSED(pval);
|
UNUSED(pval);
|
||||||
UNUSED(ival);
|
UNUSED(ival);
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
|
|||||||
@@ -104,18 +104,19 @@ static struct {
|
|||||||
dns_qpkey_t ascii;
|
dns_qpkey_t ascii;
|
||||||
} item[ITEM_COUNT];
|
} item[ITEM_COUNT];
|
||||||
|
|
||||||
static void
|
static uint32_t
|
||||||
item_attach(void *ctx, void *pval, uint32_t ival) {
|
item_attach(void *ctx, void *pval, uint32_t ival) {
|
||||||
INSIST(ctx == NULL);
|
assert_null(ctx);
|
||||||
INSIST(pval == &item[ival]);
|
assert_ptr_equal(pval, &item[ival]);
|
||||||
item[ival].refcount++;
|
return (item[ival].refcount++);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static uint32_t
|
||||||
item_detach(void *ctx, void *pval, uint32_t ival) {
|
item_detach(void *ctx, void *pval, uint32_t ival) {
|
||||||
assert_null(ctx);
|
assert_null(ctx);
|
||||||
assert_ptr_equal(pval, &item[ival]);
|
assert_ptr_equal(pval, &item[ival]);
|
||||||
item[ival].refcount--;
|
assert_int_not_equal(item[ival].refcount, 0);
|
||||||
|
return (item[ival].refcount--);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
|
|||||||
Reference in New Issue
Block a user