Incorrect warning message on thread pool startup in full AOT:ed Windows build.
[mono.git] / mono / utils / mono-time.c
1 /*
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.
6  */
7
8 #include <config.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11
12 #ifdef HAVE_SYS_TIME_H
13 #include <sys/time.h>
14 #endif
15
16 #include <utils/mono-time.h>
17
18
19 #define MTICKS_PER_SEC 10000000
20
21 #ifdef HOST_WIN32
22 #include <windows.h>
23
24 guint32
25 mono_msec_ticks (void)
26 {
27         /* GetTickCount () is reportedly monotonic */
28         return GetTickCount ();
29 }
30
31 /* Returns the number of 100ns ticks from unspecified time: this should be monotonic */
32 gint64
33 mono_100ns_ticks (void)
34 {
35         static LARGE_INTEGER freq;
36         static UINT64 start_time;
37         UINT64 cur_time;
38         LARGE_INTEGER value;
39
40         if (!freq.QuadPart) {
41                 if (!QueryPerformanceFrequency (&freq))
42                         return mono_100ns_datetime ();
43                 QueryPerformanceCounter (&value);
44                 start_time = value.QuadPart;
45         }
46         QueryPerformanceCounter (&value);
47         cur_time = value.QuadPart;
48         /* we use unsigned numbers and return the difference to avoid overflows */
49         return (cur_time - start_time) * (double)MTICKS_PER_SEC / freq.QuadPart;
50 }
51
52 /* Returns the number of 100ns ticks since Jan 1, 1601, UTC timezone */
53 gint64
54 mono_100ns_datetime (void)
55 {
56         ULARGE_INTEGER ft;
57
58         if (sizeof(ft) != sizeof(FILETIME))
59                 g_assert_not_reached ();
60
61         GetSystemTimeAsFileTime ((FILETIME*) &ft);
62         return ft.QuadPart;
63 }
64
65 #else
66
67
68 #if defined (HAVE_SYS_PARAM_H)
69 #include <sys/param.h>
70 #endif
71 #if defined(HAVE_SYS_SYSCTL_H)
72 #include <sys/sysctl.h>
73 #endif
74
75 #if defined(PLATFORM_MACOSX)
76 #include <mach/mach.h>
77 #include <mach/mach_time.h>
78 #endif
79
80 #include <time.h>
81
82 static gint64
83 get_boot_time (void)
84 {
85 #if defined (HAVE_SYS_PARAM_H) && defined (KERN_BOOTTIME)
86         int mib [2];
87         size_t size;
88         time_t now;
89         struct timeval boottime;
90
91         (void)time(&now);
92
93         mib [0] = CTL_KERN;
94         mib [1] = KERN_BOOTTIME;
95
96         size = sizeof(boottime);
97
98         if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1)
99                 return (gint64)((now - boottime.tv_sec) * MTICKS_PER_SEC);
100 #else
101         FILE *uptime = fopen ("/proc/uptime", "r");
102         if (uptime) {
103                 double upt;
104                 if (fscanf (uptime, "%lf", &upt) == 1) {
105                         gint64 now = mono_100ns_ticks ();
106                         fclose (uptime);
107                         return now - (gint64)(upt * MTICKS_PER_SEC);
108                 }
109                 fclose (uptime);
110         }
111 #endif
112         /* a made up uptime of 300 seconds */
113         return (gint64)300 * MTICKS_PER_SEC;
114 }
115
116 /* Returns the number of milliseconds from boot time: this should be monotonic */
117 guint32
118 mono_msec_ticks (void)
119 {
120         static gint64 boot_time = 0;
121         gint64 now;
122         if (!boot_time)
123                 boot_time = get_boot_time ();
124         now = mono_100ns_ticks ();
125         /*printf ("now: %llu (boot: %llu) ticks: %llu\n", (gint64)now, (gint64)boot_time, (gint64)(now - boot_time));*/
126         return (now - boot_time)/10000;
127 }
128
129 /* Returns the number of 100ns ticks from unspecified time: this should be monotonic */
130 gint64
131 mono_100ns_ticks (void)
132 {
133         struct timeval tv;
134 #ifdef CLOCK_MONOTONIC
135         struct timespec tspec;
136         static struct timespec tspec_freq = {0};
137         static int can_use_clock = 0;
138         if (!tspec_freq.tv_nsec) {
139                 can_use_clock = clock_getres (CLOCK_MONOTONIC, &tspec_freq) == 0;
140                 /*printf ("resolution: %lu.%lu\n", tspec_freq.tv_sec, tspec_freq.tv_nsec);*/
141         }
142         if (can_use_clock) {
143                 if (clock_gettime (CLOCK_MONOTONIC, &tspec) == 0) {
144                         /*printf ("time: %lu.%lu\n", tspec.tv_sec, tspec.tv_nsec); */
145                         return ((gint64)tspec.tv_sec * MTICKS_PER_SEC + tspec.tv_nsec / 100);
146                 }
147         }
148         
149 #elif defined(PLATFORM_MACOSX)
150         /* http://developer.apple.com/library/mac/#qa/qa1398/_index.html */
151         static mach_timebase_info_data_t timebase;
152         guint64 now = mach_absolute_time ();
153         if (timebase.denom == 0) {
154                 mach_timebase_info (&timebase);
155                 timebase.denom *= 100; /* we return 100ns ticks */
156         }
157         return now * timebase.numer / timebase.denom;
158 #endif
159         if (gettimeofday (&tv, NULL) == 0)
160                 return ((gint64)tv.tv_sec * 1000000 + tv.tv_usec) * 10;
161         return 0;
162 }
163
164 /*
165  * Magic number to convert unix epoch start to windows epoch start
166  * Jan 1, 1970 into a value which is relative to Jan 1, 1601.
167  */
168 #define EPOCH_ADJUST    ((guint64)11644473600LL)
169
170 /* Returns the number of 100ns ticks since 1/1/1601, UTC timezone */
171 gint64
172 mono_100ns_datetime (void)
173 {
174         struct timeval tv;
175         if (gettimeofday (&tv, NULL) == 0)
176                 return mono_100ns_datetime_from_timeval (tv);
177         return 0;
178 }
179
180 gint64
181 mono_100ns_datetime_from_timeval (struct timeval tv)
182 {
183         return (((gint64)tv.tv_sec + EPOCH_ADJUST) * 1000000 + tv.tv_usec) * 10;
184 }
185
186 #endif
187