+/*
+ * Find a suitable system time. Start with the highest resolution source
+ * and work down to the slower ones. This is added as additional data and
+ * isn't counted as randomness, so any result is acceptable.
+ */
+static uint64_t get_timer_bits(void)
+{
+ uint64_t res = OPENSSL_rdtsc();
+
+ if (res != 0)
+ return res;
+#if defined(_WIN32)
+ {
+ LARGE_INTEGER t;
+ FILETIME ft;
+
+ if (QueryPerformanceCounter(&t) != 0)
+ return t.QuadPart;
+ GetSystemTimeAsFileTime(&ft);
+ return TWO32TO64(ft.dwHighDateTime, ft.dwLowDateTime);
+ }
+#elif defined(__sun) || defined(__hpux)
+ return gethrtime();
+#elif defined(_AIX)
+ {
+ timebasestruct_t t;
+
+ read_wall_time(&t, TIMEBASE_SZ);
+ return TWO32TO64(t.tb_high, t.tb_low);
+ }
+#else
+
+# if defined(_POSIX_C_SOURCE) \
+ && defined(_POSIX_TIMERS) \
+ && _POSIX_C_SOURCE >= 199309L \
+ && (!defined(__GLIBC__) || __GLIBC_PREREQ(2, 17))
+ {
+ struct timespec ts;
+ clockid_t cid;
+
+# ifdef CLOCK_BOOTTIME
+ cid = CLOCK_BOOTTIME;
+# elif defined(_POSIX_MONOTONIC_CLOCK)
+ cid = CLOCK_MONOTONIC;
+# else
+ cid = CLOCK_REALTIME;
+# endif
+
+ if (clock_gettime(cid, &ts) == 0)
+ return TWO32TO64(ts.tv_sec, ts.tv_nsec);
+ }
+# endif
+# if defined(__unix__) \
+ || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
+ {
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) == 0)
+ return TWO32TO64(tv.tv_sec, tv.tv_usec);
+ }
+# endif
+ return time(NULL);
+#endif
+}
+