(void)__db_mutex_unlock(&lp_w->mutex, lt->fd);
(void)__db_mutex_unlock(&lp_w->mutex, lt->reginfo.fd);
__lock_put_internal(lt, lockp, do_all)	DB_LOCKTAB *lt;	struct __db_lock *lockp;	int do_all;{	struct __db_lock *lp_w, *lp_h, *next_waiter;	DB_LOCKOBJ *sh_obj;	int state_changed;	if (lockp->refcount == 0 || (lockp->status != DB_LSTAT_HELD &&	    lockp->status != DB_LSTAT_WAITING) || lockp->obj == 0) {		__db_err(lt->dbenv, "lock_put: invalid lock %lu",		    (u_long)((u_int8_t *)lockp - (u_int8_t *)lt->region));		return (EINVAL);	}	if (do_all)		lt->region->nreleases += lockp->refcount;	else		lt->region->nreleases++;	if (do_all == 0 && lockp->refcount > 1) {		lockp->refcount--;		return (0);	}	/* Get the object associated with this lock. */	sh_obj = (DB_LOCKOBJ *)((u_int8_t *)lockp + lockp->obj);	/* Remove lock from locker list. */	SH_LIST_REMOVE(lockp, locker_links, __db_lock);	/* Remove this lock from its holders/waitlist. */	if (lockp->status != DB_LSTAT_HELD)		__lock_remove_waiter(lt, sh_obj, lockp, DB_LSTAT_FREE);	else		SH_TAILQ_REMOVE(&sh_obj->holders, lockp, links, __db_lock);	/*	 * We need to do lock promotion.  We also need to determine if	 * we're going to need to run the deadlock detector again.  If	 * we release locks, and there are waiters, but no one gets promoted,	 * then we haven't fundamentally changed the lockmgr state, so	 * we may still have a deadlock and we have to run again.  However,	 * if there were no waiters, or we actually promoted someone, then	 * we are OK and we don't have to run it immediately.	 */	for (lp_w = SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock),	    state_changed = lp_w == NULL;	    lp_w != NULL;	    lp_w = next_waiter) {		next_waiter = SH_TAILQ_NEXT(lp_w, links, __db_lock);		for (lp_h = SH_TAILQ_FIRST(&sh_obj->holders, __db_lock);		    lp_h != NULL;		    lp_h = SH_TAILQ_NEXT(lp_h, links, __db_lock)) {			if (CONFLICTS(lt, lp_h->mode, lp_w->mode) &&			    lp_h->holder != lp_w->holder)				break;		}		if (lp_h != NULL)	/* Found a conflict. */			break;		/* No conflict, promote the waiting lock. */		SH_TAILQ_REMOVE(&sh_obj->waiters, lp_w, links, __db_lock);		lp_w->status = DB_LSTAT_PENDING;		SH_TAILQ_INSERT_TAIL(&sh_obj->holders, lp_w, links);		/* Wake up waiter. */		(void)__db_mutex_unlock(&lp_w->mutex, lt->fd);		state_changed = 1;	}	/* Check if object should be reclaimed. */	if (SH_TAILQ_FIRST(&sh_obj->holders, __db_lock) == NULL) {		HASHREMOVE_EL(lt->hashtab, __db_lockobj,		    links, sh_obj, lt->region->table_size, __lock_lhash);		if (sh_obj->lockobj.size > sizeof(sh_obj->objdata))			__db_shalloc_free(lt->mem,			    SH_DBT_PTR(&sh_obj->lockobj));		SH_TAILQ_INSERT_HEAD(&lt->region->free_objs, sh_obj, links,		    __db_lockobj);		state_changed = 1;	}	/* Free lock. */	lockp->status = DB_LSTAT_FREE;	SH_TAILQ_INSERT_HEAD(&lt->region->free_locks, lockp, links, __db_lock);	/*	 * If we did not promote anyone; we need to run the deadlock	 * detector again.	 */	if (state_changed == 0)		lt->region->need_dd = 1;	return (0);}