TimeUtil: fix the generic fallback platform's clocks

This branch is live on the Switch and the BSDs - ppsspp_config.h only maps LINUX to
Android and Linux - and three of its functions didn't do what their callers assume.

time_now_raw() is documented and used as nanoseconds, and from_time_raw() scales it
by 1/nanos, but this built a double of *seconds* and returned it through the uint64_t
return type: the fraction was truncated away and the result was off by a factor of a
billion. Return real monotonic nanoseconds, like every other platform branch.

time_now_unix_utc() just forwarded to time_now_raw(), which is now explicitly a
monotonic clock with no relation to the epoch (and before this, was seconds truncated
to a whole number). Read the wall clock.

Instant took gettimeofday's tv_usec into nsecs_ and stored tv_sec as the start, while
ElapsedNanos() subtracts those from clock_gettime(CLOCK_MONOTONIC) - so it mixed two
different clocks *and* two different units, then applied a microsecond borrow to a
nanosecond difference. Elapsed times were nonsense and could come out negative.
This commit is contained in:
Henrik Rydgård committed 2026-08-31 12:55:14 +02:00
1 parent 5c329415a5
commit 820c6e0134
1 file changed
+20 -15
+20 -15
View File
@@ -238,12 +238,12 @@ double time_now_d() {
}
uint64_t time_now_raw() {
struct timeval tv;
gettimeofday(&tv, nullptr);
if (start == 0) {
start = tv.tv_sec;
}
return (double)tv.tv_sec + (double)tv.tv_usec * (1.0 / micros);
// Nanoseconds, like the other platforms - from_time_raw() scales by 1/nanos. This used to
// build a double of seconds and return it through the uint64_t, so it both lost the fraction
// and was off by a factor of a billion.
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return (uint64_t)tp.tv_sec * 1000000000ULL + tp.tv_nsec;
}
double from_time_raw(uint64_t raw_time) {
@@ -257,7 +257,10 @@ double from_time_raw_relative(uint64_t raw_time) {
void yield() {}
double time_now_unix_utc() {
return time_now_raw();
// Not time_now_raw() - that's a monotonic clock with no relation to the epoch.
struct timeval tv;
gettimeofday(&tv, nullptr);
return (double)tv.tv_sec + (double)tv.tv_usec * (1.0 / micros);
}
double time_to_unix_utc(double t) {
@@ -267,10 +270,12 @@ double time_to_unix_utc(double t) {
}
Instant::Instant() {
struct timeval tv;
gettimeofday(&tv, nullptr);
nativeStart_ = tv.tv_sec;
nsecs_ = tv.tv_usec;
// Has to be the same clock, and the same unit, as ElapsedNanos() below: this took the wall
// clock in microseconds while that one subtracts it from a monotonic clock in nanoseconds.
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
nativeStart_ = ts.tv_sec;
nsecs_ = ts.tv_nsec;
}
int64_t Instant::ElapsedNanos() const {
@@ -278,12 +283,12 @@ int64_t Instant::ElapsedNanos() const {
clock_gettime(CLOCK_MONOTONIC, &ts);
int64_t secs = ts.tv_sec - nativeStart_;
int64_t usecs = ts.tv_nsec - nsecs_;
if (usecs < 0) {
int64_t nsecs = ts.tv_nsec - nsecs_;
if (nsecs < 0) {
secs--;
usecs += 1000000;
nsecs += 1000000000;
}
return secs * 1000000000 + usecs * 1000;
return secs * 1000000000 + nsecs;
}
double Instant::ElapsedSeconds() const {