Skip to content
Snippets Groups Projects
Commit 31f88f98 authored by Philippe Canal's avatar Philippe Canal
Browse files

RWLock: handle case of writer meeting a nested reader.

Prior to this update if a thread requested the write lock when another thread had two or more nested
read lock take, the code would dead-lock
parent b77e8064
No related branches found
No related tags found
No related merge requests found
...@@ -50,6 +50,10 @@ struct UniqueLockRecurseCount { ...@@ -50,6 +50,10 @@ struct UniqueLockRecurseCount {
template <typename MutexT> template <typename MutexT>
void DecrementReadCount(local_t &local, MutexT &) { DecrementReadCount(local); } void DecrementReadCount(local_t &local, MutexT &) { DecrementReadCount(local); }
void ResetReadCount(local_t &local, int newvalue) {
local->fReadersCount = newvalue;
}
bool IsNotCurrentWriter(local_t &local) { return !local->fIsWriter; } bool IsNotCurrentWriter(local_t &local) { return !local->fIsWriter; }
void SetIsWriter(local_t &local) void SetIsWriter(local_t &local)
...@@ -97,6 +101,10 @@ struct RecurseCounts { ...@@ -97,6 +101,10 @@ struct RecurseCounts {
DecrementReadCount(local); DecrementReadCount(local);
} }
void ResetReadCount(local_t &local, int newvalue) {
fReadersCount[local] = newvalue;
}
bool IsNotCurrentWriter(local_t &local) { return fWriterThread != local; } bool IsNotCurrentWriter(local_t &local) { return fWriterThread != local; }
void SetIsWriter(local_t &local) void SetIsWriter(local_t &local)
......
...@@ -35,6 +35,7 @@ thus preventing starvation. ...@@ -35,6 +35,7 @@ thus preventing starvation.
#include "ROOT/TSpinMutex.hxx" #include "ROOT/TSpinMutex.hxx"
#include "TMutex.h" #include "TMutex.h"
#include "TError.h" #include "TError.h"
#include <assert.h>
using namespace ROOT; using namespace ROOT;
...@@ -75,7 +76,21 @@ void TReentrantRWLock<MutexT, RecurseCountsT>::ReadLock() ...@@ -75,7 +76,21 @@ void TReentrantRWLock<MutexT, RecurseCountsT>::ReadLock()
std::unique_lock<MutexT> lock(fMutex); std::unique_lock<MutexT> lock(fMutex);
// Wait for writers, if any // Wait for writers, if any
if (fWriter && fRecurseCounts.IsNotCurrentWriter(local)) fCond.wait(lock, [this] { return !fWriter; }); if (fWriter && fRecurseCounts.IsNotCurrentWriter(local)) {
auto readerCount = fRecurseCounts.GetLocalReadersCount(local);
if (readerCount == 0)
fCond.wait(lock, [this] { return !fWriter; });
// else
// There is a writer **but** we have outstanding readers
// locks, this must mean that the writer is actually
// waiting on this thread to release its read locks.
// This can be done in only two ways:
// * request the writer lock
// * release the reader lock
// Either way, this thread needs to proceed to
// be able to reach a point whether it does one
// of the two.
}
fRecurseCounts.IncrementReadCount(local); fRecurseCounts.IncrementReadCount(local);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment