Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] Re: [PATCH] NPTL



Ludwig Nussel wrote:
> Starting from Werners patch for signal handling I spent the whole
> day debugging the cutmarks jumping problems that showed up when
> using NPTL. The culprit for the hangs was a usleep(1) inside a mutex
> protected section. With the attached patches jumping between
> cutmarks, starting/pausing/stopping replays and properly quitting
> vdr now work fine for me. Even if it works it for sure doesn't fix
> all problems, I assume there are way more mutex locks necessary.
> 
> vdr-1.2.6-fpic.patch - add -fPIC and source Make.config in subdirectories
> vdr-1.2.6-werner.diff - the patch from Werner adapted for 1.2.6
> vdr-1.2.6-13threads.diff - thread.[ch] from vdr-1.3.9
> vdr-1.2.6-threadcancelsegv.diff - fix a segfault
> vdr-1.2.6-fixthreads.diff - the actual NPTL fixes

An updated version of that last patch is attached. It removes the
locking around the dvr fd I introduced before. Makes recording work
again.

cu
Ludwig

-- 
(o_  Ludwig.Nussel@gmx.de
//\  PGP Key ID: FF8135CE
V_/_ ICQ:        52166811
Index: vdr-1.2.6/dvbdevice.c
===================================================================
--- vdr-1.2.6.orig/dvbdevice.c	2004-06-11 15:16:29.998955336 +0200
+++ vdr-1.2.6/dvbdevice.c	2004-06-11 23:39:18.438857073 +0200
@@ -540,6 +540,7 @@
 
 cDvbDevice::~cDvbDevice()
 {
+  LOCK_THREAD;
   delete spuDecoder;
   delete siProcessor;
   delete scanner;
@@ -607,6 +608,7 @@
 
 cSpuDecoder *cDvbDevice::GetSpuDecoder(void)
 {
+  LOCK_THREAD;
   if (!spuDecoder && IsPrimaryDevice())
      spuDecoder = new cDvbSpuDecoder();
   return spuDecoder;
@@ -614,6 +616,7 @@
 
 bool cDvbDevice::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY)
 {
+  LOCK_THREAD;
   if (devVideoIndex < 0)
      return false;
   char buffer[PATH_MAX];
@@ -713,12 +716,14 @@
 
 void cDvbDevice::SetVideoFormat(bool VideoFormat16_9)
 {
+  LOCK_THREAD;
   if (HasDecoder())
      CHECK(ioctl(fd_video, VIDEO_SET_FORMAT, VideoFormat16_9 ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3));
 }
 
 eVideoSystem cDvbDevice::GetVideoSystem(void)
 {
+  LOCK_THREAD;
   eVideoSystem VideoSytem = vsPAL;
   video_size_t vs;
   if (ioctl(fd_video, VIDEO_GET_SIZE, &vs) == 0) {
@@ -735,6 +740,7 @@
 
 bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
 {
+  LOCK_THREAD;
   if (Handle->pid) {
      dmx_pes_filter_params pesFilterParams;
      memset(&pesFilterParams, 0, sizeof(pesFilterParams));
@@ -775,6 +781,7 @@
 
 void cDvbDevice::TurnOffLiveMode(void)
 {
+  LOCK_THREAD;
   // Avoid noise while switching:
 
   CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, true));
@@ -838,6 +845,7 @@
 
 bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
 {
+  LOCK_THREAD;
   bool IsEncrypted = Channel->Ca() > CACONFBASE && !ciHandler; // only LL-firmware can do non-live CA channels
 
   bool DoTune = !dvbTuner->IsTunedTo(Channel);
@@ -915,6 +923,7 @@
 
 void cDvbDevice::SetVolumeDevice(int Volume)
 {
+  LOCK_THREAD;
   if (HasDecoder()) {
      audio_mixer_t am;
      am.volume_left = am.volume_right = Volume;
@@ -964,6 +973,7 @@
 
 bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
 {
+  LOCK_THREAD;
   if (PlayMode != pmExtern_THIS_SHOULD_BE_AVOIDED && fd_video < 0 && fd_audio < 0) {
      // reopen the devices
      fd_video = DvbOpen(DEV_DVB_VIDEO,  CardIndex(), O_RDWR | O_NONBLOCK);
@@ -1028,6 +1038,7 @@
 
 int64_t cDvbDevice::GetSTC(void)
 {
+  LOCK_THREAD;
   if (fd_stc >= 0) {
      struct dmx_stc stc;
      stc.num = 0;
@@ -1042,12 +1053,14 @@
 
 void cDvbDevice::TrickSpeed(int Speed)
 {
+  LOCK_THREAD;
   if (fd_video >= 0)
      CHECK(ioctl(fd_video, VIDEO_SLOWMOTION, Speed));
 }
 
 void cDvbDevice::Clear(void)
 {
+  LOCK_THREAD;
   if (fd_video >= 0)
      CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER));
   if (fd_audio >= 0)
@@ -1057,6 +1070,7 @@
 
 void cDvbDevice::Play(void)
 {
+  LOCK_THREAD;
   if (playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) {
      if (fd_audio >= 0)
         CHECK(ioctl(fd_audio, AUDIO_CONTINUE));
@@ -1072,6 +1086,7 @@
 
 void cDvbDevice::Freeze(void)
 {
+  LOCK_THREAD;
   if (playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) {
      if (fd_audio >= 0)
         CHECK(ioctl(fd_audio, AUDIO_PAUSE));
@@ -1087,6 +1102,7 @@
 
 void cDvbDevice::Mute(void)
 {
+  LOCK_THREAD;
   if (fd_audio >= 0) {
      CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false));
      CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, true));
@@ -1096,6 +1112,7 @@
 
 void cDvbDevice::StillPicture(const uchar *Data, int Length)
 {
+  LOCK_THREAD;
 /* Using the VIDEO_STILLPICTURE ioctl call would be the
    correct way to display a still frame, but unfortunately this
    doesn't work with frames from VDR. So let's do pretty much the
@@ -1200,6 +1217,7 @@
 
 int cDvbDevice::PlayVideo(const uchar *Data, int Length)
 {
+  LOCK_THREAD;
   int fd = (playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) ? fd_audio : fd_video;
   if (fd >= 0)
      return write(fd, Data, Length);
@@ -1212,6 +1230,8 @@
   cDevice::PlayAudio(Data, Length);
 }
 
+// no need to lock the following functions, they only operate on fd_dvr and are
+// called from the Action method in cDvbDevice.
 bool cDvbDevice::OpenDvr(void)
 {
   CloseDvr();
Index: vdr-1.2.6/dvbplayer.c
===================================================================
--- vdr-1.2.6.orig/dvbplayer.c	2004-06-11 15:16:30.000954908 +0200
+++ vdr-1.2.6/dvbplayer.c	2004-06-11 15:31:14.936651960 +0200
@@ -422,14 +422,15 @@
   running = true;
   while (running && (NextFile() || readIndex >= 0 || ringBuffer->Available())) {
         cPoller Poller;
-        if (DevicePoll(Poller, 100)) {
-
-           LOCK_THREAD;
+        if (DevicePoll(Poller, -1)) {
 
            // Read the next frame from the file:
 
            if (!readFrame && (replayFile >= 0 || readIndex >= 0)) {
               if (playMode != pmStill) {
+
+		 LOCK_THREAD;
+
                  if (!nonBlockingFileReader->Reading()) {
                     if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) {
                        uchar FileNumber;
@@ -490,12 +491,14 @@
                     break;
                     }
                  }
-              else//XXX
-                 usleep(1); // this keeps the CPU load low
-              }
+              else
+		pause(); // block until WakeUp()
+	      }
 
            // Store the frame in the buffer:
 
+	   LOCK_THREAD;
+
            if (readFrame) {
               if (ringBuffer->Put(readFrame))
                  readFrame = NULL;
@@ -576,6 +579,7 @@
      DevicePlay();
      playMode = pmPlay;
      playDir = pdForward;
+     WakeUp();
     }
 }
 
Index: vdr-1.2.6/thread.c
===================================================================
--- vdr-1.2.6.orig/thread.c	2004-06-11 15:16:29.997955550 +0200
+++ vdr-1.2.6/thread.c	2004-06-11 15:31:14.939651319 +0200
@@ -155,22 +155,21 @@
 
 void cThread::SignalHandler(int signum)
 {
+  dsyslog("%s:%d (%s) Tid: %ld Sig: %d\n",__FILE__, __LINE__, __FUNCTION__, pthread_self(), signum);
   signal(signum, SignalHandler);
 }
 
 void *cThread::StartThread(cThread *Thread)
 {
-  (void)pthread_sigmask(SIG_BLOCK, &TheSigset, (sigset_t*)0);
   if (!signalHandlerInstalled) {
-    sigset_t sigset;
-    sigemptyset(&sigset);
-    sigaddset(&sigset, SIGIO);
-
     signal(SIGIO, SignalHandler);
-    (void)pthread_sigmask(SIG_UNBLOCK, &sigset, (sigset_t*)0);
-
     signalHandlerInstalled = true;
   }
+  sigset_t sigset;
+  sigemptyset(&sigset);
+  sigaddset(&sigset, SIGIO);
+  (void)pthread_sigmask(SIG_UNBLOCK, &sigset, (sigset_t*)0);
+
   Thread->childTid = pthread_self();
   if (Thread->description)
      dsyslog("%s thread started (pid=%d, tid=%ld)", Thread->description, getpid(), Thread->childTid);
@@ -222,6 +221,7 @@
 {
   if(!running) return;
   running = false;
+  WakeUp();
   if (WaitSeconds > 0) {
      for (time_t t0 = time(NULL) + WaitSeconds; time(NULL) < t0; ) {
          if (!Active())
@@ -235,7 +235,8 @@
 
 void cThread::WakeUp(void)
 {
-  pthread_kill(parentTid, SIGIO); // makes any waiting 'select()' call return immediately
+  if(childTid)
+    pthread_kill(childTid, SIGIO); // makes any waiting 'select()' call return immediately
 }
 
 bool cThread::EmergencyExit(bool Request)

Attachment: pgp00014.pgp
Description: PGP signature


Home | Main Index | Thread Index