diff options
Diffstat (limited to 'libs/utils/SystemClock.cpp')
-rw-r--r-- | libs/utils/SystemClock.cpp | 92 |
1 files changed, 80 insertions, 12 deletions
diff --git a/libs/utils/SystemClock.cpp b/libs/utils/SystemClock.cpp index 8b8ac10..ec2d82e 100644 --- a/libs/utils/SystemClock.cpp +++ b/libs/utils/SystemClock.cpp @@ -106,7 +106,74 @@ int64_t uptimeMillis() */ int64_t elapsedRealtime() { + return nanoseconds_to_milliseconds(elapsedRealtimeNano()); +} + +#define METHOD_CLOCK_GETTIME 0 +#define METHOD_IOCTL 1 +#define METHOD_SYSTEMTIME 2 + +static const char *gettime_method_names[] = { + "clock_gettime", + "ioctl", + "systemTime", +}; + +static inline void checkTimeStamps(int64_t timestamp, + int64_t volatile *prevTimestampPtr, + int volatile *prevMethodPtr, + int curMethod) +{ + /* + * Disable the check for SDK since the prebuilt toolchain doesn't contain + * gettid, and int64_t is different on the ARM platform + * (ie long vs long long). + */ +#ifdef ARCH_ARM + int64_t prevTimestamp = *prevTimestampPtr; + int prevMethod = *prevMethodPtr; + + if (timestamp < prevTimestamp) { + ALOGW("time going backwards: prev %lld(%s) vs now %lld(%s), tid=%d", + prevTimestamp, gettime_method_names[prevMethod], + timestamp, gettime_method_names[curMethod], + gettid()); + } + // NOTE - not atomic and may generate spurious warnings if the 64-bit + // write is interrupted or not observed as a whole. + *prevTimestampPtr = timestamp; + *prevMethodPtr = curMethod; +#endif +} + +/* + * native public static long elapsedRealtimeNano(); + */ +int64_t elapsedRealtimeNano() +{ #ifdef HAVE_ANDROID_OS + struct timespec ts; + int result; + int64_t timestamp; + static volatile int64_t prevTimestamp; + static volatile int prevMethod; + +#if 0 + /* + * b/7100774 + * clock_gettime appears to have clock skews and can sometimes return + * backwards values. Disable its use until we find out what's wrong. + */ + result = clock_gettime(CLOCK_BOOTTIME, &ts); + if (result == 0) { + timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; + checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, + METHOD_CLOCK_GETTIME); + return timestamp; + } +#endif + + // CLOCK_BOOTTIME doesn't exist, fallback to /dev/alarm static int s_fd = -1; if (s_fd == -1) { @@ -116,23 +183,24 @@ int64_t elapsedRealtime() } } - struct timespec ts; - int result = ioctl(s_fd, + result = ioctl(s_fd, ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts); if (result == 0) { - int64_t when = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; - return (int64_t) nanoseconds_to_milliseconds(when); - } else { - // XXX: there was an error, probably because the driver didn't - // exist ... this should return - // a real error, like an exception! - int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); - return (int64_t) nanoseconds_to_milliseconds(when); + timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; + checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, METHOD_IOCTL); + return timestamp; } + + // XXX: there was an error, probably because the driver didn't + // exist ... this should return + // a real error, like an exception! + timestamp = systemTime(SYSTEM_TIME_MONOTONIC); + checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, + METHOD_SYSTEMTIME); + return timestamp; #else - int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); - return (int64_t) nanoseconds_to_milliseconds(when); + return systemTime(SYSTEM_TIME_MONOTONIC); #endif } |