#include <isc/mem.h>
#include <isc/print.h>
+#include <isc/refcount.h>
#include <isc/rwlock.h>
#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/util.h>
/* Unlocked. */
unsigned int magic;
isc_mem_t *mctx;
- isc_mutex_t lock;
+ isc_refcount_t active_nodes;
+ isc_refcount_t references;
isc_rwlock_t rwlock;
- /* Locked by lock. */
- isc_uint32_t active_nodes;
/* Locked by rwlock. */
- isc_uint32_t references;
dns_rbt_t *table;
};
REQUIRE(keytablep != NULL && *keytablep == NULL);
keytable = isc_mem_get(mctx, sizeof(*keytable));
- if (keytable == NULL)
+ if (keytable == NULL) {
return (ISC_R_NOMEMORY);
+ }
keytable->table = NULL;
result = dns_rbt_create(mctx, free_keynode, mctx, &keytable->table);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
goto cleanup_keytable;
+ }
- result = isc_mutex_init(&keytable->lock);
- if (result != ISC_R_SUCCESS)
+ result = isc_rwlock_init(&keytable->rwlock, 0, 0);
+ if (result != ISC_R_SUCCESS) {
goto cleanup_rbt;
+ }
- result = isc_rwlock_init(&keytable->rwlock, 0, 0);
- if (result != ISC_R_SUCCESS)
- goto cleanup_lock;
+ result = isc_refcount_init(&keytable->active_nodes, 0);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup_rwlock;
+ }
+
+ result = isc_refcount_init(&keytable->references, 1);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup_active_nodes;
+ }
keytable->mctx = NULL;
isc_mem_attach(mctx, &keytable->mctx);
- keytable->active_nodes = 0;
- keytable->references = 1;
keytable->magic = KEYTABLE_MAGIC;
*keytablep = keytable;
return (ISC_R_SUCCESS);
- cleanup_lock:
- DESTROYLOCK(&keytable->lock);
+ cleanup_active_nodes:
+ isc_refcount_destroy(&keytable->active_nodes);
- cleanup_rbt:
+ cleanup_rwlock:
+ isc_rwlock_destroy(&keytable->rwlock);
+
+ cleanup_rbt:
dns_rbt_destroy(&keytable->table);
- cleanup_keytable:
+ cleanup_keytable:
isc_mem_putanddetach(&mctx, keytable, sizeof(*keytable));
return (result);
REQUIRE(VALID_KEYTABLE(source));
REQUIRE(targetp != NULL && *targetp == NULL);
- RWLOCK(&source->rwlock, isc_rwlocktype_write);
-
- INSIST(source->references > 0);
- source->references++;
- INSIST(source->references != 0);
-
- RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
+ isc_refcount_increment(&source->references, NULL);
*targetp = source;
}
void
dns_keytable_detach(dns_keytable_t **keytablep) {
- isc_boolean_t destroy = ISC_FALSE;
dns_keytable_t *keytable;
+ unsigned int refs;
/*
* Detach *keytablep from its keytable.
REQUIRE(keytablep != NULL && VALID_KEYTABLE(*keytablep));
keytable = *keytablep;
+ *keytablep = NULL;
- RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
-
- INSIST(keytable->references > 0);
- keytable->references--;
- LOCK(&keytable->lock);
- if (keytable->references == 0 && keytable->active_nodes == 0)
- destroy = ISC_TRUE;
- UNLOCK(&keytable->lock);
-
- RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
-
- if (destroy) {
+ isc_refcount_decrement(&keytable->references, &refs);
+ if (refs == 0) {
+ INSIST(isc_refcount_current(&keytable->active_nodes) == 0);
+ isc_refcount_destroy(&keytable->active_nodes);
+ isc_refcount_destroy(&keytable->references);
dns_rbt_destroy(&keytable->table);
isc_rwlock_destroy(&keytable->rwlock);
- DESTROYLOCK(&keytable->lock);
keytable->magic = 0;
isc_mem_putanddetach(&keytable->mctx,
keytable, sizeof(*keytable));
}
-
- *keytablep = NULL;
}
static isc_result_t
DNS_RBTFIND_NOOPTIONS, NULL, NULL);
if (result == ISC_R_SUCCESS) {
if (node->data != NULL) {
- LOCK(&keytable->lock);
- keytable->active_nodes++;
- UNLOCK(&keytable->lock);
+ isc_refcount_increment0(&keytable->active_nodes, NULL);
dns_keynode_attach(node->data, keynodep);
} else
result = ISC_R_NOTFOUND;
return (ISC_R_NOTFOUND);
dns_keynode_attach(keynode->next, nextnodep);
- LOCK(&keytable->lock);
- keytable->active_nodes++;
- UNLOCK(&keytable->lock);
+ isc_refcount_increment(&keytable->active_nodes, NULL);
return (ISC_R_SUCCESS);
}
break;
}
if (knode != NULL) {
- LOCK(&keytable->lock);
- keytable->active_nodes++;
- UNLOCK(&keytable->lock);
+ isc_refcount_increment0(&keytable->active_nodes, NULL);
dns_keynode_attach(knode, keynodep);
} else
result = DNS_R_PARTIALMATCH;
break;
}
if (knode != NULL) {
- LOCK(&keytable->lock);
- keytable->active_nodes++;
- UNLOCK(&keytable->lock);
+ isc_refcount_increment(&keytable->active_nodes, NULL);
result = ISC_R_SUCCESS;
dns_keynode_attach(knode, nextnodep);
} else
REQUIRE(VALID_KEYNODE(source));
REQUIRE(target != NULL && *target == NULL);
- LOCK(&keytable->lock);
- keytable->active_nodes++;
- UNLOCK(&keytable->lock);
+ isc_refcount_increment(&keytable->active_nodes, NULL);
dns_keynode_attach(source, target);
}
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
- LOCK(&keytable->lock);
- INSIST(keytable->active_nodes > 0);
- keytable->active_nodes--;
- UNLOCK(&keytable->lock);
-
+ isc_refcount_decrement(&keytable->active_nodes, NULL);
dns_keynode_detach(keytable->mctx, keynodep);
}
result = ISC_R_SUCCESS;
goto cleanup;
}
+ isc_refcount_increment0(&keytable->active_nodes, NULL);
for (;;) {
dns_rbtnodechain_current(&chain, NULL, NULL, &node);
if (node->data != NULL)
break;
}
}
+ isc_refcount_decrement(&keytable->active_nodes, NULL);
cleanup:
dns_rbtnodechain_invalidate(&chain);
isc_result_t
dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
isc_result_t result;
- dns_keynode_t *knode = NULL;
+ dns_keynode_t *knode;
REQUIRE(target != NULL && *target == NULL);