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