Fixes race condition in EnsureMonotonic on 32-bit builds, which was causing unreliable timer behavior, fixes #1729
This was SVN commit r12927.
This commit is contained in:
parent
ad3fbc543d
commit
e91a918164
@ -34,6 +34,7 @@
|
|||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
|
||||||
#include "lib/module_init.h"
|
#include "lib/module_init.h"
|
||||||
|
#include "lib/posix/posix_pthread.h"
|
||||||
#include "lib/posix/posix_time.h"
|
#include "lib/posix/posix_time.h"
|
||||||
# include "lib/sysdep/cpu.h"
|
# include "lib/sysdep/cpu.h"
|
||||||
#if OS_WIN
|
#if OS_WIN
|
||||||
@ -81,33 +82,16 @@ void timer_LatchStartTime()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static pthread_mutex_t ensure_monotonic_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
// NB: does not guarantee strict monotonicity - callers must avoid
|
// NB: does not guarantee strict monotonicity - callers must avoid
|
||||||
// dividing by the difference of two equal times.
|
// dividing by the difference of two equal times.
|
||||||
// (this avoids having to update maxRepresentation when
|
|
||||||
// updating newTime to the (more recent) oldTime)
|
|
||||||
static void EnsureMonotonic(double& newTime)
|
static void EnsureMonotonic(double& newTime)
|
||||||
{
|
{
|
||||||
i64 newRepresentation;
|
pthread_mutex_lock(&ensure_monotonic_mutex);
|
||||||
memcpy(&newRepresentation, &newTime, sizeof(newRepresentation));
|
static double maxTime;
|
||||||
|
maxTime = std::max(maxTime, newTime);
|
||||||
// representation of the latest time reported by any thread
|
newTime = maxTime;
|
||||||
static volatile i64 maxRepresentation; // initially 0.0
|
pthread_mutex_unlock(&ensure_monotonic_mutex);
|
||||||
|
|
||||||
retry:
|
|
||||||
const i64 oldRepresentation = maxRepresentation; // latch
|
|
||||||
double oldTime;
|
|
||||||
memcpy(&oldTime, &oldRepresentation, sizeof(oldTime));
|
|
||||||
// a previous or concurrent call got a more recent time -
|
|
||||||
// return that and avoid updating maxRepresentation.
|
|
||||||
if(newTime < oldTime)
|
|
||||||
{
|
|
||||||
newTime = oldTime;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!cpu_CAS64(&maxRepresentation, oldRepresentation, newRepresentation))
|
|
||||||
goto retry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -142,11 +142,11 @@ static void* RunEngine(void* data)
|
|||||||
|
|
||||||
// Calculate frame length
|
// Calculate frame length
|
||||||
{
|
{
|
||||||
double time = timer_Time();
|
const double time = timer_Time();
|
||||||
static double last_time = time;
|
static double last_time = time;
|
||||||
// TODO: why is this sometimes negative, if timer_Time ensures monotonic results?
|
const double realFrameLength = time-last_time;
|
||||||
float realFrameLength = std::max(0.0f, (float)(time-last_time));
|
|
||||||
last_time = time;
|
last_time = time;
|
||||||
|
ENSURE(realFrameLength >= 0.0);
|
||||||
// TODO: filter out big jumps, e.g. when having done a lot of slow
|
// TODO: filter out big jumps, e.g. when having done a lot of slow
|
||||||
// processing in the last frame
|
// processing in the last frame
|
||||||
state.realFrameLength = realFrameLength;
|
state.realFrameLength = realFrameLength;
|
||||||
|
Loading…
Reference in New Issue
Block a user