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 adding play mode pmVideoOnly
for fixing a possible crash with inconsistent SI data for fixing a possible crash with inconsistent SI data
for pointing out a problem with the cChannel copy constructor 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> Torsten Herz <torsten.herz@web.de>
for fixing a possible deadlock when using the "Blue" button in the "Schedules" menu 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 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. 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 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "dvbdevice.h"
@ -81,7 +81,7 @@ private:
eTunerStatus tunerStatus; eTunerStatus tunerStatus;
cMutex mutex; cMutex mutex;
cCondVar locked; cCondVar locked;
cCondWait newSet; cCondVar newSet;
bool GetFrontendEvent(dvb_frontend_event &Event, int TimeoutMs = 0); bool GetFrontendEvent(dvb_frontend_event &Event, int TimeoutMs = 0);
bool SetFrontend(void); bool SetFrontend(void);
virtual void Action(void); virtual void Action(void);
@ -112,7 +112,8 @@ cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType, cCi
cDvbTuner::~cDvbTuner() cDvbTuner::~cDvbTuner()
{ {
tunerStatus = tsIdle; tunerStatus = tsIdle;
newSet.Signal(); newSet.Broadcast();
locked.Broadcast();
Cancel(3); Cancel(3);
} }
@ -123,7 +124,7 @@ bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
void cDvbTuner::Set(const cChannel *Channel, bool Tune, bool UseCa) void cDvbTuner::Set(const cChannel *Channel, bool Tune, bool UseCa)
{ {
Lock(); cMutexLock MutexLock(&mutex);
if (Tune) if (Tune)
tunerStatus = tsSet; tunerStatus = tsSet;
else if (tunerStatus == tsCam) else if (tunerStatus == tsCam)
@ -132,12 +133,15 @@ void cDvbTuner::Set(const cChannel *Channel, bool Tune, bool UseCa)
if (Channel->Ca() && tunerStatus != tsCam) if (Channel->Ca() && tunerStatus != tsCam)
startTime = time(NULL); startTime = time(NULL);
channel = *Channel; channel = *Channel;
Unlock(); newSet.Broadcast();
newSet.Signal();
} }
bool cDvbTuner::Locked(int TimeoutMs) bool cDvbTuner::Locked(int TimeoutMs)
{ {
bool isLocked = (tunerStatus >= tsLocked);
if (isLocked || !TimeoutMs)
return isLocked;
cMutexLock MutexLock(&mutex); cMutexLock MutexLock(&mutex);
if (TimeoutMs && tunerStatus < tsLocked) if (TimeoutMs && tunerStatus < tsLocked)
locked.TimedWait(mutex, TimeoutMs); locked.TimedWait(mutex, TimeoutMs);
@ -292,25 +296,33 @@ void cDvbTuner::Action(void)
{ {
dvb_frontend_event event; dvb_frontend_event event;
while (Running()) { while (Running()) {
Lock(); bool hasEvent = GetFrontendEvent(event, 1);
if (tunerStatus == tsSet) {
while (GetFrontendEvent(event)) cMutexLock MutexLock(&mutex);
; // discard stale events switch (tunerStatus) {
tunerStatus = SetFrontend() ? tsTuned : tsIdle; case tsIdle:
} break;
if (tunerStatus != tsIdle) { case tsSet:
while (GetFrontendEvent(event, 10)) { if (hasEvent)
if (event.status & FE_REINIT) { continue;
tunerStatus = tsSet; tunerStatus = SetFrontend() ? tsTuned : tsIdle;
esyslog("ERROR: frontend %d was reinitialized - re-tuning", cardIndex); continue;
} case tsTuned:
if (event.status & FE_HAS_LOCK) { case tsLocked:
cMutexLock MutexLock(&mutex); case tsCam:
tunerStatus = tsLocked; if (hasEvent) {
locked.Broadcast(); 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) {
if (ciHandler->Process() && useCa) { if (ciHandler->Process() && useCa) {
if (tunerStatus == tsLocked) { if (tunerStatus == tsLocked) {
@ -332,10 +344,9 @@ void cDvbTuner::Action(void)
else if (tunerStatus > tsLocked) else if (tunerStatus > tsLocked)
tunerStatus = tsLocked; tunerStatus = tsLocked;
} }
Unlock();
// in the beginning we loop more often to let the CAM connection start up fast // in the beginning we loop more often to let the CAM connection start up fast
if (tunerStatus != tsTuned) if (tunerStatus != tsTuned)
newSet.Wait((ciHandler && (time(NULL) - startTime < 20)) ? 100 : 1000); newSet.TimedWait(mutex, (ciHandler && (time(NULL) - startTime < 20)) ? 100 : 1000);
} }
} }