]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
make System_GetTimeMonotonic() really monotonic
authorOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:23:10 +0000 (11:23 -0700)
committerOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:23:10 +0000 (11:23 -0700)
Solaris has an issue where times() can return a lower value than it
returned earlier, making it non-monotonic. This change works
around this by saving the last returned value and returning that
if the times() function return a lower value.

open-vm-tools/lib/system/systemLinux.c

index 8e6f77269e1d47177e0a81ca2447a864488a0ead..293adb23eff8eba0c8d9e675184e7dc7bd35754c 100644 (file)
@@ -162,9 +162,32 @@ System_GetTimeMonotonic(void)
 
    return base + (last = current);
 #else  // VM_X86_64
-
+#ifdef sun
+   /* Solaris has a bug where times() can return a lower value than in
+    * a previous call, see bug #1710952, so we make sure to never
+    * return a lower value, by saving the old value and compare.
+    * We also make that thread safe. */
+   static Atomic_uint64 last = { 0 };
+
+   while (1) {
+      uint64 last1 = Atomic_Read64(&last);
+      uint64 now = times(&tp);
+
+      if (now > last1) {
+         uint64 last2 = Atomic_ReadIfEqualWrite64(&last, last1, now);
+         /* check if another thread changed last, and try again if true */
+         if (last2 != last1) {
+            continue;
+         }
+         return now;
+      } else {
+         return last1;
+      }
+   }
+#else
    return times(&tp);
 #endif
+#endif
 }