From: Ondřej Surý Date: Thu, 24 May 2018 12:43:07 +0000 (+0200) Subject: Rewrite isc_refcount API after stdatomics and use release-acquire memory barriers X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2F10-atomic-refcount;p=thirdparty%2Fbind9.git Rewrite isc_refcount API after stdatomics and use release-acquire memory barriers --- diff --git a/bin/named/server.c b/bin/named/server.c index 8017a47be63..597901a01fe 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -8984,7 +8984,7 @@ view_loaded(void *arg) { ns_zoneload_t *zl = (ns_zoneload_t *) arg; named_server_t *server = zl->server; isc_boolean_t reconfig = zl->reconfig; - unsigned int refs; + int_fast32_t refs; /* @@ -8995,8 +8995,8 @@ view_loaded(void *arg) { * We use the zoneload reference counter to let us * know when all views are finished. */ - isc_refcount_decrement(&zl->refs, &refs); - if (refs != 0) + refs = isc_refcount_decrement(&zl->refs); + if (refs > 1) return (ISC_R_SUCCESS); isc_refcount_destroy(&zl->refs); @@ -9032,7 +9032,7 @@ load_zones(named_server_t *server, isc_boolean_t init, isc_boolean_t reconfig) { isc_result_t result; dns_view_t *view; ns_zoneload_t *zl; - unsigned int refs = 0; + int_fast32_t refs; zl = isc_mem_get(server->mctx, sizeof (*zl)); if (zl == NULL) @@ -9071,13 +9071,13 @@ load_zones(named_server_t *server, isc_boolean_t init, isc_boolean_t reconfig) { * 'dns_view_asyncload' calls view_loaded if there are no * zones. */ - isc_refcount_increment(&zl->refs, NULL); + isc_refcount_increment(&zl->refs); CHECK(dns_view_asyncload(view, view_loaded, zl)); } cleanup: - isc_refcount_decrement(&zl->refs, &refs); - if (refs == 0) { + refs = isc_refcount_decrement(&zl->refs); + if (refs == 1) { isc_refcount_destroy(&zl->refs); isc_mem_put(server->mctx, zl, sizeof (*zl)); } else if (init) { diff --git a/bin/tests/system/dyndb/driver/db.c b/bin/tests/system/dyndb/driver/db.c index eebe621880f..bb4357ec08f 100644 --- a/bin/tests/system/dyndb/driver/db.c +++ b/bin/tests/system/dyndb/driver/db.c @@ -69,7 +69,7 @@ attach(dns_db_t *source, dns_db_t **targetp) { REQUIRE(VALID_SAMPLEDB(sampledb)); - isc_refcount_increment(&sampledb->refs, NULL); + isc_refcount_increment(&sampledb->refs); *targetp = source; } @@ -85,13 +85,14 @@ free_sampledb(sampledb_t *sampledb) { static void detach(dns_db_t **dbp) { sampledb_t *sampledb = (sampledb_t *)(*dbp); - unsigned int refs; + int_fast32_t refs; REQUIRE(VALID_SAMPLEDB(sampledb)); - isc_refcount_decrement(&sampledb->refs, &refs); - if (refs == 0) + refs = isc_refcount_decrement(&sampledb->refs); + if (refs == 1) { free_sampledb(sampledb); + } *dbp = NULL; } diff --git a/lib/dns/acl.c b/lib/dns/acl.c index 9a9d56ccfe9..e029b17ca27 100644 --- a/lib/dns/acl.c +++ b/lib/dns/acl.c @@ -503,7 +503,7 @@ void dns_acl_attach(dns_acl_t *source, dns_acl_t **target) { REQUIRE(DNS_ACL_VALID(source)); - isc_refcount_increment(&source->refcount, NULL); + isc_refcount_increment(&source->refcount); *target = source; } @@ -536,13 +536,14 @@ destroy(dns_acl_t *dacl) { void dns_acl_detach(dns_acl_t **aclp) { dns_acl_t *acl = *aclp; - unsigned int refs; + int_fast32_t refs; REQUIRE(DNS_ACL_VALID(acl)); - isc_refcount_decrement(&acl->refcount, &refs); - if (refs == 0) + refs = isc_refcount_decrement(&acl->refcount); + if (refs == 1) { destroy(acl); + } *aclp = NULL; } diff --git a/lib/dns/catz.c b/lib/dns/catz.c index f1ad5599393..e03a23ed452 100644 --- a/lib/dns/catz.c +++ b/lib/dns/catz.c @@ -230,7 +230,7 @@ dns_catz_entry_copy(dns_catz_zone_t *zone, const dns_catz_entry_t *entry, void dns_catz_entry_attach(dns_catz_entry_t *entry, dns_catz_entry_t **entryp) { REQUIRE(entryp != NULL && *entryp == NULL); - isc_refcount_increment(&entry->refs, NULL); + isc_refcount_increment(&entry->refs); *entryp = entry; } @@ -238,7 +238,7 @@ void dns_catz_entry_detach(dns_catz_zone_t *zone, dns_catz_entry_t **entryp) { dns_catz_entry_t *entry; isc_mem_t *mctx; - unsigned int refs; + int_fast32_t refs; REQUIRE(entryp != NULL && *entryp != NULL); @@ -247,8 +247,8 @@ dns_catz_entry_detach(dns_catz_zone_t *zone, dns_catz_entry_t **entryp) { mctx = zone->catzs->mctx; - isc_refcount_decrement(&entry->refs, &refs); - if (refs == 0) { + refs = isc_refcount_decrement(&entry->refs); + if (refs == 1) { dns_catz_options_free(&entry->opts, mctx); if (dns_name_dynamic(&entry->name)) dns_name_free(&entry->name, mctx); @@ -728,7 +728,7 @@ void dns_catz_catzs_attach(dns_catz_zones_t *catzs, dns_catz_zones_t **catzsp) { REQUIRE(catzsp != NULL && *catzsp == NULL); - isc_refcount_increment(&catzs->refs, NULL); + isc_refcount_increment(&catzs->refs); *catzsp = catzs; } @@ -736,7 +736,7 @@ void dns_catz_zone_attach(dns_catz_zone_t *zone, dns_catz_zone_t **zonep) { REQUIRE(zonep != NULL && *zonep == NULL); - isc_refcount_increment(&zone->refs, NULL); + isc_refcount_increment(&zone->refs); *zonep = zone; } @@ -746,14 +746,14 @@ dns_catz_zone_detach(dns_catz_zone_t **zonep) { dns_catz_zone_t *zone; isc_ht_iter_t *iter = NULL; isc_mem_t *mctx; - unsigned int refs; + int_fast32_t refs; REQUIRE(zonep != NULL && *zonep != NULL); zone = *zonep; *zonep = NULL; - isc_refcount_decrement(&zone->refs, &refs); - if (refs == 0) { + refs = isc_refcount_decrement(&zone->refs); + if (refs == 1) { if (zone->entries != NULL) { result = isc_ht_iter_create(zone->entries, &iter); INSIST(result == ISC_R_SUCCESS); @@ -802,7 +802,7 @@ dns_catz_catzs_detach(dns_catz_zones_t ** catzsp) { dns_catz_zones_t *catzs; isc_ht_iter_t *iter = NULL; isc_result_t result; - unsigned int refs; + int_fast32_t refs; dns_catz_zone_t *zone; @@ -811,9 +811,9 @@ dns_catz_catzs_detach(dns_catz_zones_t ** catzsp) { REQUIRE(catzs != NULL); *catzsp = NULL; - isc_refcount_decrement(&catzs->refs, &refs); + refs = isc_refcount_decrement(&catzs->refs); - if (refs == 0) { + if (refs == 1) { DESTROYLOCK(&catzs->lock); if (catzs->zones != NULL) { result = isc_ht_iter_create(catzs->zones, &iter); diff --git a/lib/dns/dnstap.c b/lib/dns/dnstap.c index 35b325f207c..a59eca69ba1 100644 --- a/lib/dns/dnstap.c +++ b/lib/dns/dnstap.c @@ -529,7 +529,7 @@ dns_dt_attach(dns_dtenv_t *source, dns_dtenv_t **destp) { REQUIRE(VALID_DTENV(source)); REQUIRE(destp != NULL && *destp == NULL); - isc_refcount_increment(&source->refcount, NULL); + isc_refcount_increment(&source->refcount); *destp = source; } diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c index 564c9aa206d..db45644c7d7 100644 --- a/lib/dns/dst_api.c +++ b/lib/dns/dst_api.c @@ -1163,7 +1163,7 @@ dst_key_attach(dst_key_t *source, dst_key_t **target) { REQUIRE(target != NULL && *target == NULL); REQUIRE(VALID_KEY(source)); - isc_refcount_increment(&source->refs, NULL); + isc_refcount_increment(&source->refs); *target = source; } @@ -1171,7 +1171,7 @@ void dst_key_free(dst_key_t **keyp) { isc_mem_t *mctx; dst_key_t *key; - unsigned int refs; + int_fast32_t refs; REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(keyp != NULL && VALID_KEY(*keyp)); @@ -1179,9 +1179,10 @@ dst_key_free(dst_key_t **keyp) { key = *keyp; mctx = key->mctx; - isc_refcount_decrement(&key->refs, &refs); - if (refs != 0) + refs = isc_refcount_decrement(&key->refs); + if (refs > 1) { return; + } isc_refcount_destroy(&key->refs); if (key->keydata.generic != NULL) { diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h index 14bdf030609..5a5b6ffff25 100644 --- a/lib/dns/include/dns/rbt.h +++ b/lib/dns/include/dns/rbt.h @@ -1044,28 +1044,18 @@ dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name); * The following macros provide a common interface to these operations, * hiding the back-end. The usage is the same as that of isc_refcount_xxx(). */ -#define dns_rbtnode_refinit(node, n) \ - do { \ - isc_refcount_init(&(node)->references, (n)); \ - } while (0) -#define dns_rbtnode_refdestroy(node) \ - do { \ - isc_refcount_destroy(&(node)->references); \ - } while (0) -#define dns_rbtnode_refcurrent(node) \ +#define dns_rbtnode_refinit(node, n) \ + isc_refcount_init(&(node)->references, (n)) +#define dns_rbtnode_refdestroy(node) \ + isc_refcount_destroy(&(node)->references) +#define dns_rbtnode_refcurrent(node) \ isc_refcount_current(&(node)->references) -#define dns_rbtnode_refincrement0(node, refs) \ - do { \ - isc_refcount_increment0(&(node)->references, (refs)); \ - } while (0) -#define dns_rbtnode_refincrement(node, refs) \ - do { \ - isc_refcount_increment(&(node)->references, (refs)); \ - } while (0) -#define dns_rbtnode_refdecrement(node, refs) \ - do { \ - isc_refcount_decrement(&(node)->references, (refs)); \ - } while (0) +#define dns_rbtnode_refincrement0(node) \ + isc_refcount_increment0(&(node)->references) +#define dns_rbtnode_refincrement(node) \ + isc_refcount_increment(&(node)->references) +#define dns_rbtnode_refdecrement(node) \ + isc_refcount_decrement(&(node)->references) void dns_rbtnode_nodename(dns_rbtnode_t *node, dns_name_t *name); diff --git a/lib/dns/iptable.c b/lib/dns/iptable.c index f44bae7d634..490c36ee769 100644 --- a/lib/dns/iptable.c +++ b/lib/dns/iptable.c @@ -140,18 +140,19 @@ dns_iptable_merge(dns_iptable_t *tab, dns_iptable_t *source, isc_boolean_t pos) void dns_iptable_attach(dns_iptable_t *source, dns_iptable_t **target) { REQUIRE(DNS_IPTABLE_VALID(source)); - isc_refcount_increment(&source->refcount, NULL); + isc_refcount_increment(&source->refcount); *target = source; } void dns_iptable_detach(dns_iptable_t **tabp) { dns_iptable_t *tab = *tabp; - unsigned int refs; + int_fast32_t refs; REQUIRE(DNS_IPTABLE_VALID(tab)); - isc_refcount_decrement(&tab->refcount, &refs); - if (refs == 0) + refs = isc_refcount_decrement(&tab->refcount); + if (refs == 1) { destroy_iptable(tab); + } *tabp = NULL; } diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c index 38ed494e8cd..d9b6ae63f68 100644 --- a/lib/dns/keytable.c +++ b/lib/dns/keytable.c @@ -129,7 +129,7 @@ dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) { REQUIRE(VALID_KEYTABLE(source)); REQUIRE(targetp != NULL && *targetp == NULL); - isc_refcount_increment(&source->references, NULL); + isc_refcount_increment(&source->references); *targetp = source; } @@ -137,7 +137,7 @@ dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) { void dns_keytable_detach(dns_keytable_t **keytablep) { dns_keytable_t *keytable; - unsigned int refs; + int_fast32_t refs; /* * Detach *keytablep from its keytable. @@ -148,8 +148,8 @@ dns_keytable_detach(dns_keytable_t **keytablep) { keytable = *keytablep; *keytablep = NULL; - isc_refcount_decrement(&keytable->references, &refs); - if (refs == 0) { + refs = isc_refcount_decrement(&keytable->references); + if (refs == 1) { INSIST(isc_refcount_current(&keytable->active_nodes) == 0); isc_refcount_destroy(&keytable->active_nodes); isc_refcount_destroy(&keytable->references); @@ -422,7 +422,7 @@ dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname, DNS_RBTFIND_NOOPTIONS, NULL, NULL); if (result == ISC_R_SUCCESS) { if (node->data != NULL) { - isc_refcount_increment0(&keytable->active_nodes, NULL); + isc_refcount_increment0(&keytable->active_nodes); dns_keynode_attach(node->data, keynodep); } else result = ISC_R_NOTFOUND; @@ -450,7 +450,7 @@ dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode, return (ISC_R_NOTFOUND); dns_keynode_attach(keynode->next, nextnodep); - isc_refcount_increment(&keytable->active_nodes, NULL); + isc_refcount_increment(&keytable->active_nodes); return (ISC_R_SUCCESS); } @@ -498,7 +498,7 @@ dns_keytable_findkeynode(dns_keytable_t *keytable, const dns_name_t *name, break; } if (knode != NULL) { - isc_refcount_increment0(&keytable->active_nodes, NULL); + isc_refcount_increment0(&keytable->active_nodes); dns_keynode_attach(knode, keynodep); } else result = DNS_R_PARTIALMATCH; @@ -536,7 +536,7 @@ dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode, break; } if (knode != NULL) { - isc_refcount_increment(&keytable->active_nodes, NULL); + isc_refcount_increment(&keytable->active_nodes); result = ISC_R_SUCCESS; dns_keynode_attach(knode, nextnodep); } else @@ -585,7 +585,7 @@ dns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source, REQUIRE(VALID_KEYNODE(source)); REQUIRE(target != NULL && *target == NULL); - isc_refcount_increment(&keytable->active_nodes, NULL); + isc_refcount_increment(&keytable->active_nodes); dns_keynode_attach(source, target); } @@ -600,7 +600,7 @@ dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep) REQUIRE(VALID_KEYTABLE(keytable)); REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep)); - isc_refcount_decrement(&keytable->active_nodes, NULL); + isc_refcount_decrement(&keytable->active_nodes); dns_keynode_detach(keytable->mctx, keynodep); } @@ -746,7 +746,7 @@ dns_keytable_forall(dns_keytable_t *keytable, result = ISC_R_SUCCESS; goto cleanup; } - isc_refcount_increment0(&keytable->active_nodes, NULL); + isc_refcount_increment0(&keytable->active_nodes); for (;;) { dns_rbtnodechain_current(&chain, NULL, NULL, &node); if (node->data != NULL) @@ -758,7 +758,7 @@ dns_keytable_forall(dns_keytable_t *keytable, break; } } - isc_refcount_decrement(&keytable->active_nodes, NULL); + isc_refcount_decrement(&keytable->active_nodes); cleanup: dns_rbtnodechain_invalidate(&chain); @@ -822,17 +822,17 @@ dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) { void dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) { REQUIRE(VALID_KEYNODE(source)); - isc_refcount_increment(&source->refcount, NULL); + isc_refcount_increment(&source->refcount); *target = source; } void dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) { - unsigned int refs; + int_fast32_t refs; dns_keynode_t *node = *keynode; REQUIRE(VALID_KEYNODE(node)); - isc_refcount_decrement(&node->refcount, &refs); - if (refs == 0) { + refs = isc_refcount_decrement(&node->refcount); + if (refs == 1) { if (node->key != NULL) dst_key_free(&node->key); isc_refcount_destroy(&node->refcount); diff --git a/lib/dns/nta.c b/lib/dns/nta.c index 48810a4e152..1f715b2f899 100644 --- a/lib/dns/nta.c +++ b/lib/dns/nta.c @@ -58,19 +58,19 @@ struct dns_nta { */ static void nta_ref(dns_nta_t *nta) { - isc_refcount_increment(&nta->refcount, NULL); + isc_refcount_increment(&nta->refcount); } static void nta_detach(isc_mem_t *mctx, dns_nta_t **ntap) { - unsigned int refs; + int_fast32_t refs; dns_nta_t *nta = *ntap; REQUIRE(VALID_NTA(nta)); *ntap = NULL; - isc_refcount_decrement(&nta->refcount, &refs); - if (refs == 0) { + refs = isc_refcount_decrement(&nta->refcount); + if (refs == 1) { nta->magic = 0; if (nta->timer != NULL) { (void) isc_timer_reset(nta->timer, diff --git a/lib/dns/order.c b/lib/dns/order.c index 50b55f45a89..161374a5b4c 100644 --- a/lib/dns/order.c +++ b/lib/dns/order.c @@ -131,7 +131,7 @@ void dns_order_attach(dns_order_t *source, dns_order_t **target) { REQUIRE(DNS_ORDER_VALID(source)); REQUIRE(target != NULL && *target == NULL); - isc_refcount_increment(&source->references, NULL); + isc_refcount_increment(&source->references); *target = source; } @@ -139,15 +139,16 @@ void dns_order_detach(dns_order_t **orderp) { dns_order_t *order; dns_order_ent_t *ent; - unsigned int references; + int_fast32_t refs; REQUIRE(orderp != NULL); order = *orderp; REQUIRE(DNS_ORDER_VALID(order)); - isc_refcount_decrement(&order->references, &references); *orderp = NULL; - if (references != 0) + refs = isc_refcount_decrement(&order->references); + if (refs > 1) { return; + } order->magic = 0; while ((ent = ISC_LIST_HEAD(order->ents)) != NULL) { diff --git a/lib/dns/portlist.c b/lib/dns/portlist.c index d624a7a0f8a..d48d305fb53 100644 --- a/lib/dns/portlist.c +++ b/lib/dns/portlist.c @@ -231,21 +231,20 @@ dns_portlist_attach(dns_portlist_t *portlist, dns_portlist_t **portlistp) { REQUIRE(DNS_VALID_PORTLIST(portlist)); REQUIRE(portlistp != NULL && *portlistp == NULL); - isc_refcount_increment(&portlist->refcount, NULL); + isc_refcount_increment(&portlist->refcount); *portlistp = portlist; } void dns_portlist_detach(dns_portlist_t **portlistp) { dns_portlist_t *portlist; - unsigned int count; + int_fast32_t refs; REQUIRE(portlistp != NULL); portlist = *portlistp; REQUIRE(DNS_VALID_PORTLIST(portlist)); - *portlistp = NULL; - isc_refcount_decrement(&portlist->refcount, &count); - if (count == 0) { + refs = isc_refcount_decrement(&portlist->refcount); + if (refs == 1) { portlist->magic = 0; isc_refcount_destroy(&portlist->refcount); if (portlist->list != NULL) @@ -256,4 +255,5 @@ dns_portlist_detach(dns_portlist_t **portlistp) { isc_mem_putanddetach(&portlist->mctx, portlist, sizeof(*portlist)); } + *portlistp = NULL; } diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 880cadaacfe..9237e6cf5af 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -769,7 +769,7 @@ attach(dns_db_t *source, dns_db_t **targetp) { REQUIRE(VALID_RBTDB(rbtdb)); - isc_refcount_increment(&rbtdb->references, NULL); + isc_refcount_increment(&rbtdb->references); *targetp = source; } @@ -968,14 +968,10 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) { REQUIRE(rbtdb->future_version == NULL); if (rbtdb->current_version != NULL) { - unsigned int refs; - - isc_refcount_decrement(&rbtdb->current_version->references, - &refs); - INSIST(refs == 0); + isc_refcount_decrement(&rbtdb->current_version->references); + isc_refcount_destroy(&rbtdb->current_version->references); /* Ensures this was the last reference */ UNLINK(rbtdb->open_versions, rbtdb->current_version, link); isc_rwlock_destroy(&rbtdb->current_version->glue_rwlock); - isc_refcount_destroy(&rbtdb->current_version->references); isc_rwlock_destroy(&rbtdb->current_version->rwlock); isc_mem_put(rbtdb->common.mctx, rbtdb->current_version, sizeof(rbtdb_version_t)); @@ -1183,14 +1179,15 @@ maybe_free_rbtdb(dns_rbtdb_t *rbtdb) { static void detach(dns_db_t **dbp) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)(*dbp); - unsigned int refs; + int_fast32_t refs; REQUIRE(VALID_RBTDB(rbtdb)); - isc_refcount_decrement(&rbtdb->references, &refs); - - if (refs == 0) + refs = isc_refcount_decrement(&rbtdb->references); + + if (refs == 1) { maybe_free_rbtdb(rbtdb); + } *dbp = NULL; } @@ -1199,13 +1196,12 @@ static void currentversion(dns_db_t *db, dns_dbversion_t **versionp) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; rbtdb_version_t *version; - unsigned int refs; REQUIRE(VALID_RBTDB(rbtdb)); RWLOCK(&rbtdb->lock, isc_rwlocktype_read); version = rbtdb->current_version; - isc_refcount_increment(&version->references, &refs); + isc_refcount_increment(&version->references); RWUNLOCK(&rbtdb->lock, isc_rwlocktype_read); *versionp = (dns_dbversion_t *)version; @@ -1330,13 +1326,11 @@ attachversion(dns_db_t *db, dns_dbversion_t *source, { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; rbtdb_version_t *rbtversion = source; - unsigned int refs; REQUIRE(VALID_RBTDB(rbtdb)); INSIST(rbtversion != NULL && rbtversion->rbtdb == rbtdb); - isc_refcount_increment(&rbtversion->references, &refs); - INSIST(refs > 1); + isc_refcount_increment(&rbtversion->references); *targetp = rbtversion; } @@ -1346,7 +1340,6 @@ add_changed(dns_rbtdb_t *rbtdb, rbtdb_version_t *version, dns_rbtnode_t *node) { rbtdb_changed_t *changed; - unsigned int refs; /* * Caller must be holding the node lock if its reference must be @@ -1360,8 +1353,7 @@ add_changed(dns_rbtdb_t *rbtdb, rbtdb_version_t *version, REQUIRE(version->writer); if (changed != NULL) { - dns_rbtnode_refincrement(node, &refs); - INSIST(refs != 0); + (void)dns_rbtnode_refincrement(node); changed->node = node; changed->dirty = ISC_FALSE; ISC_LIST_INITANDAPPEND(version->changed_list, changed, link); @@ -1869,17 +1861,15 @@ check_ttl(dns_rbtnode_t *node, rbtdb_search_t *search, */ static inline void new_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) { - unsigned int lockrefs, noderefs; + int_fast32_t noderefs; isc_refcount_t *lockref; INSIST(!ISC_LINK_LINKED(node, deadlink)); - dns_rbtnode_refincrement0(node, &noderefs); - if (noderefs == 1) { /* this is the first reference to the node */ + noderefs = dns_rbtnode_refincrement0(node); + if (noderefs == 0) { /* this is the first reference to the node */ lockref = &rbtdb->node_locks[node->locknum].references; - isc_refcount_increment0(lockref, &lockrefs); - INSIST(lockrefs != 0); + isc_refcount_increment0(lockref); } - INSIST(noderefs != 0); } /*% @@ -2011,7 +2001,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, isc_result_t result; isc_boolean_t write_locked; rbtdb_nodelock_t *nodelock; - unsigned int refs, nrefs; + int_fast32_t refs; int bucket = node->locknum; isc_boolean_t no_reference = ISC_TRUE; @@ -2023,13 +2013,12 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, /* Handle easy and typical case first. */ if (!node->dirty && KEEP_NODE(node, rbtdb)) { - dns_rbtnode_refdecrement(node, &nrefs); - INSIST((int)nrefs >= 0); - if (nrefs == 0) { - isc_refcount_decrement(&nodelock->references, &refs); - INSIST((int)refs >= 0); + refs = dns_rbtnode_refdecrement(node); + if (refs == 1) { + isc_refcount_decrement(&nodelock->references); + return ISC_TRUE; } - return ((nrefs == 0) ? ISC_TRUE : ISC_FALSE); + return ISC_FALSE; } /* Upgrade the lock? */ @@ -2038,12 +2027,12 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, NODE_WEAKLOCK(&nodelock->lock, isc_rwlocktype_write); } - dns_rbtnode_refdecrement(node, &nrefs); - INSIST((int)nrefs >= 0); - if (nrefs > 0) { + refs = dns_rbtnode_refdecrement(node); + if (refs > 1) { /* Restore the lock? */ - if (nlock == isc_rwlocktype_read) + if (nlock == isc_rwlocktype_read) { NODE_WEAKDOWNGRADE(&nodelock->lock); + } return (ISC_FALSE); } @@ -2088,8 +2077,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, } else write_locked = ISC_TRUE; - isc_refcount_decrement(&nodelock->references, &refs); - INSIST((int)refs >= 0); + isc_refcount_decrement(&nodelock->references); if (KEEP_NODE(node, rbtdb)) goto restore_locks; @@ -2444,7 +2432,7 @@ cleanup_dead_nodes_callback(isc_task_t *task, isc_event_t *event) { dns_rbtdb_t *rbtdb = event->ev_arg; isc_boolean_t again = ISC_FALSE; unsigned int locknum; - unsigned int refs; + int_fast32_t refs; RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); for (locknum = 0; locknum < rbtdb->node_lock_count; locknum++) { @@ -2461,9 +2449,10 @@ cleanup_dead_nodes_callback(isc_task_t *task, isc_event_t *event) { isc_task_send(task, &event); else { isc_event_free(&event); - isc_refcount_decrement(&rbtdb->references, &refs); - if (refs == 0) + refs = isc_refcount_decrement(&rbtdb->references); + if (refs == 1) { maybe_free_rbtdb(rbtdb); + } } } @@ -2477,7 +2466,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { rbtdb_changed_t *changed, *next_changed; rbtdb_serial_t serial, least_serial; dns_rbtnode_t *rbtnode; - unsigned int refs; + int_fast32_t refs; rdatasetheader_t *header; REQUIRE(VALID_RBTDB(rbtdb)); @@ -2488,8 +2477,8 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { ISC_LIST_INIT(cleanup_list); ISC_LIST_INIT(resigned_list); - isc_refcount_decrement(&version->references, &refs); - if (refs > 0) { /* typical and easy case first */ + refs = isc_refcount_decrement(&version->references); + if (refs > 1) { /* typical and easy case first */ if (commit) { RWLOCK(&rbtdb->lock, isc_rwlocktype_read); INSIST(!version->writer); @@ -2509,7 +2498,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { serial = version->serial; if (version->writer) { if (commit) { - unsigned cur_ref; + int_fast32_t cur_refs; rbtdb_version_t *cur_version; INSIST(version->commit_ok); @@ -2520,9 +2509,8 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { * DB itself and unlink it from the open list. */ cur_version = rbtdb->current_version; - isc_refcount_decrement(&cur_version->references, - &cur_ref); - if (cur_ref == 0) { + cur_refs = isc_refcount_decrement(&cur_version->references); + if (cur_refs == 1) { if (cur_version->serial == rbtdb->least_serial) INSIST(EMPTY(cur_version->changed_list)); UNLINK(rbtdb->open_versions, @@ -2556,7 +2544,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { * isn't being used by anyone, we can clean * it up. */ - if (cur_ref == 0) { + if (cur_refs == 1) { cleanup_version = cur_version; APPENDLIST(version->changed_list, cleanup_version->changed_list, @@ -2577,9 +2565,8 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { * case where we need to increment the counter from * zero and need to use isc_refcount_increment0(). */ - isc_refcount_increment0(&version->references, - &cur_ref); - INSIST(cur_ref == 1); + cur_refs = isc_refcount_increment0(&version->references); + INSIST(cur_refs == 0); PREPEND(rbtdb->open_versions, rbtdb->current_version, link); resigned_list = version->resigned_list; @@ -2731,7 +2718,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { sizeof(*changed)); } if (event != NULL) { - isc_refcount_increment(&rbtdb->references, NULL); + isc_refcount_increment(&rbtdb->references); isc_task_send(rbtdb->task, &event); } else RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); @@ -5280,14 +5267,12 @@ static void attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; dns_rbtnode_t *node = (dns_rbtnode_t *)source; - unsigned int refs; REQUIRE(VALID_RBTDB(rbtdb)); REQUIRE(targetp != NULL && *targetp == NULL); NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock); - dns_rbtnode_refincrement(node, &refs); - INSIST(refs != 0); + dns_rbtnode_refincrement(node); NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock); *targetp = source; @@ -5450,7 +5435,7 @@ printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) { NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock, isc_rwlocktype_read); - fprintf(out, "node %p, %u references, locknum = %u\n", + fprintf(out, "node %p, %" PRIdFAST32 " references, locknum = %u\n", rbtnode, dns_rbtnode_refcurrent(rbtnode), rbtnode->locknum); if (rbtnode->data != NULL) { @@ -5716,7 +5701,6 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node; rbtdb_version_t *rbtversion = version; rbtdb_rdatasetiter_t *iterator; - unsigned int refs; REQUIRE(VALID_RBTDB(rbtdb)); @@ -5732,9 +5716,7 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, else { INSIST(rbtversion->rbtdb == rbtdb); - isc_refcount_increment(&rbtversion->references, - &refs); - INSIST(refs > 1); + isc_refcount_increment(&rbtversion->references); } } else { if (now == 0) @@ -5751,8 +5733,7 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, NODE_STRONGLOCK(&rbtdb->node_locks[rbtnode->locknum].lock); - dns_rbtnode_refincrement(rbtnode, &refs); - INSIST(refs != 0); + dns_rbtnode_refincrement(rbtnode); iterator->current = NULL; @@ -8325,7 +8306,7 @@ dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, if (result != ISC_R_SUCCESS) { while (i-- > 0) { NODE_DESTROYLOCK(&rbtdb->node_locks[i].lock); - isc_refcount_decrement(&rbtdb->node_locks[i].references, NULL); + isc_refcount_decrement(&rbtdb->node_locks[i].references); isc_refcount_destroy(&rbtdb->node_locks[i].references); } goto cleanup_deadnodes; @@ -8459,7 +8440,7 @@ dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, rbtdb->next_serial = 2; rbtdb->current_version = allocate_version(mctx, 1, 1, ISC_FALSE); if (rbtdb->current_version == NULL) { - isc_refcount_decrement(&rbtdb->references, NULL); + isc_refcount_decrement(&rbtdb->references); isc_refcount_destroy(&rbtdb->references); free_rbtdb(rbtdb, ISC_FALSE, NULL); return (ISC_R_NOMEMORY); @@ -8481,7 +8462,7 @@ dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, isc_mem_put(mctx, rbtdb->current_version, sizeof(*rbtdb->current_version)); rbtdb->current_version = NULL; - isc_refcount_decrement(&rbtdb->references, NULL); + isc_refcount_decrement(&rbtdb->references); isc_refcount_destroy(&rbtdb->references); free_rbtdb(rbtdb, ISC_FALSE, NULL); return (result); @@ -9448,12 +9429,9 @@ dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, * expirenode() currently always returns success. */ if (expire_result == ISC_R_SUCCESS && node->down == NULL) { - unsigned int refs; - rbtdbiter->deletions[rbtdbiter->delcnt++] = node; NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock); - dns_rbtnode_refincrement(node, &refs); - INSIST(refs != 0); + dns_rbtnode_refincrement(node); NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock); } } diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index 74b70092c9f..706a0e02c5b 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -1479,7 +1479,7 @@ cleanup_task: dns_rbt_destroy(&zones->rbt); cleanup_rbt: - isc_refcount_decrement(&zones->refs, NULL); + isc_refcount_decrement(&zones->refs); isc_refcount_destroy(&zones->refs); cleanup_refcount: @@ -1565,7 +1565,7 @@ cleanup_ht: isc_timer_detach(&zone->updatetimer); cleanup_timer: - isc_refcount_decrement(&zone->refs, NULL); + isc_refcount_decrement(&zone->refs); isc_refcount_destroy(&zone->refs); cleanup_refcount: @@ -2048,51 +2048,64 @@ cidr_free(dns_rpz_zones_t *rpzs) { static void rpz_detach(dns_rpz_zone_t **rpzp, dns_rpz_zones_t *rpzs) { dns_rpz_zone_t *rpz; - unsigned int refs; + int_fast32_t refs; rpz = *rpzp; *rpzp = NULL; - isc_refcount_decrement(&rpz->refs, &refs); - if (refs != 0) + refs = isc_refcount_decrement(&rpz->refs); + if (refs > 1) { return; + } + isc_refcount_destroy(&rpz->refs); - if (dns_name_dynamic(&rpz->origin)) + if (dns_name_dynamic(&rpz->origin)) { dns_name_free(&rpz->origin, rpzs->mctx); - if (dns_name_dynamic(&rpz->client_ip)) + } + if (dns_name_dynamic(&rpz->client_ip)) { dns_name_free(&rpz->client_ip, rpzs->mctx); - if (dns_name_dynamic(&rpz->ip)) + } + if (dns_name_dynamic(&rpz->ip)) { dns_name_free(&rpz->ip, rpzs->mctx); - if (dns_name_dynamic(&rpz->nsdname)) + } + if (dns_name_dynamic(&rpz->nsdname)) { dns_name_free(&rpz->nsdname, rpzs->mctx); - if (dns_name_dynamic(&rpz->nsip)) + } + if (dns_name_dynamic(&rpz->nsip)) { dns_name_free(&rpz->nsip, rpzs->mctx); - if (dns_name_dynamic(&rpz->passthru)) + } + if (dns_name_dynamic(&rpz->passthru)) { dns_name_free(&rpz->passthru, rpzs->mctx); - if (dns_name_dynamic(&rpz->drop)) + } + if (dns_name_dynamic(&rpz->drop)) { dns_name_free(&rpz->drop, rpzs->mctx); - if (dns_name_dynamic(&rpz->tcp_only)) + } + if (dns_name_dynamic(&rpz->tcp_only)) { dns_name_free(&rpz->tcp_only, rpzs->mctx); - if (dns_name_dynamic(&rpz->cname)) + } + if (dns_name_dynamic(&rpz->cname)) { dns_name_free(&rpz->cname, rpzs->mctx); - if (rpz->db_registered) + } + if (rpz->db_registered) { dns_db_updatenotify_unregister(rpz->db, dns_rpz_dbupdate_callback, rpz); - if (rpz->dbversion != NULL) + } + if (rpz->dbversion != NULL) { dns_db_closeversion(rpz->db, &rpz->dbversion, ISC_FALSE); - if (rpz->db) + } + if (rpz->db) { dns_db_detach(&rpz->db); + } isc_ht_destroy(&rpz->nodes); isc_timer_detach(&rpz->updatetimer); - isc_mem_put(rpzs->mctx, rpz, sizeof(*rpz)); } void dns_rpz_attach_rpzs(dns_rpz_zones_t *rpzs, dns_rpz_zones_t **rpzsp) { REQUIRE(rpzsp != NULL && *rpzsp == NULL); - isc_refcount_increment(&rpzs->refs, NULL); + isc_refcount_increment(&rpzs->refs); *rpzsp = rpzs; } @@ -2104,18 +2117,19 @@ dns_rpz_detach_rpzs(dns_rpz_zones_t **rpzsp) { dns_rpz_zones_t *rpzs; dns_rpz_zone_t *rpz; dns_rpz_num_t rpz_num; - unsigned int refs; + int_fast32_t refs; REQUIRE(rpzsp != NULL); rpzs = *rpzsp; REQUIRE(rpzs != NULL); *rpzsp = NULL; - isc_refcount_decrement(&rpzs->refs, &refs); - if (refs != 0) { + refs = isc_refcount_decrement(&rpzs->refs); + + if (refs > 1) { return; } - + /* * Forget the last of view's rpz machinery after the last reference. */ diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index 96a6d53bc38..f796091fa35 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -375,8 +375,9 @@ dns_tsigkey_createfromkey(const dns_name_t *name, const dns_name_t *algorithm, cleanup_refs: tkey->magic = 0; - while (refs-- > 0) - isc_refcount_decrement(&tkey->refs, NULL); + while (refs-- > 0) { + isc_refcount_decrement(&tkey->refs); + } isc_refcount_destroy(&tkey->refs); cleanup_creator: if (tkey->key != NULL) @@ -712,7 +713,7 @@ dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) { REQUIRE(VALID_TSIG_KEY(source)); REQUIRE(targetp != NULL && *targetp == NULL); - isc_refcount_increment(&source->refs, NULL); + isc_refcount_increment(&source->refs); *targetp = source; } @@ -741,16 +742,17 @@ tsigkey_free(dns_tsigkey_t *key) { void dns_tsigkey_detach(dns_tsigkey_t **keyp) { dns_tsigkey_t *key; - unsigned int refs; + int_fast32_t refs; REQUIRE(keyp != NULL); REQUIRE(VALID_TSIG_KEY(*keyp)); key = *keyp; - isc_refcount_decrement(&key->refs, &refs); + refs = isc_refcount_decrement(&key->refs); - if (refs == 0) + if (refs == 1) { tsigkey_free(key); + } *keyp = NULL; } @@ -1790,7 +1792,7 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, const dns_name_t *name, return (ISC_R_NOTFOUND); } #endif - isc_refcount_increment(&key->refs, NULL); + isc_refcount_increment(&key->refs); RWUNLOCK(&ring->lock, isc_rwlocktype_read); adjust_lru(key); *tsigkey = key; @@ -1859,8 +1861,9 @@ dns_tsigkeyring_add(dns_tsig_keyring_t *ring, const dns_name_t *name, isc_result_t result; result = keyring_add(ring, name, tkey); - if (result == ISC_R_SUCCESS) - isc_refcount_increment(&tkey->refs, NULL); + if (result == ISC_R_SUCCESS) { + isc_refcount_increment(&tkey->refs); + } return (result); } diff --git a/lib/dns/view.c b/lib/dns/view.c index 8fbdd7bf85a..236f2e22299 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -567,7 +567,7 @@ dns_view_attach(dns_view_t *source, dns_view_t **targetp) { REQUIRE(DNS_VIEW_VALID(source)); REQUIRE(targetp != NULL && *targetp == NULL); - isc_refcount_increment(&source->references, NULL); + isc_refcount_increment(&source->references); *targetp = source; } @@ -575,7 +575,7 @@ dns_view_attach(dns_view_t *source, dns_view_t **targetp) { static void view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) { dns_view_t *view; - unsigned int refs; + int_fast32_t refs; isc_boolean_t done = ISC_FALSE; REQUIRE(viewp != NULL); @@ -584,8 +584,8 @@ view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) { if (flush) view->flush = ISC_TRUE; - isc_refcount_decrement(&view->references, &refs); - if (refs == 0) { + refs = isc_refcount_decrement(&view->references); + if (refs == 1) { dns_zone_t *mkzone = NULL, *rdzone = NULL; LOCK(&view->lock); diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 03ece190a29..370df8078b4 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -1068,7 +1068,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { isc_stats_detach(&zone->gluecachestats); free_erefs: - isc_refcount_decrement(&zone->erefs, NULL); + isc_refcount_decrement(&zone->erefs); isc_refcount_destroy(&zone->erefs); free_dblock: @@ -5178,7 +5178,7 @@ void dns_zone_attach(dns_zone_t *source, dns_zone_t **target) { REQUIRE(DNS_ZONE_VALID(source)); REQUIRE(target != NULL && *target == NULL); - isc_refcount_increment(&source->erefs, NULL); + isc_refcount_increment(&source->erefs); *target = source; } @@ -5187,16 +5187,16 @@ dns_zone_detach(dns_zone_t **zonep) { dns_zone_t *zone; dns_zone_t *raw = NULL; dns_zone_t *secure = NULL; - unsigned int refs; + int_fast32_t refs; isc_boolean_t free_now = ISC_FALSE; REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep)); zone = *zonep; - isc_refcount_decrement(&zone->erefs, &refs); + refs = isc_refcount_decrement(&zone->erefs); - if (refs == 0) { + if (refs == 1) { LOCK_ZONE(zone); INSIST(zone != zone->raw); /* @@ -18461,7 +18461,7 @@ dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) { /* dns_zone_attach(raw, &zone->raw); */ - isc_refcount_increment(&raw->erefs, NULL); + isc_refcount_increment(&raw->erefs); zone->raw = raw; /* dns_zone_iattach(zone, &raw->secure); */ diff --git a/lib/isc/include/isc/refcount.h b/lib/isc/include/isc/refcount.h index cdb9f149b76..05690665552 100644 --- a/lib/isc/include/isc/refcount.h +++ b/lib/isc/include/isc/refcount.h @@ -22,6 +22,7 @@ #ifdef ISC_PLATFORM_USETHREADS #include +#include #endif /*! \file isc/refcount.h @@ -95,68 +96,65 @@ ISC_LANG_BEGINDECLS typedef atomic_int_fast32_t isc_refcount_t; -#define isc_refcount_current(ref) \ - ((unsigned int)(atomic_load_explicit(ref, \ - memory_order_relaxed))) -#define isc_refcount_destroy(ref) ISC_REQUIRE(isc_refcount_current(ref) == 0) - -#define isc_refcount_increment0(ref, tp) \ - do { \ - unsigned int *_tmp = (unsigned int *)(tp); \ - isc_int32_t prev; \ - prev = atomic_fetch_add_explicit \ - (ref, 1, memory_order_relaxed); \ - if (_tmp != NULL) \ - *_tmp = prev + 1; \ - } while (0) +static inline +isc_result_t +isc_refcount_init(isc_refcount_t *ref, int_fast32_t n) { + atomic_store_explicit(ref, n, memory_order_release); + return (ISC_R_SUCCESS); +} -#define isc_refcount_increment(ref, tp) \ - do { \ - unsigned int *_tmp = (unsigned int *)(tp); \ - isc_int32_t prev; \ - prev = atomic_fetch_add_explicit \ - (ref, 1, memory_order_relaxed); \ - ISC_REQUIRE(prev > 0); \ - if (_tmp != NULL) \ - *_tmp = prev + 1; \ - } while (0) +#define isc_refcount_current(ref) \ + atomic_load_explicit(ref, memory_order_acquire) -#define isc_refcount_decrement(ref, tp) \ - do { \ - unsigned int *_tmp = (unsigned int *)(tp); \ - isc_int32_t prev; \ - prev = atomic_fetch_sub_explicit \ - (ref, 1, memory_order_relaxed); \ - ISC_REQUIRE(prev > 0); \ - if (_tmp != NULL) \ - *_tmp = prev - 1; \ - } while (0) +static inline +void +isc_refcount_destroy(isc_refcount_t *ref) { + int_fast32_t cur = isc_refcount_current(ref); + ISC_REQUIRE(cur == 0); +} + +#define isc_refcount_increment0(ref) \ + atomic_fetch_add_explicit(ref, 1, memory_order_relaxed) + +static inline int_fast32_t isc_refcount_increment(isc_refcount_t *ref) { + int_fast32_t prev = atomic_fetch_add_explicit(ref, 1, + memory_order_relaxed); + ISC_REQUIRE(prev > 0); + return (prev); +} + +static inline int_fast32_t isc_refcount_decrement(isc_refcount_t *ref) { + int_fast32_t prev = atomic_fetch_sub_explicit(ref, 1, + memory_order_release); + ISC_REQUIRE(prev > 0); + return (prev); +} #else /* ISC_PLATFORM_USETHREADS */ -typedef struct isc_refcount { - int refs; -} isc_refcount_t; + +typedef isc_int32_t isc_refcount_t + +static inline +isc_result_t +isc_refcount_init(isc_refcount_t *ref, isc_refcount_t n) { + ISC_REQUIRE(ref); + *ref = n; + return (ISC_R_SUCCESS); +} #define isc_refcount_destroy(ref) ISC_REQUIRE(ref == 0) #define isc_refcount_current(ref) ((unsigned int)(ref) -#define isc_refcount_increment0(ref, tp) \ +#define isc_refcount_increment0(ref) \ do { \ - unsigned int *_tmp = (unsigned int *)(tp); \ - int _n = ++ref; \ - if (_tmp != NULL) \ - *_tmp = _n; \ + ++ref; \ } while (0) -#define isc_refcount_increment(ref, tp) \ +#define isc_refcount_increment(ref) \ do { \ - unsigned int *_tmp = (unsigned int *)(tp); \ - int _n; \ ISC_REQUIRE(ref > 0); \ - _n = ++ref; \ - if (_tmp != NULL) \ - *_tmp = _n; \ + ++ref; \ } while (0) #define isc_refcount_decrement(ref, tp) \ @@ -171,14 +169,6 @@ typedef struct isc_refcount { #endif /* ISC_PLATFORM_USETHREADS */ -static inline -isc_result_t -isc_refcount_init(isc_refcount_t *ref, isc_refcount_t n) { - ISC_REQUIRE(ref); - *ref = n; - return (ISC_R_SUCCESS); -} - ISC_LANG_ENDDECLS #endif /* ISC_REFCOUNT_H */ diff --git a/lib/isc/radix.c b/lib/isc/radix.c index 191d783671f..634fba566fa 100644 --- a/lib/isc/radix.c +++ b/lib/isc/radix.c @@ -76,14 +76,14 @@ _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest, static void _deref_prefix(isc_prefix_t *prefix) { - int refs; + int_fast32_t refs; if (prefix == NULL) return; - isc_refcount_decrement(&prefix->refcount, &refs); + refs = isc_refcount_decrement(&prefix->refcount); - if (refs <= 0) { + if (refs == 1) { isc_refcount_destroy(&prefix->refcount); isc_mem_putanddetach(&prefix->mctx, prefix, sizeof(isc_prefix_t)); @@ -110,7 +110,7 @@ _ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix) { return (ret); } - isc_refcount_increment(&prefix->refcount, NULL); + isc_refcount_increment(&prefix->refcount); *target = prefix; return (ISC_R_SUCCESS); diff --git a/lib/isc/stats.c b/lib/isc/stats.c index 36482835bb7..3cee9ce3eef 100644 --- a/lib/isc/stats.c +++ b/lib/isc/stats.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -51,15 +52,8 @@ struct isc_stats { isc_mem_t *mctx; int ncounters; - isc_mutex_t lock; - unsigned int references; /* locked by lock */ + isc_refcount_t references; - /*% - * Locked by counterlock or unlocked. - */ -#if ISC_STATS_LOCKCOUNTERS - isc_rwlock_t counterlock; -#endif isc_stat_t *counters; /*% @@ -81,9 +75,7 @@ isc_stats_attach(isc_stats_t *stats, isc_stats_t **statsp) { REQUIRE(ISC_STATS_VALID(stats)); REQUIRE(statsp != NULL && *statsp == NULL); - LOCK(&stats->lock); - stats->references++; - UNLOCK(&stats->lock); + isc_refcount_increment(&stats->references); *statsp = stats; } @@ -91,30 +83,23 @@ isc_stats_attach(isc_stats_t *stats, isc_stats_t **statsp) { void isc_stats_detach(isc_stats_t **statsp) { isc_stats_t *stats; + int_fast32_t refcount; REQUIRE(statsp != NULL && ISC_STATS_VALID(*statsp)); stats = *statsp; *statsp = NULL; - LOCK(&stats->lock); - stats->references--; + refcount = isc_refcount_decrement(&stats->references); - if (stats->references == 0) { + if (refcount == 1) { isc_mem_put(stats->mctx, stats->copiedcounters, sizeof(isc_stat_t) * stats->ncounters); isc_mem_put(stats->mctx, stats->counters, sizeof(isc_stat_t) * stats->ncounters); - UNLOCK(&stats->lock); - DESTROYLOCK(&stats->lock); -#if ISC_STATS_LOCKCOUNTERS - isc_rwlock_destroy(&stats->counterlock); -#endif isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats)); return; } - - UNLOCK(&stats->lock); } int @@ -135,14 +120,10 @@ isc_stats_create(isc_mem_t *mctx, isc_stats_t **statsp, int ncounters) { if (stats == NULL) return (ISC_R_NOMEMORY); - result = isc_mutex_init(&stats->lock); - if (result != ISC_R_SUCCESS) - goto clean_stats; - stats->counters = isc_mem_get(mctx, sizeof(isc_stat_t) * ncounters); if (stats->counters == NULL) { result = ISC_R_NOMEMORY; - goto clean_mutex; + goto clean_stats; } stats->copiedcounters = isc_mem_get(mctx, @@ -152,14 +133,7 @@ isc_stats_create(isc_mem_t *mctx, isc_stats_t **statsp, int ncounters) { goto clean_counters; } -#if ISC_STATS_LOCKCOUNTERS - result = isc_rwlock_init(&stats->counterlock, 0, 0); - if (result != ISC_R_SUCCESS) { - goto clean_copiedcounters; - } -#endif - - stats->references = 1; + isc_refcount_init(&stats->references, 1); memset(stats->counters, 0, sizeof(isc_stat_t) * ncounters); stats->mctx = NULL; isc_mem_attach(mctx, &stats->mctx); @@ -170,18 +144,9 @@ isc_stats_create(isc_mem_t *mctx, isc_stats_t **statsp, int ncounters) { return (result); -#if ISC_STATS_LOCKCOUNTERS -clean_copiedcounters: - isc_mem_put(mctx, stats->copiedcounters, - sizeof(isc_stat_t) * ncounters); -#endif - clean_counters: isc_mem_put(mctx, stats->counters, sizeof(isc_stat_t) * ncounters); -clean_mutex: - DESTROYLOCK(&stats->lock); - clean_stats: isc_mem_put(mctx, stats, sizeof(*stats)); @@ -193,21 +158,8 @@ isc_stats_increment(isc_stats_t *stats, isc_statscounter_t counter) { REQUIRE(ISC_STATS_VALID(stats)); REQUIRE(counter < stats->ncounters); #ifdef ISC_PLATFORM_USETHREADS - /* - * We use a "read" lock to prevent other threads from reading the - * counter while we "writing" a counter field. The write access itself - * is protected by the atomic operation. - */ -#if ISC_STATS_LOCKCOUNTERS - isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write); -#endif - atomic_fetch_add_explicit(&stats->counters[counter], 1, - memory_order_relaxed); - -#if ISC_STATS_LOCKCOUNTERS - isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write); -#endif + memory_order_release); #else /* ISC_PLATFORM_USETHREADS */ stats->counters[counter]++; #endif /* ISC_PLATFORM_USETHREADS */ @@ -219,16 +171,8 @@ isc_stats_decrement(isc_stats_t *stats, isc_statscounter_t counter) { REQUIRE(counter < stats->ncounters); #ifdef ISC_PLATFORM_USETHREADS -#if ISC_STATS_LOCKCOUNTERS - isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write); -#endif - atomic_fetch_sub_explicit(&stats->counters[counter], 1, - memory_order_relaxed); - -#if ISC_STATS_LOCKCOUNTERS - isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write); -#endif + memory_order_release); #else /* ISC_PLATFORM_USETHREADS */ stats->counters[counter]--; #endif /* ISC_PLATFORM_USETHREADS */ @@ -243,24 +187,12 @@ isc_stats_dump(isc_stats_t *stats, isc_stats_dumper_t dump_fn, REQUIRE(ISC_STATS_VALID(stats)); #ifdef ISC_PLATFORM_USETHREADS - /* - * We use a "write" lock before "reading" the statistics counters as - * an exclusive lock. - */ -#if ISC_STATS_LOCKCOUNTERS - isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_read); -#endif - for (i = 0; i < stats->ncounters; i++) { stats->copiedcounters[i] = atomic_load_explicit(&stats->counters[i], - memory_order_relaxed); + memory_order_acquire); } -#if ISC_STATS_LOCKCOUNTERS - isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read); -#endif - for (i = 0; i < stats->ncounters; i++) { if ((options & ISC_STATSDUMP_VERBOSE) == 0 && stats->copiedcounters[i] == 0) @@ -285,16 +217,8 @@ isc_stats_set(isc_stats_t *stats, isc_uint64_t val, REQUIRE(counter < stats->ncounters); #ifdef ISC_PLATFORM_USETHREADS -#if ISC_STATS_LOCKCOUNTERS - isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write); -#endif - atomic_store_explicit(&stats->counters[counter], val, - memory_order_relaxed); - -#if ISC_STATS_LOCKCOUNTERS - isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write); -#endif + memory_order_release); #else /* ISC_PLATFORM_USETHREADS */ stats->counters[counter] = val; #endif /* ISC_PLATFORM_USETHREADS */ diff --git a/lib/isccfg/aclconf.c b/lib/isccfg/aclconf.c index b3650c231a2..d14f8e9e28c 100644 --- a/lib/isccfg/aclconf.c +++ b/lib/isccfg/aclconf.c @@ -68,7 +68,7 @@ cfg_aclconfctx_attach(cfg_aclconfctx_t *src, cfg_aclconfctx_t **dest) { REQUIRE(src != NULL); REQUIRE(dest != NULL && *dest == NULL); - isc_refcount_increment(&src->references, NULL); + isc_refcount_increment(&src->references); *dest = src; } @@ -76,14 +76,14 @@ void cfg_aclconfctx_detach(cfg_aclconfctx_t **actxp) { cfg_aclconfctx_t *actx; dns_acl_t *dacl, *next; - unsigned int refs; + int_fast32_t refs; REQUIRE(actxp != NULL && *actxp != NULL); actx = *actxp; - isc_refcount_decrement(&actx->references, &refs); - if (refs == 0) { + refs = isc_refcount_decrement(&actx->references); + if (refs == 1) { for (dacl = ISC_LIST_HEAD(actx->named_acl_cache); dacl != NULL; dacl = next) diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c index 6e840161fb1..a7f5a9b77e7 100644 --- a/lib/isccfg/parser.c +++ b/lib/isccfg/parser.c @@ -657,22 +657,22 @@ cfg_parser_attach(cfg_parser_t *src, cfg_parser_t **dest) { REQUIRE(src != NULL); REQUIRE(dest != NULL && *dest == NULL); - isc_refcount_increment(&src->references, NULL); + isc_refcount_increment(&src->references); *dest = src; } void cfg_parser_destroy(cfg_parser_t **pctxp) { cfg_parser_t *pctx; - unsigned int refs; + int_fast32_t refs; REQUIRE(pctxp != NULL && *pctxp != NULL); pctx = *pctxp; *pctxp = NULL; - isc_refcount_decrement(&pctx->references, &refs); - if (refs == 0) { + refs = isc_refcount_decrement(&pctx->references); + if (refs == 1) { isc_lex_destroy(&pctx->lexer); /* * Cleaning up open_files does not @@ -3125,15 +3125,15 @@ cfg_obj_istype(const cfg_obj_t *obj, const cfg_type_t *type) { void cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **objp) { cfg_obj_t *obj; - unsigned int refs; + int_fast32_t refs; REQUIRE(objp != NULL && *objp != NULL); REQUIRE(pctx != NULL); obj = *objp; - isc_refcount_decrement(&obj->references, &refs); - if (refs == 0) { + refs = isc_refcount_decrement(&obj->references); + if (refs == 1) { obj->type->rep->free(pctx, obj); isc_refcount_destroy(&obj->references); isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t)); @@ -3143,11 +3143,11 @@ cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **objp) { void cfg_obj_attach(cfg_obj_t *src, cfg_obj_t **dest) { - REQUIRE(src != NULL); - REQUIRE(dest != NULL && *dest == NULL); + REQUIRE(src != NULL); + REQUIRE(dest != NULL && *dest == NULL); - isc_refcount_increment(&src->references, NULL); - *dest = src; + isc_refcount_increment(&src->references); + *dest = src; } static void diff --git a/lib/ns/server.c b/lib/ns/server.c index 01965aef649..96f2ae83829 100644 --- a/lib/ns/server.c +++ b/lib/ns/server.c @@ -122,7 +122,7 @@ ns_server_attach(ns_server_t *src, ns_server_t **dest) { REQUIRE(SCTX_VALID(src)); REQUIRE(dest != NULL && *dest == NULL); - isc_refcount_increment(&src->references, NULL); + isc_refcount_increment(&src->references); *dest = src; } @@ -130,14 +130,14 @@ ns_server_attach(ns_server_t *src, ns_server_t **dest) { void ns_server_detach(ns_server_t **sctxp) { ns_server_t *sctx; - unsigned int refs; + int_fast32_t refs; REQUIRE(sctxp != NULL); sctx = *sctxp; REQUIRE(SCTX_VALID(sctx)); - isc_refcount_decrement(&sctx->references, &refs); - if (refs == 0) { + refs = isc_refcount_decrement(&sctx->references); + if (refs == 1) { ns_altsecret_t *altsecret; sctx->magic = 0;