8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 19:23:03 +01:00

Fixed bug CORE-2000 : Lock manager reported false deadlocks under high load

This commit is contained in:
hvlad 2008-07-28 21:21:21 +00:00
parent 7711c2806c
commit c1b161fc2d
2 changed files with 23 additions and 7 deletions

View File

@ -1814,9 +1814,12 @@ lrq* LockManager::deadlock_walk(lrq* request, bool* maybe_deadlock)
// Don't pursue lock owners that still have to finish processing their AST.
// If the blocking queue is not empty, then the owner still has some
// AST's to process (or lock reposts).
// hvlad: also lock maybe just granted to owner and blocked owners have no
// time to send blocking ATS
// Remember this fact because they still might be part of a deadlock.
if (owner->own_flags & OWN_signaled || !SRQ_EMPTY((owner->own_blocks)))
if (owner->own_flags & (OWN_signaled | OWN_wakeup) || !SRQ_EMPTY((owner->own_blocks)) ||
block->lrq_flags & LRQ_just_granted)
{
*maybe_deadlock = true;
continue;
@ -2541,7 +2544,7 @@ void LockManager::post_blockage(thread_db* tdbb, lrq* request, lbl* lock)
if (!(block->lrq_flags & LRQ_blocking)) {
insert_tail(&blocking_owner->own_blocks, &block->lrq_own_blocks);
block->lrq_flags |= LRQ_blocking;
block->lrq_flags &= ~LRQ_blocking_seen;
block->lrq_flags &= ~(LRQ_blocking_seen | LRQ_just_granted);
}
if (blocking_owner != owner)
@ -2654,7 +2657,7 @@ void LockManager::post_pending(lbl* lock)
post_wakeup(owner);
if (lockOrdering()) {
CHECK(lock->lbl_pending_lrq_count >= pending_counter);
return;
break;
}
}
}
@ -2668,12 +2671,24 @@ void LockManager::post_pending(lbl* lock)
post_wakeup(owner);
if (lockOrdering()) {
CHECK(lock->lbl_pending_lrq_count >= pending_counter);
return;
break;
}
}
}
CHECK(lock->lbl_pending_lrq_count == pending_counter);
CHECK(lock->lbl_pending_lrq_count >= pending_counter);
if (lock->lbl_pending_lrq_count) {
SRQ_LOOP(lock->lbl_requests, lock_srq)
{
lrq* request = (lrq*) ((UCHAR *) lock_srq - OFFSET(lrq*, lrq_lbl_requests));
if (request->lrq_flags & LRQ_pending)
break;
if (!(request->lrq_flags & (LRQ_blocking | LRQ_blocking_seen)))
request->lrq_flags |= LRQ_just_granted;
}
}
}
@ -3005,7 +3020,7 @@ void LockManager::release_request(lrq* request)
request->lrq_flags &= ~LRQ_blocking;
}
request->lrq_flags &= ~LRQ_blocking_seen;
request->lrq_flags &= ~(LRQ_blocking_seen | LRQ_just_granted);
// Update counts if we are cleaning up something we're waiting on!
// This should only happen if we are purging out an owner that died.
@ -3552,7 +3567,7 @@ void LockManager::validate_request(const SRQ_PTR lrq_ptr, USHORT freed, USHORT r
(request->lrq_flags &
~(LRQ_blocking | LRQ_pending | LRQ_converting |
LRQ_rejected | LRQ_timed_out | LRQ_deadlock |
LRQ_repost | LRQ_scanned | LRQ_blocking_seen)));
LRQ_repost | LRQ_scanned | LRQ_blocking_seen | LRQ_just_granted)));
// LRQ_converting & LRQ_timed_out are defined, but never actually used
CHECK(!(request->lrq_flags & (LRQ_converting | LRQ_timed_out)));

View File

@ -225,6 +225,7 @@ const USHORT LRQ_deadlock = 32; // Request has been seen by the deadlock-walk
const USHORT LRQ_repost = 64; // Request block used for repost
const USHORT LRQ_scanned = 128; // Request already scanned for deadlock
const USHORT LRQ_blocking_seen = 256; // Blocking notification received by owner
const USHORT LRQ_just_granted = 512; // Request is just granted and blocked owners still have not sent blocking AST
// Process block