about summary refs log tree commit diff
path: root/db2/btree/bt_search.c
diff options
context:
space:
mode:
Diffstat (limited to 'db2/btree/bt_search.c')
-rw-r--r--db2/btree/bt_search.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/db2/btree/bt_search.c b/db2/btree/bt_search.c
index a21a8208bc..c39c9af322 100644
--- a/db2/btree/bt_search.c
+++ b/db2/btree/bt_search.c
@@ -47,7 +47,7 @@
 #include "config.h"
 
 #ifndef lint
-static const char sccsid[] = "@(#)bt_search.c	10.8 (Sleepycat) 10/25/97";
+static const char sccsid[] = "@(#)bt_search.c	10.9 (Sleepycat) 11/18/97";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -119,12 +119,20 @@ __bam_search(dbp, key, flags, stop, recnop, exactp)
 		return (ret);
 	}
 
-	/* Decide if we need to save this page; if we do, write lock it. */
+	/*
+	 * Decide if we need to save this page; if we do, write lock it.
+	 * We deliberately don't lock-couple on this call.  If the tree
+	 * is tiny, i.e., one page, and two threads are busily updating
+	 * the root page, we're almost guaranteed deadlocks galore, as
+	 * each one gets a read lock and then blocks the other's attempt
+	 * for a write lock.
+	 */
 	if (!stack &&
 	    ((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) ||
 	    (LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
 		(void)memp_fput(dbp->mpf, h, 0);
-		if ((ret = __bam_lget(dbp, 1, pg, DB_LOCK_WRITE, &lock)) != 0)
+		(void)__BT_LPUT(dbp, lock);
+		if ((ret = __bam_lget(dbp, 0, pg, DB_LOCK_WRITE, &lock)) != 0)
 			return (ret);
 		if ((ret = __bam_pget(dbp, &h, &pg, 0)) != 0) {
 			(void)__BT_LPUT(dbp, lock);