static bool
decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
rbtdb_serial_t least_serial, isc_rwlocktype_t *nlocktypep,
- isc_rwlocktype_t *tlocktypep, bool pruning) {
+ isc_rwlocktype_t *tlocktypep, bool tryupgrade,
+ bool pruning) {
isc_result_t result;
bool locked = *tlocktypep != isc_rwlocktype_none;
bool write_locked = false;
* the node lock before acquiring the tree write lock because
* we only do a trylock.
*/
+ /* We are allowed to upgrade the tree lock */
switch (*tlocktypep) {
case isc_rwlocktype_write:
result = ISC_R_SUCCESS;
break;
case isc_rwlocktype_read:
- result = TREE_TRYUPGRADE(&rbtdb->tree_lock, tlocktypep);
+ if (tryupgrade) {
+ result = TREE_TRYUPGRADE(&rbtdb->tree_lock, tlocktypep);
+ } else {
+ result = ISC_R_LOCKBUSY;
+ }
break;
case isc_rwlocktype_none:
result = TREE_TRYWRLOCK(&rbtdb->tree_lock, tlocktypep);
do {
parent = node->parent;
decrement_reference(rbtdb, node, 0, &nlocktype, &tlocktype,
- true);
+ true, true);
if (parent != NULL && parent->down == NULL) {
/*
resign_insert(rbtdb, header->node->locknum, header);
}
decrement_reference(rbtdb, header->node, least_serial,
- &nlocktype, &tlocktype, false);
+ &nlocktype, &tlocktype, true, false);
NODE_UNLOCK(lock, &nlocktype);
INSIST(tlocktype == isc_rwlocktype_none);
}
rollback_node(rbtnode, serial);
}
decrement_reference(rbtdb, rbtnode, least_serial,
- &nlocktype, &tlocktype, false);
+ &nlocktype, &tlocktype, true,
+ false);
NODE_UNLOCK(lock, &nlocktype);
NODE_RDLOCK(lock, &nlocktype);
decrement_reference(search.rbtdb, node, 0, &nlocktype,
- &tlocktype, false);
+ &tlocktype, true, false);
NODE_UNLOCK(lock, &nlocktype);
INSIST(tlocktype == isc_rwlocktype_none);
}
NODE_RDLOCK(lock, &nlocktype);
decrement_reference(search.rbtdb, node, 0, &nlocktype,
- &tlocktype, false);
+ &tlocktype, true, false);
NODE_UNLOCK(lock, &nlocktype);
INSIST(tlocktype == isc_rwlocktype_none);
}
NODE_RDLOCK(&nodelock->lock, &nlocktype);
- if (decrement_reference(rbtdb, node, 0, &nlocktype, &tlocktype, false))
- {
+ if (decrement_reference(rbtdb, node, 0, &nlocktype, &tlocktype, true,
+ false)) {
if (isc_refcount_current(&nodelock->references) == 0 &&
nodelock->exiting) {
inactive = true;
lock = &rbtdb->node_locks[node->locknum].lock;
NODE_RDLOCK(lock, &nlocktype);
decrement_reference(rbtdb, node, 0, &nlocktype, &rbtdbiter->tree_locked,
- false);
+ false, false);
NODE_UNLOCK(lock, &nlocktype);
- if (tlocktype != rbtdbiter->tree_locked) {
- TREE_UNLOCK(&rbtdb->tree_lock, &rbtdbiter->tree_locked);
- if (tlocktype == isc_rwlocktype_read) {
- TREE_RDLOCK(&rbtdb->tree_lock, &rbtdbiter->tree_locked);
- }
- }
INSIST(rbtdbiter->tree_locked == tlocktype);
rbtdbiter->node = NULL;
NODE_RDLOCK(lock, &nlocktype);
decrement_reference(rbtdb, node, 0, &nlocktype,
- &rbtdbiter->tree_locked, false);
+ &rbtdbiter->tree_locked, true, false);
NODE_UNLOCK(lock, &nlocktype);
}
*/
new_reference(rbtdb, header->node, nlocktype);
decrement_reference(rbtdb, header->node, 0, &nlocktype,
- tlocktypep, false);
+ tlocktypep, true, false);
if (rbtdb->cachestats == NULL) {
return;