From 1786d9973558c0538ecb3f32cd695613c789c658 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Tue, 19 Dec 2006 08:00:45 +0000 Subject: [PATCH] GetPositionSeconds(&tm) returns the clock time timestamp associated with the returned sound time. This is tricky: we may be interrupted, causing timing error. We tried working around this by trying to hint the scheduler that we're in a period where we don't want to be interrupted, even though we're in a thread that's not normally high priority, by boosting the priority temporarily. This worked in Windows, but not in general; it's too far out of the expectations of schedulers and generally just made things worse. Let's look at this like an interruption-based lockless algorithm: try it, see if it succeeded, and if it failed, try again. Retrying even once should be a rare exception, but failsafe anyway, so a bug in a sound driver won't hang. --- stepmania/src/RageSound.cpp | 39 ++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/stepmania/src/RageSound.cpp b/stepmania/src/RageSound.cpp index de2d5a5283..51e9e7d66a 100644 --- a/stepmania/src/RageSound.cpp +++ b/stepmania/src/RageSound.cpp @@ -26,7 +26,6 @@ #include "RageUtil.h" #include "RageLog.h" #include "PrefsManager.h" -#include "arch/ArchHooks/ArchHooks.h" #include "RageSoundUtil.h" #include "RageSoundReader_Pan.h" @@ -656,18 +655,40 @@ float RageSound::GetPositionSeconds( bool *bApproximate, RageTimer *pTimestamp ) { LockMut( m_Mutex ); - if( pTimestamp ) + if( pTimestamp == NULL ) + { + const int64_t iPositionFrames = GetPositionSecondsInternal( bApproximate ); + return iPositionFrames / float(samplerate()); + } + + /* + * We may have unpredictable scheduling delays between updating the timestamp + * and reading the sound position. If we're preempted while doing this and + * it may have caused the timestamp to not match the returned time, retry. + * + * As a failsafe, only allow a few attempts. If this has to try more than + * a few times, then probably we have thread contention that's causing more + * severe performance problems, anyway. + */ + int iTries = 3; + int64_t iPositionFrames; + do { - HOOKS->EnterTimeCriticalSection(); pTimestamp->Touch(); + iPositionFrames = GetPositionSecondsInternal( bApproximate ); + } while( --iTries && pTimestamp->Ago() > 0.002f ); + + if( iTries == 0 ) + { + static bool bLogged = false; + if( !bLogged ) + { + bLogged = true; + LOG->Warn( "RageSound::GetPositionSeconds: too many tries" ); + } } - const int64_t iPositionFrames = GetPositionSecondsInternal( bApproximate ); - const float fPosition = iPositionFrames / float(samplerate()); - if( pTimestamp ) - HOOKS->ExitTimeCriticalSection(); - - return fPosition; + return iPositionFrames / float(samplerate()); }