Merge pull request #2803 from BrzVlad/feature-conc-pinned-scan
[mono.git] / mono / utils / mono-time.c
index 32a55faab34fa880ed463f9d86850a761ac99670..5f0168ebb7475b94886d44a002331d2aa1184842 100644 (file)
@@ -2,15 +2,23 @@
  * Time utility functions.
  * Author: Paolo Molaro (<lupus@ximian.com>)
  * Copyright (C) 2008 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
-#include <utils/mono-time.h>
+#include <config.h>
 #include <stdlib.h>
 #include <stdio.h>
 
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <utils/mono-time.h>
+
+
 #define MTICKS_PER_SEC 10000000
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
 #include <windows.h>
 
 guint32
@@ -25,35 +33,48 @@ gint64
 mono_100ns_ticks (void)
 {
        static LARGE_INTEGER freq;
+       static UINT64 start_time;
+       UINT64 cur_time;
        LARGE_INTEGER value;
 
-       if (!freq.QuadPart && !QueryPerformanceFrequency (&freq))
-               return mono_100ns_datetime ();
+       if (!freq.QuadPart) {
+               if (!QueryPerformanceFrequency (&freq))
+                       return mono_100ns_datetime ();
+               QueryPerformanceCounter (&value);
+               start_time = value.QuadPart;
+       }
        QueryPerformanceCounter (&value);
-       return value.QuadPart * MTICKS_PER_SEC / freq.QuadPart;
+       cur_time = value.QuadPart;
+       /* we use unsigned numbers and return the difference to avoid overflows */
+       return (cur_time - start_time) * (double)MTICKS_PER_SEC / freq.QuadPart;
 }
 
-/*
- * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
- */
-#define FILETIME_ADJUST ((guint64)504911232000000000LL)
-
-/* Returns the number of 100ns ticks since 1/1/1, UTC timezone */
+/* Returns the number of 100ns ticks since Jan 1, 1601, UTC timezone */
 gint64
 mono_100ns_datetime (void)
 {
-       SYSTEMTIME st;
-       FILETIME ft;
+       ULARGE_INTEGER ft;
 
-       GetSystemTime (&st);
-       SystemTimeToFileTime (&st, &ft);
-       return (gint64) FILETIME_ADJUST + ((((gint64)ft.dwHighDateTime)<<32) | ft.dwLowDateTime);
+       if (sizeof(ft) != sizeof(FILETIME))
+               g_assert_not_reached ();
+
+       GetSystemTimeAsFileTime ((FILETIME*) &ft);
+       return ft.QuadPart;
 }
 
 #else
 
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
+
+#if defined (HAVE_SYS_PARAM_H)
+#include <sys/param.h>
+#endif
+#if defined(HAVE_SYS_SYSCTL_H)
+#include <sys/sysctl.h>
+#endif
+
+#if defined(PLATFORM_MACOSX)
+#include <mach/mach.h>
+#include <mach/mach_time.h>
 #endif
 
 #include <time.h>
@@ -61,7 +82,22 @@ mono_100ns_datetime (void)
 static gint64
 get_boot_time (void)
 {
-       /* FIXME: use sysctl (kern.boottime) on OSX */
+#if defined (HAVE_SYS_PARAM_H) && defined (KERN_BOOTTIME)
+       int mib [2];
+       size_t size;
+       time_t now;
+       struct timeval boottime;
+
+       (void)time(&now);
+
+       mib [0] = CTL_KERN;
+       mib [1] = KERN_BOOTTIME;
+
+       size = sizeof(boottime);
+
+       if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1)
+               return (gint64)((now - boottime.tv_sec) * MTICKS_PER_SEC);
+#else
        FILE *uptime = fopen ("/proc/uptime", "r");
        if (uptime) {
                double upt;
@@ -72,6 +108,7 @@ get_boot_time (void)
                }
                fclose (uptime);
        }
+#endif
        /* a made up uptime of 300 seconds */
        return (gint64)300 * MTICKS_PER_SEC;
 }
@@ -109,6 +146,15 @@ mono_100ns_ticks (void)
                }
        }
        
+#elif defined(PLATFORM_MACOSX)
+       /* http://developer.apple.com/library/mac/#qa/qa1398/_index.html */
+       static mach_timebase_info_data_t timebase;
+       guint64 now = mach_absolute_time ();
+       if (timebase.denom == 0) {
+               mach_timebase_info (&timebase);
+               timebase.denom *= 100; /* we return 100ns ticks */
+       }
+       return now * timebase.numer / timebase.denom;
 #endif
        if (gettimeofday (&tv, NULL) == 0)
                return ((gint64)tv.tv_sec * 1000000 + tv.tv_usec) * 10;
@@ -116,20 +162,26 @@ mono_100ns_ticks (void)
 }
 
 /*
- * Magic number to convert a time which is relative to
- * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
+ * Magic number to convert unix epoch start to windows epoch start
+ * Jan 1, 1970 into a value which is relative to Jan 1, 1601.
  */
-#define EPOCH_ADJUST    ((guint64)62135596800LL)
+#define EPOCH_ADJUST    ((guint64)11644473600LL)
 
-/* Returns the number of 100ns ticks since 1/1/1, UTC timezone */
+/* Returns the number of 100ns ticks since 1/1/1601, UTC timezone */
 gint64
 mono_100ns_datetime (void)
 {
        struct timeval tv;
        if (gettimeofday (&tv, NULL) == 0)
-               return (((gint64)tv.tv_sec + EPOCH_ADJUST) * 1000000 + tv.tv_usec) * 10;
+               return mono_100ns_datetime_from_timeval (tv);
        return 0;
 }
 
+gint64
+mono_100ns_datetime_from_timeval (struct timeval tv)
+{
+       return (((gint64)tv.tv_sec + EPOCH_ADJUST) * 1000000 + tv.tv_usec) * 10;
+}
+
 #endif