2 * Time utility functions.
3 * Author: Paolo Molaro (<lupus@ximian.com>)
4 * Copyright (C) 2008 Novell, Inc.
5 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12 #ifdef HAVE_SYS_TIME_H
16 #include <utils/mono-time.h>
19 #define MTICKS_PER_SEC (10 * 1000 * 1000)
22 mono_msec_ticks (void)
24 return mono_100ns_ticks () / 10 / 1000;
31 /* we get "error: implicit declaration of function 'GetTickCount64'" */
32 ULONGLONG GetTickCount64(void);
36 mono_msec_boottime (void)
38 /* GetTickCount () is reportedly monotonic */
39 return GetTickCount64 ();
42 /* Returns the number of 100ns ticks from unspecified time: this should be monotonic */
44 mono_100ns_ticks (void)
46 static LARGE_INTEGER freq;
47 static UINT64 start_time;
52 if (!QueryPerformanceFrequency (&freq))
53 return mono_100ns_datetime ();
54 QueryPerformanceCounter (&value);
55 start_time = value.QuadPart;
57 QueryPerformanceCounter (&value);
58 cur_time = value.QuadPart;
59 /* we use unsigned numbers and return the difference to avoid overflows */
60 return (cur_time - start_time) * (double)MTICKS_PER_SEC / freq.QuadPart;
63 /* Returns the number of 100ns ticks since Jan 1, 1601, UTC timezone */
65 mono_100ns_datetime (void)
69 if (sizeof(ft) != sizeof(FILETIME))
70 g_assert_not_reached ();
72 GetSystemTimeAsFileTime ((FILETIME*) &ft);
79 #if defined (HAVE_SYS_PARAM_H)
80 #include <sys/param.h>
82 #if defined(HAVE_SYS_SYSCTL_H)
83 #include <sys/sysctl.h>
86 #if defined(PLATFORM_MACOSX)
87 #include <mach/mach.h>
88 #include <mach/mach_time.h>
96 #if defined (HAVE_SYS_PARAM_H) && defined (KERN_BOOTTIME)
100 struct timeval boottime;
105 mib [1] = KERN_BOOTTIME;
107 size = sizeof(boottime);
109 if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1)
110 return (gint64)((now - boottime.tv_sec) * MTICKS_PER_SEC);
112 FILE *uptime = fopen ("/proc/uptime", "r");
115 if (fscanf (uptime, "%lf", &upt) == 1) {
116 gint64 now = mono_100ns_ticks ();
118 return now - (gint64)(upt * MTICKS_PER_SEC);
123 /* a made up uptime of 300 seconds */
124 return (gint64)300 * MTICKS_PER_SEC;
127 /* Returns the number of milliseconds from boot time: this should be monotonic */
129 mono_msec_boottime (void)
131 static gint64 boot_time = 0;
134 boot_time = get_boot_time ();
135 now = mono_100ns_ticks ();
136 /*printf ("now: %llu (boot: %llu) ticks: %llu\n", (gint64)now, (gint64)boot_time, (gint64)(now - boot_time));*/
137 g_assert (now > boot_time);
138 return (now - boot_time)/10000;
141 /* Returns the number of 100ns ticks from unspecified time: this should be monotonic */
143 mono_100ns_ticks (void)
146 #ifdef CLOCK_MONOTONIC
147 struct timespec tspec;
148 static struct timespec tspec_freq = {0};
149 static int can_use_clock = 0;
150 if (!tspec_freq.tv_nsec) {
151 can_use_clock = clock_getres (CLOCK_MONOTONIC, &tspec_freq) == 0;
152 /*printf ("resolution: %lu.%lu\n", tspec_freq.tv_sec, tspec_freq.tv_nsec);*/
155 if (clock_gettime (CLOCK_MONOTONIC, &tspec) == 0) {
156 /*printf ("time: %lu.%lu\n", tspec.tv_sec, tspec.tv_nsec); */
157 return ((gint64)tspec.tv_sec * MTICKS_PER_SEC + tspec.tv_nsec / 100);
161 #elif defined(PLATFORM_MACOSX)
162 /* http://developer.apple.com/library/mac/#qa/qa1398/_index.html */
163 static mach_timebase_info_data_t timebase;
164 guint64 now = mach_absolute_time ();
165 if (timebase.denom == 0) {
166 mach_timebase_info (&timebase);
167 timebase.denom *= 100; /* we return 100ns ticks */
169 return now * timebase.numer / timebase.denom;
171 if (gettimeofday (&tv, NULL) == 0)
172 return ((gint64)tv.tv_sec * 1000000 + tv.tv_usec) * 10;
177 * Magic number to convert unix epoch start to windows epoch start
178 * Jan 1, 1970 into a value which is relative to Jan 1, 1601.
180 #define EPOCH_ADJUST ((guint64)11644473600LL)
182 /* Returns the number of 100ns ticks since 1/1/1601, UTC timezone */
184 mono_100ns_datetime (void)
187 if (gettimeofday (&tv, NULL) == 0)
188 return mono_100ns_datetime_from_timeval (tv);
193 mono_100ns_datetime_from_timeval (struct timeval tv)
195 return (((gint64)tv.tv_sec + EPOCH_ADJUST) * 1000000 + tv.tv_usec) * 10;