Implement JVM_GetNanoTimeAdjustment
Bug: 180577079
Test: atest CtsLibcoreOjTestCases:test.java.time.TestClock_System
Change-Id: I5300da80b5f8555358d0ab56a9340cebae765bab
diff --git a/openjdkjvm/OpenjdkJvm.cc b/openjdkjvm/OpenjdkJvm.cc
index 63503f4..8c1f773 100644
--- a/openjdkjvm/OpenjdkJvm.cc
+++ b/openjdkjvm/OpenjdkJvm.cc
@@ -210,6 +210,33 @@
return when;
}
+/**
+ * See the spec of this function in jdk.internal.misc.VM.
+ * @return -1 if the system time isn't within +/- 2^32 seconds from offset_secs
+ */
+JNIEXPORT jlong JVM_GetNanoTimeAdjustment(JNIEnv *ATTRIBUTE_UNUSED,
+ jclass ATTRIBUTE_UNUSED,
+ jlong offset_secs) {
+ struct timeval tv;
+ // Note that we don't want the elapsed time here, but the system clock.
+ // gettimeofday() doesn't provide nanosecond-level precision.
+ // clock_gettime(CLOCK_REALTIME, tp) may provide nanosecond-level precision.
+ // If it does support higher precision, we should switch both
+ // JVM_CurrentTimeMillis and JVM_GetNanoTimeAdjustment to use clock_gettime
+ // instead of gettimeofday() because various callers assume that
+ // System.currentTimeMillis() and VM.getNanoTimeAdjustment(offset) use the
+ // same time source.
+ gettimeofday(&tv, (struct timezone *) nullptr);
+ jlong sec_diff = ((jlong) tv.tv_sec) - offset_secs;
+ const jlong max_diff = ((jlong) 1) << 32;
+ const jlong min_diff = -max_diff;
+ if (sec_diff >= max_diff || sec_diff <= min_diff) {
+ return -1;
+ }
+ jlong usec_diff = sec_diff * 1000000LL + tv.tv_usec;
+ return usec_diff * 1000;
+}
+
JNIEXPORT jint JVM_Socket(jint domain, jint type, jint protocol) {
return TEMP_FAILURE_RETRY(socket(domain, type, protocol));
}