mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
The cRwLock class now allows nested read locks within a write lock from the same thread
This commit is contained in:
parent
ce6c90a450
commit
85ae27e372
4
HISTORY
4
HISTORY
@ -8839,3 +8839,7 @@ Video Disk Recorder Revision History
|
||||
instead.
|
||||
- The SVDRP command DELC now refuses to delete the very last channel in the list,
|
||||
to avoid ending up with an empty channel list.
|
||||
- The cRwLock class now allows nested read locks within a write lock from the
|
||||
same thread. This fixes possible crashes when moving or deleting channels in
|
||||
the menu or through SVDRP (as well as other operations that try to acquire a
|
||||
read lock within a write lock).
|
||||
|
22
thread.c
22
thread.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: thread.c 4.1 2015/08/29 14:43:03 kls Exp $
|
||||
* $Id: thread.c 4.2 2016/12/08 10:18:32 kls Exp $
|
||||
*/
|
||||
|
||||
#include "thread.h"
|
||||
@ -151,6 +151,8 @@ void cCondVar::Broadcast(void)
|
||||
|
||||
cRwLock::cRwLock(bool PreferWriter)
|
||||
{
|
||||
locked = 0;
|
||||
writeLockThreadId = 0;
|
||||
pthread_rwlockattr_t attr;
|
||||
pthread_rwlockattr_init(&attr);
|
||||
pthread_rwlockattr_setkind_np(&attr, PreferWriter ? PTHREAD_RWLOCK_PREFER_WRITER_NP : PTHREAD_RWLOCK_PREFER_READER_NP);
|
||||
@ -170,8 +172,15 @@ bool cRwLock::Lock(bool Write, int TimeoutMs)
|
||||
if (!GetAbsTime(&abstime, TimeoutMs))
|
||||
TimeoutMs = 0;
|
||||
}
|
||||
if (Write)
|
||||
if (Write) {
|
||||
Result = TimeoutMs ? pthread_rwlock_timedwrlock(&rwlock, &abstime) : pthread_rwlock_wrlock(&rwlock);
|
||||
if (Result == 0)
|
||||
writeLockThreadId = cThread::ThreadId();
|
||||
}
|
||||
else if (writeLockThreadId == cThread::ThreadId()) {
|
||||
locked++; // there can be any number of stacked read locks, so we keep track here
|
||||
Result = 0; // aquiring a read lock while holding a write lock within the same thread is OK
|
||||
}
|
||||
else
|
||||
Result = TimeoutMs ? pthread_rwlock_timedrdlock(&rwlock, &abstime) : pthread_rwlock_rdlock(&rwlock);
|
||||
return Result == 0;
|
||||
@ -179,6 +188,13 @@ bool cRwLock::Lock(bool Write, int TimeoutMs)
|
||||
|
||||
void cRwLock::Unlock(void)
|
||||
{
|
||||
if (writeLockThreadId == cThread::ThreadId()) { // this is the thread that obtained the initial write lock
|
||||
if (locked) { // this is the unlock of a read lock within the write lock
|
||||
locked--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
writeLockThreadId = 0;
|
||||
pthread_rwlock_unlock(&rwlock);
|
||||
}
|
||||
|
||||
@ -474,9 +490,11 @@ void cStateLock::Unlock(cStateKey &StateKey, bool IncState)
|
||||
if (StateKey.write && IncState && !explicitModify)
|
||||
state++;
|
||||
StateKey.state = state;
|
||||
if (StateKey.write) {
|
||||
StateKey.write = false;
|
||||
threadId = 0;
|
||||
explicitModify = false;
|
||||
}
|
||||
rwLock.Unlock();
|
||||
}
|
||||
|
||||
|
8
thread.h
8
thread.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: thread.h 4.1 2015/08/17 13:06:24 kls Exp $
|
||||
* $Id: thread.h 4.2 2016/12/08 10:18:32 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __THREAD_H
|
||||
@ -14,6 +14,8 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef pid_t tThreadId;
|
||||
|
||||
class cCondWait {
|
||||
private:
|
||||
pthread_mutex_t mutex;
|
||||
@ -53,6 +55,8 @@ public:
|
||||
class cRwLock {
|
||||
private:
|
||||
pthread_rwlock_t rwlock;
|
||||
int locked;
|
||||
tThreadId writeLockThreadId;
|
||||
public:
|
||||
cRwLock(bool PreferWriter = false);
|
||||
~cRwLock();
|
||||
@ -72,8 +76,6 @@ public:
|
||||
void Unlock(void);
|
||||
};
|
||||
|
||||
typedef pid_t tThreadId;
|
||||
|
||||
class cThread {
|
||||
friend class cThreadLock;
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user