Fixed cDvbTuner to avoid lockups on NPTL systems

This commit is contained in:
Klaus Schmidinger 2005-08-21 09:25:51 +02:00
parent 9dd6796702
commit 7533b69e9b
3 changed files with 40 additions and 27 deletions

View File

@ -737,6 +737,7 @@ Marcel Wiesweg <marcel.wiesweg@gmx.de>
for adding play mode pmVideoOnly
for fixing a possible crash with inconsistent SI data
for pointing out a problem with the cChannel copy constructor
for fixing cDvbTuner to avoid lockups on NPTL systems
Torsten Herz <torsten.herz@web.de>
for fixing a possible deadlock when using the "Blue" button in the "Schedules" menu

View File

@ -3710,3 +3710,4 @@ Video Disk Recorder Revision History
available" happens if VDR is started with the current channel being an encrypted
one, or a timer on such a channel hits right after starting VDR.
- Fixed cVideoRepacker to better handle errors in data (thanks to Reinhard Nissl).
- Fixed cDvbTuner to avoid lockups on NPTL systems (thanks to Marcel Wiesweg).

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbdevice.c 1.135 2005/08/20 15:22:36 kls Exp $
* $Id: dvbdevice.c 1.136 2005/08/21 09:17:20 kls Exp $
*/
#include "dvbdevice.h"
@ -81,7 +81,7 @@ private:
eTunerStatus tunerStatus;
cMutex mutex;
cCondVar locked;
cCondWait newSet;
cCondVar newSet;
bool GetFrontendEvent(dvb_frontend_event &Event, int TimeoutMs = 0);
bool SetFrontend(void);
virtual void Action(void);
@ -112,7 +112,8 @@ cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType, cCi
cDvbTuner::~cDvbTuner()
{
tunerStatus = tsIdle;
newSet.Signal();
newSet.Broadcast();
locked.Broadcast();
Cancel(3);
}
@ -123,7 +124,7 @@ bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
void cDvbTuner::Set(const cChannel *Channel, bool Tune, bool UseCa)
{
Lock();
cMutexLock MutexLock(&mutex);
if (Tune)
tunerStatus = tsSet;
else if (tunerStatus == tsCam)
@ -132,12 +133,15 @@ void cDvbTuner::Set(const cChannel *Channel, bool Tune, bool UseCa)
if (Channel->Ca() && tunerStatus != tsCam)
startTime = time(NULL);
channel = *Channel;
Unlock();
newSet.Signal();
newSet.Broadcast();
}
bool cDvbTuner::Locked(int TimeoutMs)
{
bool isLocked = (tunerStatus >= tsLocked);
if (isLocked || !TimeoutMs)
return isLocked;
cMutexLock MutexLock(&mutex);
if (TimeoutMs && tunerStatus < tsLocked)
locked.TimedWait(mutex, TimeoutMs);
@ -292,25 +296,33 @@ void cDvbTuner::Action(void)
{
dvb_frontend_event event;
while (Running()) {
Lock();
if (tunerStatus == tsSet) {
while (GetFrontendEvent(event))
; // discard stale events
tunerStatus = SetFrontend() ? tsTuned : tsIdle;
}
if (tunerStatus != tsIdle) {
while (GetFrontendEvent(event, 10)) {
if (event.status & FE_REINIT) {
tunerStatus = tsSet;
esyslog("ERROR: frontend %d was reinitialized - re-tuning", cardIndex);
}
if (event.status & FE_HAS_LOCK) {
cMutexLock MutexLock(&mutex);
tunerStatus = tsLocked;
locked.Broadcast();
}
}
}
bool hasEvent = GetFrontendEvent(event, 1);
cMutexLock MutexLock(&mutex);
switch (tunerStatus) {
case tsIdle:
break;
case tsSet:
if (hasEvent)
continue;
tunerStatus = SetFrontend() ? tsTuned : tsIdle;
continue;
case tsTuned:
case tsLocked:
case tsCam:
if (hasEvent) {
if (event.status & FE_REINIT) {
tunerStatus = tsSet;
esyslog("ERROR: frontend %d was reinitialized - re-tuning", cardIndex);
}
if (event.status & FE_HAS_LOCK) {
tunerStatus = tsLocked;
locked.Broadcast();
}
continue;
}
}
if (ciHandler) {
if (ciHandler->Process() && useCa) {
if (tunerStatus == tsLocked) {
@ -332,10 +344,9 @@ void cDvbTuner::Action(void)
else if (tunerStatus > tsLocked)
tunerStatus = tsLocked;
}
Unlock();
// in the beginning we loop more often to let the CAM connection start up fast
if (tunerStatus != tsTuned)
newSet.Wait((ciHandler && (time(NULL) - startTime < 20)) ? 100 : 1000);
newSet.TimedWait(mutex, (ciHandler && (time(NULL) - startTime < 20)) ? 100 : 1000);
}
}