diff --git a/fuzz/dns_qp.c b/fuzz/dns_qp.c index 3f0b674c14..a528019597 100644 --- a/fuzz/dns_qp.c +++ b/fuzz/dns_qp.c @@ -57,18 +57,19 @@ static struct { dns_qpkey_t ascii; } item[256 * 256 / 4]; -static void +static uint32_t fuzz_attach(void *ctx, void *pval, uint32_t ival) { assert(ctx == NULL); 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) { assert(ctx == NULL); assert(pval == &item[ival]); - item[ival].refcount--; + assert(item[ival].refcount > 0); + return (item[ival].refcount--); } static size_t diff --git a/lib/dns/include/dns/qp.h b/lib/dns/include/dns/qp.h index 4604d6cee0..ef676de7d4 100644 --- a/lib/dns/include/dns/qp.h +++ b/lib/dns/include/dns/qp.h @@ -180,8 +180,9 @@ typedef uint8_t dns_qpkey_t[512]; * The `attach` and `detach` methods adjust reference counts on value * objects. They support copy-on-write and safe memory reclamation * needed for multi-version concurrency. The methods are only called - * when the `dns_qpmulti_t` mutex is held, so they only need to use - * atomic ops if the refcounts are used by code other than the qp-trie. + * when the `dns_qpmulti_t` mutex is held. For tracing purposes, they + * 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 * 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`. */ typedef struct dns_qpmethods { - void (*attach)(void *uctx, void *pval, uint32_t ival); - void (*detach)(void *uctx, void *pval, uint32_t ival); + uint32_t (*attach)(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, uint32_t ival); void (*triename)(void *uctx, char *buf, size_t size); diff --git a/lib/dns/qp_p.h b/lib/dns/qp_p.h index cbaefb6f88..5fc4cdf801 100644 --- a/lib/dns/qp_p.h +++ b/lib/dns/qp_p.h @@ -890,6 +890,34 @@ unpack_reader(dns_qpreader_t *qp, qp_node_t *reader) { * 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 attach_leaf(dns_qpreadable_t qpr, qp_node_t *n) { 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)); } +#endif + static inline size_t leaf_qpkey(dns_qpreadable_t qpr, qp_node_t *n, dns_qpkey_t key) { dns_qpreader_t *qp = dns_qpreader(qpr); diff --git a/tests/bench/load-names.c b/tests/bench/load-names.c index 455f20928f..99c5325dd4 100644 --- a/tests/bench/load-names.c +++ b/tests/bench/load-names.c @@ -37,10 +37,11 @@ struct { dns_fixedname_t fixed; } item[1024 * 1024]; -static void +static uint32_t item_check(void *ctx, void *pval, uint32_t ival) { UNUSED(ctx); assert(pval == &item[ival]); + return (1); } static size_t diff --git a/tests/bench/qp-dump.c b/tests/bench/qp-dump.c index 18c83851d4..515048ea97 100644 --- a/tests/bench/qp-dump.c +++ b/tests/bench/qp-dump.c @@ -95,17 +95,19 @@ qpkey_from_smallname(dns_qpkey_t key, void *ctx, void *pval, uint32_t ival) { return (dns_qpkey_fromname(key, &name)); } -static void +static uint32_t smallname_attach(void *ctx, void *pval, uint32_t ival) { 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) { - 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); } + return (refs); } static void diff --git a/tests/bench/qpmulti.c b/tests/bench/qpmulti.c index ed072804a9..59c9a11a3e 100644 --- a/tests/bench/qpmulti.c +++ b/tests/bench/qpmulti.c @@ -89,11 +89,12 @@ static struct { dns_qpkey_t key; } *item; -static void +static uint32_t item_refcount(void *ctx, void *pval, uint32_t ival) { UNUSED(ctx); UNUSED(pval); UNUSED(ival); + return (1); } static size_t diff --git a/tests/dns/qpmulti_test.c b/tests/dns/qpmulti_test.c index dede4951ba..28605080e0 100644 --- a/tests/dns/qpmulti_test.c +++ b/tests/dns/qpmulti_test.c @@ -104,18 +104,19 @@ static struct { dns_qpkey_t ascii; } item[ITEM_COUNT]; -static void +static uint32_t item_attach(void *ctx, void *pval, uint32_t ival) { - INSIST(ctx == NULL); - INSIST(pval == &item[ival]); - item[ival].refcount++; + assert_null(ctx); + assert_ptr_equal(pval, &item[ival]); + return (item[ival].refcount++); } -static void +static uint32_t item_detach(void *ctx, void *pval, uint32_t ival) { assert_null(ctx); assert_ptr_equal(pval, &item[ival]); - item[ival].refcount--; + assert_int_not_equal(item[ival].refcount, 0); + return (item[ival].refcount--); } static size_t