From f3fe1e9a136cb82f0683a41d6889acaf8cacff50 Mon Sep 17 00:00:00 2001 From: Rolf Ahrenberg Date: Mon, 13 Nov 2017 22:12:10 +0200 Subject: [PATCH] Serialize channel switching to prevent device allocation failures. --- device.c | 16 +++++++++++++++- device.h | 8 +++++--- deviceif.h | 1 + tuner.c | 1 + 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/device.c b/device.c index ee8c1c5..ddd5b55 100644 --- a/device.c +++ b/device.c @@ -15,6 +15,8 @@ static cSatipDevice * SatipDevicesS[SATIP_MAX_DEVICES] = { NULL }; +cMutex cSatipDevice::mutexS = cMutex(); + cSatipDevice::cSatipDevice(unsigned int indexP) : deviceIndexM(indexP), isPacketDeliveredM(false), @@ -22,7 +24,7 @@ cSatipDevice::cSatipDevice(unsigned int indexP) deviceNameM(*cString::sprintf("%s %d", *DeviceType(), deviceIndexM)), channelM(), createdM(0), - mutexM() + tunedM() { unsigned int bufsize = (unsigned int)SATIP_BUFFER_SIZE; bufsize -= (bufsize % TS_SIZE); @@ -42,6 +44,8 @@ cSatipDevice::cSatipDevice(unsigned int indexP) cSatipDevice::~cSatipDevice() { debug1("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM); + // Release immediately any pending conditional wait + tunedM.Broadcast(); // Stop section handler StopSectionHandler(); DELETE_POINTER(pSectionFilterHandlerM); @@ -339,6 +343,7 @@ bool cSatipDevice::MaySwitchTransponder(const cChannel *channelP) const bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP) { + cMutexLock MutexLock(&mutexS); // Global lock to prevent any simultaneous zapping debug9("%s (%d, %d) [device %u]", __PRETTY_FUNCTION__, channelP ? channelP->Number() : -1, liveViewP, deviceIndexM); if (channelP) { cDvbTransponderParameters dtp(channelP->Parameters()); @@ -356,6 +361,8 @@ bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP) if (pTunerM && pTunerM->SetSource(server, channelP->Transponder(), *params, deviceIndexM)) { channelM = *channelP; deviceNameM = cString::sprintf("%s %d %s", *DeviceType(), deviceIndexM, *cSatipDiscover::GetInstance()->GetServerString(server)); + // Wait for actual channel tuning to prevent simultaneous frontend allocation failures + tunedM.TimedWait(mutexS, eTuningTimeoutMs); return true; } } @@ -367,6 +374,13 @@ bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP) return false; } +void cSatipDevice::SetChannelTuned(void) +{ + debug9("%s () [device %u]", __PRETTY_FUNCTION__, deviceIndexM); + // Release immediately any pending conditional wait + tunedM.Broadcast(); +} + bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP) { debug12("%s (%d, %d, %d) [device %u]", __PRETTY_FUNCTION__, handleP ? handleP->pid : -1, typeP, onP, deviceIndexM); diff --git a/device.h b/device.h index 983e24d..334ceef 100644 --- a/device.h +++ b/device.h @@ -18,7 +18,7 @@ class cSatipDevice : public cDevice, public cSatipPidStatistics, public cSatipBufferStatistics, public cSatipDeviceIf { // static ones public: - static unsigned int deviceCount; + static cMutex mutexS; static bool Initialize(unsigned int DeviceCount); static void Shutdown(void); static unsigned int Count(void); @@ -28,7 +28,8 @@ public: // private parts private: enum { - eReadyTimeoutMs = 2000 // in milliseconds + eReadyTimeoutMs = 2000, // in milliseconds + eTuningTimeoutMs = 1000 // in milliseconds }; unsigned int deviceIndexM; bool isPacketDeliveredM; @@ -39,7 +40,7 @@ private: cSatipTuner *pTunerM; cSatipSectionFilterHandler *pSectionFilterHandlerM; cTimeMs createdM; - cMutex mutexM; + cCondVar tunedM; // constructor & destructor public: @@ -107,6 +108,7 @@ public: // for internal device interface public: virtual void WriteData(u_char *bufferP, int lengthP); + virtual void SetChannelTuned(void); virtual int GetId(void); virtual int GetPmtPid(void); virtual int GetCISlot(void); diff --git a/deviceif.h b/deviceif.h index 9fe1636..e0a418f 100644 --- a/deviceif.h +++ b/deviceif.h @@ -13,6 +13,7 @@ public: cSatipDeviceIf() {} virtual ~cSatipDeviceIf() {} virtual void WriteData(u_char *bufferP, int lengthP) = 0; + virtual void SetChannelTuned(void) = 0; virtual int GetId(void) = 0; virtual int GetPmtPid(void) = 0; virtual int GetCISlot(void) = 0; diff --git a/tuner.c b/tuner.c index 9eb1e06..df8aee9 100644 --- a/tuner.c +++ b/tuner.c @@ -126,6 +126,7 @@ void cSatipTuner::Action(void) break; case tsTuned: debug4("%s: tsTuned [device %d]", __PRETTY_FUNCTION__, deviceIdM); + deviceM->SetChannelTuned(); reConnectM.Set(eConnectTimeoutMs); idleCheck.Set(eIdleCheckTimeoutMs); lastIdleStatus = false;