summaryrefslogtreecommitdiff
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);