in src/Trinity.C/src/Storage/LocalStorage/ThreadContext.cpp [211:310]
static bool _CalculateLockDependency(const THREAD_CONTEXT& a, const THREAD_CONTEXT& b)
{
auto sa = _GetThreadContextStatus(a);
auto sb = _GetThreadContextStatus(b);
if (sa == LOCKCELL) switch (sb)
{
case LOCKCELL:
// a is locking a cell held by b
return b.LockedCells.Contains(a.LockingCell);
case LOCKHASH:
// a is locking a cell, whose bucket lock is taken by b.
// or b is holding the lock.
return (Storage::LocalMemoryStorage::GetTrunkId(a.LockingCell) ==
b.LockingMTHash)
|| b.LockedCells.Contains(a.LockingCell);
case RELOAD:
// a is locking a cell, whose trunk is being reloaded
// or b is holding the lock.
return (Storage::LocalMemoryStorage::GetTrunkId(a.LockingCell) ==
Storage::LocalMemoryStorage::GetTrunkId(b.LockingCell))
|| b.LockedCells.Contains(a.LockingCell);
case LOCKDB:
// a is locking a cell while the db is being locked
return true;
}
else if (sb == LOCKCELL) switch (sa)
{
//case LOCKCELL: <-- already executed in previous branch
case LOCKHASH:
// a is locking a MTHash, while b possesses cell locks in this MTHash
return b.LockedCells.Any([&](cellid_t lockedCell)
{
return
Storage::LocalMemoryStorage::GetTrunkId(lockedCell) ==
a.LockingMTHash;
});
case RELOAD:
// a is reloading while b has locked a cell in the same MTHash
return b.LockedCells.Any([&](cellid_t lockedCell)
{
return
Storage::LocalMemoryStorage::GetTrunkId(lockedCell) ==
Storage::LocalMemoryStorage::GetTrunkId(a.LockingCell);
});
case LOCKDB:
// a is locking db, while b possesses cell locks
return (b.LockedCells.size() != 0);
}
/*(sa != LOCKCELL && sb != LOCKCELL)*/
else if (sa == RELOAD) switch(sb)
{
case LOCKHASH:
case LOCKDB:
// a is reloading a MTHash, and b possesses some locks in that trunk.
return b.LockedCells.Any([&](cellid_t lockedCell)
{
return
Storage::LocalMemoryStorage::GetTrunkId(lockedCell) ==
Storage::LocalMemoryStorage::GetTrunkId(a.LockingCell);
});
case RELOAD:
// when both a and b are reloading (they should be reloading different trunks
// due to the alloc_lock), they do not lock each other, because they share
// g_memory_arena and thus are aware of each other's context.
return false;
}
else if (sa == LOCKHASH) switch (sb)
{
case LOCKHASH:
case LOCKDB:
// a is locking a MTHash, while b possesses cell locks in that trunk.
return b.LockedCells.Any([&](cellid_t lockedCell)
{
return
Storage::LocalMemoryStorage::GetTrunkId(lockedCell) ==
a.LockingMTHash;
});
break;
case RELOAD:
// a is locking a MTHash, while b is reloading this MTHash (taken all entries)
return
a.LockingMTHash ==
Storage::LocalMemoryStorage::GetTrunkId(b.LockingCell);
break;
}
else if (sa == LOCKDB) switch (sb)
{
case LOCKHASH:
case LOCKDB:
// a is locking db and b possesses cell locks.
return (b.LockedCells.size() != 0);
case RELOAD:
// a is locking db and b is reloading, and thus possesses at least one cell lock.
return true;
}
assert(false && "_CalculateDependency_LOCKCELL");
return false;
}