Beside preventing crashes with vdr-2.6.3 this is required to
get vdr to work properly with the gcc thread sanitizer.
---
ringbuffer.c | 18 +++++++++++++++++-
ringbuffer.h | 3 +++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/ringbuffer.c b/ringbuffer.c
index 902c887..1c24df2 100644
--- a/ringbuffer.c
+++ b/ringbuffer.c
@@ -210,12 +210,16 @@ int cRingBufferLinear::DataReady(const uchar *Data, int Count)
int cRingBufferLinear::Available(void)
{
+ Lock();
int diff = head - tail;
- return (diff >= 0) ? diff : Size() + diff - margin;
+ int available = (diff >= 0) ? diff : Size() + diff - margin;
+ Unlock();
+ return available;
}
void cRingBufferLinear::Clear(void)
{
+ Lock();
int Head = head;
tail = Head;
#ifdef DEBUGRINGBUFFERS
@@ -224,11 +228,13 @@ void cRingBufferLinear::Clear(void)
lastPut = lastGet = -1;
#endif
maxFill = 0;
+ Unlock();
EnablePut();
}
int cRingBufferLinear::Read(int FileHandle, int Max)
{
+ Lock();
int Tail = tail;
int diff = Tail - head;
int free = (diff > 0) ? diff - 1 : Size() - head;
@@ -259,6 +265,7 @@ int cRingBufferLinear::Read(int FileHandle, int Max)
lastHead = head;
lastPut = Count;
#endif
+ Unlock();
EnableGet();
if (free == 0)
WaitForPut();
@@ -267,6 +274,7 @@ int cRingBufferLinear::Read(int FileHandle, int Max)
int cRingBufferLinear::Read(cUnbufferedFile *File, int Max)
{
+ Lock();
int Tail = tail;
int diff = Tail - head;
int free = (diff > 0) ? diff - 1 : Size() - head;
@@ -297,6 +305,7 @@ int cRingBufferLinear::Read(cUnbufferedFile *File, int Max)
lastHead = head;
lastPut = Count;
#endif
+ Unlock();
EnableGet();
if (free == 0)
WaitForPut();
@@ -306,6 +315,7 @@ int cRingBufferLinear::Read(cUnbufferedFile *File, int Max)
int cRingBufferLinear::Put(const uchar *Data, int Count)
{
if (Count > 0) {
+ Lock();
int Tail = tail;
int rest = Size() - head;
int diff = Tail - head;
@@ -336,6 +346,7 @@ int cRingBufferLinear::Put(const uchar *Data, int Count)
lastHead = head;
lastPut = Count;
#endif
+ Unlock();
EnableGet();
if (Count == 0)
WaitForPut();
@@ -345,6 +356,7 @@ int cRingBufferLinear::Put(const uchar *Data, int Count)
uchar *cRingBufferLinear::Get(int &Count)
{
+ Lock();
int Head = head;
if (getThreadTid <= 0)
getThreadTid = cThread::ThreadId();
@@ -362,14 +374,17 @@ uchar *cRingBufferLinear::Get(int &Count)
uchar *p = buffer + tail;
if ((cont = DataReady(p, cont)) > 0) {
Count = gotten = cont;
+ Unlock();
return p;
}
+ Unlock();
WaitForGet();
return NULL;
}
void cRingBufferLinear::Del(int Count)
{
+ Lock();
if (Count > gotten) {
esyslog("ERROR: invalid Count in cRingBufferLinear::Del: %d (limited to %d)", Count, gotten);
Count = gotten;
@@ -387,6 +402,7 @@ void cRingBufferLinear::Del(int Count)
lastTail = tail;
lastGet = Count;
#endif
+ Unlock();
}
// --- cFrame ----------------------------------------------------------------
diff --git a/ringbuffer.h b/ringbuffer.h
index 746fc51..cbaa12c 100644
--- a/ringbuffer.h
+++ b/ringbuffer.h
@@ -58,10 +58,13 @@ public:
static void PrintDebugRBL(void);
#endif
private:
+ cMutex mutex;
int margin, head, tail;
int gotten;
uchar *buffer;
char *description;
+ void Lock(void) { mutex.Lock(); }
+ void Unlock(void) { mutex.Unlock(); }
protected:
virtual int DataReady(const uchar *Data, int Count);
///< By default a ring buffer has data ready as soon as there are at least
--
2.39.1