(void)__db_mutex_lock(&newl->mutex, lt->fd);
(void)__db_mutex_lock(&newl->mutex, lt->reginfo.fd);
__lock_get_internal(lt, locker, flags, obj, lock_mode, lockp)	DB_LOCKTAB *lt;	u_int32_t locker;	int flags;	const DBT *obj;	db_lockmode_t lock_mode;	struct __db_lock **lockp;{	struct __db_lock *newl, *lp;	DB_LOCKOBJ *sh_obj, *sh_locker;	DB_LOCKREGION *lrp;	size_t newl_off;	int ihold, ret;	ret = 0;	/*	 * Check that lock mode is valid.	 */	lrp = lt->region;	if ((u_int32_t)lock_mode >= lrp->nmodes) {		__db_err(lt->dbenv,		    "lock_get: invalid lock mode %lu\n", (u_long)lock_mode);		return (EINVAL);	}	/* Allocate a new lock.  Optimize for the common case of a grant. */	if ((newl = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock)) == NULL) {		if ((ret = __lock_grow_region(lt, DB_LOCK_LOCK, 0)) != 0)			return (ret);		lrp = lt->region;		newl = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock);	}	newl_off = LOCK_TO_OFFSET(lt, newl);	/* Optimize for common case of granting a lock. */	SH_TAILQ_REMOVE(&lrp->free_locks, newl, links, __db_lock);	newl->mode = lock_mode;	newl->status = DB_LSTAT_HELD;	newl->holder = locker;	newl->refcount = 1;	if ((ret = __lock_getobj(lt, 0, obj, DB_LOCK_OBJTYPE, &sh_obj)) != 0)		return (ret);	lrp = lt->region;			/* getobj might have grown */	newl = OFFSET_TO_LOCK(lt, newl_off);	/* Now make new lock point to object */	newl->obj = SH_PTR_TO_OFF(newl, sh_obj);	/*	 * Now we have a lock and an object and we need to see if we should	 * grant the lock.  We use a FIFO ordering so we can only grant a	 * new lock if it does not conflict with anyone on the holders list	 * OR anyone on the waiters list.  The reason that we don't grant if	 * there's a conflict is that this can lead to starvation (a writer	 * waiting on a popularly read item will never be granted).  The	 * downside of this is that a waiting reader can prevent an upgrade	 * from reader to writer, which is not uncommon.	 *	 * There is one exception to the no-conflict rule.  If a lock is held	 * by the requesting locker AND the new lock does not conflict with	 * any other holders, then we grant the lock.  The most common place	 * this happens is when the holder has a WRITE lock and a READ lock	 * request comes in for the same locker.  If we do not grant the read	 * lock, then we guarantee deadlock.	 *	 * In case of conflict, we put the new lock on the end of the waiters	 * list.	 */	ihold = 0;	for (lp = SH_TAILQ_FIRST(&sh_obj->holders, __db_lock);	    lp != NULL;	    lp = SH_TAILQ_NEXT(lp, links, __db_lock)) {		if (locker == lp->holder) {			if (lp->mode == lock_mode &&			    lp->status == DB_LSTAT_HELD) {				/* Lock is held, just inc the ref count. */				lp->refcount++;				SH_TAILQ_INSERT_HEAD(&lrp->free_locks,				    newl, links, __db_lock);				*lockp = lp;				return (0);			} else				ihold = 1;		} else if (CONFLICTS(lt, lp->mode, lock_mode))			break;    	}	if (lp == NULL && !ihold)		for (lp = SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock);		    lp != NULL;		    lp = SH_TAILQ_NEXT(lp, links, __db_lock)) {			if (CONFLICTS(lt, lp->mode, lock_mode) &&			    locker != lp->holder)				break;		}	if (lp == NULL)		SH_TAILQ_INSERT_TAIL(&sh_obj->holders, newl, links);	else if (!(flags & DB_LOCK_NOWAIT))		SH_TAILQ_INSERT_TAIL(&sh_obj->waiters, newl, links);	else {		/* Free the lock and return an error. */		newl->status = DB_LSTAT_FREE;		SH_TAILQ_INSERT_HEAD(&lrp->free_locks, newl, links, __db_lock);		return (DB_LOCK_NOTGRANTED);	}	/*	 * This is really a blocker for the process, so initialize it	 * set.  That way the current process will block when it tries	 * to get it and the waking process will release it.	 */	(void)__db_mutex_init(&newl->mutex,	    MUTEX_LOCK_OFFSET(lt->region, &newl->mutex));	(void)__db_mutex_lock(&newl->mutex, lt->fd);	/*	 * Now, insert the lock onto its locker's list.	 */	if ((ret =	    __lock_getobj(lt, locker, NULL, DB_LOCK_LOCKER, &sh_locker)) != 0)		return (ret);	lrp = lt->region;	SH_LIST_INSERT_HEAD(&sh_locker->heldby, newl, locker_links, __db_lock);	if (lp != NULL) {		newl->status = DB_LSTAT_WAITING;		lrp->nconflicts++;		/*		 * We are about to wait; must release the region mutex.		 * Then, when we wakeup, we need to reacquire the region		 * mutex before continuing.		 */		if (lrp->detect == DB_LOCK_NORUN)			lt->region->need_dd = 1;		UNLOCK_LOCKREGION(lt);		/*		 * We are about to wait; before waiting, see if the deadlock		 * detector should be run.		 */		if (lrp->detect != DB_LOCK_NORUN)			ret = lock_detect(lt, 0, lrp->detect);		(void)__db_mutex_lock(&newl->mutex, lt->fd);		LOCK_LOCKREGION(lt);		if (newl->status != DB_LSTAT_PENDING) {			/* Return to free list. */			__lock_checklocker(lt, newl, 0);			SH_TAILQ_INSERT_HEAD(&lrp->free_locks, newl, links,			    __db_lock);			switch (newl->status) {				case DB_LSTAT_ABORTED:					ret = DB_LOCK_DEADLOCK;					break;				case DB_LSTAT_NOGRANT:					ret = DB_LOCK_NOTGRANTED;					break;				default:					ret = EINVAL;					break;			}			newl->status = DB_LSTAT_FREE;			newl = NULL;		} else			newl->status = DB_LSTAT_HELD;	}	*lockp = newl;	return (ret);}