mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
The new class cIoThrottle is used to allow I/O intense threads to temporarily suspend their activities in case buffers run full
This commit is contained in:
parent
e898a28258
commit
72c03260d7
@ -2891,6 +2891,8 @@ Torsten Lang <info@torstenlang.de>
|
|||||||
if the editing point merges two seamlessly fitting parts of the same stream
|
if the editing point merges two seamlessly fitting parts of the same stream
|
||||||
for reporting a sluggish response when manipulating editing marks while a cutting
|
for reporting a sluggish response when manipulating editing marks while a cutting
|
||||||
thread is running
|
thread is running
|
||||||
|
for suggesting to allow I/O intense threads to temporarily suspend their activities
|
||||||
|
in case buffers run full
|
||||||
|
|
||||||
Christian Ruppert <idl0r@gentoo.org>
|
Christian Ruppert <idl0r@gentoo.org>
|
||||||
for some improvements to the Makefiles
|
for some improvements to the Makefiles
|
||||||
|
7
HISTORY
7
HISTORY
@ -7235,7 +7235,7 @@ Video Disk Recorder Revision History
|
|||||||
function in order to make use of this new feature. See, for instance, the function
|
function in order to make use of this new feature. See, for instance, the function
|
||||||
cSkinClassicDisplayMenu::SetButtons() in skinclassic.c for details.
|
cSkinClassicDisplayMenu::SetButtons() in skinclassic.c for details.
|
||||||
|
|
||||||
2012-09-19: Version 1.7.31
|
2012-09-22: Version 1.7.31
|
||||||
|
|
||||||
- If regenerating an index file fails and no data is written to the file, VDR now
|
- If regenerating an index file fails and no data is written to the file, VDR now
|
||||||
reports this error and removes the empty index file.
|
reports this error and removes the empty index file.
|
||||||
@ -7251,3 +7251,8 @@ Video Disk Recorder Revision History
|
|||||||
(suggested by Jens Vogel).
|
(suggested by Jens Vogel).
|
||||||
- Fixed a leftover frame counter in the LCARS skin's replay display after jumping to
|
- Fixed a leftover frame counter in the LCARS skin's replay display after jumping to
|
||||||
an editing mark and resuming replay.
|
an editing mark and resuming replay.
|
||||||
|
- The new class cIoThrottle is used to allow I/O intense threads to temporarily
|
||||||
|
suspend their activities in case buffers run full (suggested by Torsten Lang).
|
||||||
|
Currently the cutter thread is suspended if the TS or Recorder buffer use more
|
||||||
|
than 50% of their capacity. Plugin authors may want to participate in this
|
||||||
|
mechanism if they use intense background I/O.
|
||||||
|
18
cutter.c
18
cutter.c
@ -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: cutter.c 2.13 2012/06/10 14:33:36 kls Exp $
|
* $Id: cutter.c 2.14 2012/09/20 09:12:47 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cutter.h"
|
#include "cutter.h"
|
||||||
@ -88,12 +88,28 @@ void cCuttingThread::Action(void)
|
|||||||
bool CheckForSeamlessStream = false;
|
bool CheckForSeamlessStream = false;
|
||||||
bool LastMark = false;
|
bool LastMark = false;
|
||||||
bool cutIn = true;
|
bool cutIn = true;
|
||||||
|
bool suspensionLogged = false;
|
||||||
while (Running()) {
|
while (Running()) {
|
||||||
uint16_t FileNumber;
|
uint16_t FileNumber;
|
||||||
off_t FileOffset;
|
off_t FileOffset;
|
||||||
int Length;
|
int Length;
|
||||||
bool Independent;
|
bool Independent;
|
||||||
|
|
||||||
|
// Suspend cutting if we have severe throughput problems:
|
||||||
|
|
||||||
|
if (cIoThrottle::Engaged()) {
|
||||||
|
if (!suspensionLogged) {
|
||||||
|
dsyslog("suspending cutter thread");
|
||||||
|
suspensionLogged = true;
|
||||||
|
}
|
||||||
|
cCondWait::SleepMs(100);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (suspensionLogged) {
|
||||||
|
dsyslog("resuming cutter thread");
|
||||||
|
suspensionLogged = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure there is enough disk space:
|
// Make sure there is enough disk space:
|
||||||
|
|
||||||
AssertFreeDiskSpace(-1);
|
AssertFreeDiskSpace(-1);
|
||||||
|
3
device.c
3
device.c
@ -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: device.c 2.67 2012/09/02 09:26:36 kls Exp $
|
* $Id: device.c 2.68 2012/09/20 09:32:26 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
@ -1721,6 +1721,7 @@ cTSBuffer::cTSBuffer(int File, int Size, int CardIndex)
|
|||||||
delivered = false;
|
delivered = false;
|
||||||
ringBuffer = new cRingBufferLinear(Size, TS_SIZE, true, "TS");
|
ringBuffer = new cRingBufferLinear(Size, TS_SIZE, true, "TS");
|
||||||
ringBuffer->SetTimeouts(100, 100);
|
ringBuffer->SetTimeouts(100, 100);
|
||||||
|
ringBuffer->SetIoThrottle();
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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: recorder.c 2.15 2011/09/04 09:26:44 kls Exp $
|
* $Id: recorder.c 2.16 2012/09/22 11:52:33 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "recorder.h"
|
#include "recorder.h"
|
||||||
@ -33,6 +33,7 @@ cRecorder::cRecorder(const char *FileName, const cChannel *Channel, int Priority
|
|||||||
|
|
||||||
ringBuffer = new cRingBufferLinear(RECORDERBUFSIZE, MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE, true, "Recorder");
|
ringBuffer = new cRingBufferLinear(RECORDERBUFSIZE, MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE, true, "Recorder");
|
||||||
ringBuffer->SetTimeouts(0, 100);
|
ringBuffer->SetTimeouts(0, 100);
|
||||||
|
ringBuffer->SetIoThrottle();
|
||||||
|
|
||||||
int Pid = Channel->Vpid();
|
int Pid = Channel->Vpid();
|
||||||
int Type = Channel->Vtype();
|
int Type = Channel->Vtype();
|
||||||
|
18
ringbuffer.c
18
ringbuffer.c
@ -7,7 +7,7 @@
|
|||||||
* Parts of this file were inspired by the 'ringbuffy.c' from the
|
* Parts of this file were inspired by the 'ringbuffy.c' from the
|
||||||
* LinuxDVB driver (see linuxtv.org).
|
* LinuxDVB driver (see linuxtv.org).
|
||||||
*
|
*
|
||||||
* $Id: ringbuffer.c 2.4 2012/09/17 08:23:43 kls Exp $
|
* $Id: ringbuffer.c 2.5 2012/09/22 11:26:49 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ringbuffer.h"
|
#include "ringbuffer.h"
|
||||||
@ -20,6 +20,8 @@
|
|||||||
#define OVERFLOWREPORTDELTA 5 // seconds between reports
|
#define OVERFLOWREPORTDELTA 5 // seconds between reports
|
||||||
#define PERCENTAGEDELTA 10
|
#define PERCENTAGEDELTA 10
|
||||||
#define PERCENTAGETHRESHOLD 70
|
#define PERCENTAGETHRESHOLD 70
|
||||||
|
#define IOTHROTTLELOW 20
|
||||||
|
#define IOTHROTTLEHIGH 50
|
||||||
|
|
||||||
cRingBuffer::cRingBuffer(int Size, bool Statistics)
|
cRingBuffer::cRingBuffer(int Size, bool Statistics)
|
||||||
{
|
{
|
||||||
@ -31,10 +33,12 @@ cRingBuffer::cRingBuffer(int Size, bool Statistics)
|
|||||||
putTimeout = getTimeout = 0;
|
putTimeout = getTimeout = 0;
|
||||||
lastOverflowReport = 0;
|
lastOverflowReport = 0;
|
||||||
overflowCount = overflowBytes = 0;
|
overflowCount = overflowBytes = 0;
|
||||||
|
ioThrottle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cRingBuffer::~cRingBuffer()
|
cRingBuffer::~cRingBuffer()
|
||||||
{
|
{
|
||||||
|
delete ioThrottle;
|
||||||
if (statistics)
|
if (statistics)
|
||||||
dsyslog("buffer stats: %d (%d%%) used", maxFill, maxFill * 100 / (size - 1));
|
dsyslog("buffer stats: %d (%d%%) used", maxFill, maxFill * 100 / (size - 1));
|
||||||
}
|
}
|
||||||
@ -50,6 +54,12 @@ void cRingBuffer::UpdatePercentage(int Fill)
|
|||||||
lastPercent = percent;
|
lastPercent = percent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ioThrottle) {
|
||||||
|
if (percent >= IOTHROTTLEHIGH)
|
||||||
|
ioThrottle->Activate();
|
||||||
|
else if (percent < IOTHROTTLELOW)
|
||||||
|
ioThrottle->Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cRingBuffer::WaitForPut(void)
|
void cRingBuffer::WaitForPut(void)
|
||||||
@ -82,6 +92,12 @@ void cRingBuffer::SetTimeouts(int PutTimeout, int GetTimeout)
|
|||||||
getTimeout = GetTimeout;
|
getTimeout = GetTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cRingBuffer::SetIoThrottle(void)
|
||||||
|
{
|
||||||
|
if (!ioThrottle)
|
||||||
|
ioThrottle = new cIoThrottle;
|
||||||
|
}
|
||||||
|
|
||||||
void cRingBuffer::ReportOverflow(int Bytes)
|
void cRingBuffer::ReportOverflow(int Bytes)
|
||||||
{
|
{
|
||||||
overflowCount++;
|
overflowCount++;
|
||||||
|
@ -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: ringbuffer.h 2.3 2011/12/04 13:38:17 kls Exp $
|
* $Id: ringbuffer.h 2.4 2012/09/20 09:29:32 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __RINGBUFFER_H
|
#ifndef __RINGBUFFER_H
|
||||||
@ -22,6 +22,7 @@ private:
|
|||||||
time_t lastOverflowReport;
|
time_t lastOverflowReport;
|
||||||
int overflowCount;
|
int overflowCount;
|
||||||
int overflowBytes;
|
int overflowBytes;
|
||||||
|
cIoThrottle *ioThrottle;
|
||||||
protected:
|
protected:
|
||||||
tThreadId getThreadTid;
|
tThreadId getThreadTid;
|
||||||
int maxFill;//XXX
|
int maxFill;//XXX
|
||||||
@ -40,6 +41,7 @@ public:
|
|||||||
cRingBuffer(int Size, bool Statistics = false);
|
cRingBuffer(int Size, bool Statistics = false);
|
||||||
virtual ~cRingBuffer();
|
virtual ~cRingBuffer();
|
||||||
void SetTimeouts(int PutTimeout, int GetTimeout);
|
void SetTimeouts(int PutTimeout, int GetTimeout);
|
||||||
|
void SetIoThrottle(void);
|
||||||
void ReportOverflow(int Bytes);
|
void ReportOverflow(int Bytes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
44
thread.c
44
thread.c
@ -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: thread.c 2.4 2012/05/08 11:15:57 kls Exp $
|
* $Id: thread.c 2.5 2012/09/20 09:05:50 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
@ -398,6 +398,48 @@ bool cThreadLock::Lock(cThread *Thread)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- cIoThrottle -----------------------------------------------------------
|
||||||
|
|
||||||
|
cMutex cIoThrottle::mutex;
|
||||||
|
int cIoThrottle::count = 0;
|
||||||
|
|
||||||
|
cIoThrottle::cIoThrottle(void)
|
||||||
|
{
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cIoThrottle::~cIoThrottle()
|
||||||
|
{
|
||||||
|
Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cIoThrottle::Activate(void)
|
||||||
|
{
|
||||||
|
if (!active) {
|
||||||
|
mutex.Lock();
|
||||||
|
count++;
|
||||||
|
active = true;
|
||||||
|
dsyslog("i/o throttle activated, count = %d (tid=%d)", count, cThread::ThreadId());
|
||||||
|
mutex.Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cIoThrottle::Release(void)
|
||||||
|
{
|
||||||
|
if (active) {
|
||||||
|
mutex.Lock();
|
||||||
|
count--;
|
||||||
|
active = false;
|
||||||
|
dsyslog("i/o throttle released, count = %d (tid=%d)", count, cThread::ThreadId());
|
||||||
|
mutex.Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cIoThrottle::Engaged(void)
|
||||||
|
{
|
||||||
|
return count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
// --- cPipe -----------------------------------------------------------------
|
// --- cPipe -----------------------------------------------------------------
|
||||||
|
|
||||||
// cPipe::Open() and cPipe::Close() are based on code originally received from
|
// cPipe::Open() and cPipe::Close() are based on code originally received from
|
||||||
|
25
thread.h
25
thread.h
@ -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: thread.h 2.1 2009/04/13 13:50:39 kls Exp $
|
* $Id: thread.h 2.2 2012/09/20 08:46:27 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __THREAD_H
|
#ifndef __THREAD_H
|
||||||
@ -157,6 +157,29 @@ public:
|
|||||||
|
|
||||||
#define LOCK_THREAD cThreadLock ThreadLock(this)
|
#define LOCK_THREAD cThreadLock ThreadLock(this)
|
||||||
|
|
||||||
|
class cIoThrottle {
|
||||||
|
private:
|
||||||
|
static cMutex mutex;
|
||||||
|
static int count;
|
||||||
|
bool active;
|
||||||
|
public:
|
||||||
|
cIoThrottle(void);
|
||||||
|
~cIoThrottle();
|
||||||
|
void Activate(void);
|
||||||
|
///< Activates the global I/O throttling mechanism.
|
||||||
|
///< This function may be called any number of times, but only
|
||||||
|
///< the first call after an inactive state will have an effect.
|
||||||
|
void Release(void);
|
||||||
|
///< Releases the global I/O throttling mechanism.
|
||||||
|
///< This function may be called any number of times, but only
|
||||||
|
///< the first call after an active state will have an effect.
|
||||||
|
bool Active(void) { return active; }
|
||||||
|
///< Returns true if this I/O throttling object is currently active.
|
||||||
|
static bool Engaged(void);
|
||||||
|
///< Returns true if any I/O throttling object is currently active.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// cPipe implements a pipe that closes all unnecessary file descriptors in
|
// cPipe implements a pipe that closes all unnecessary file descriptors in
|
||||||
// the child process.
|
// the child process.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user