2008-10-24 Mark Probst <mark.probst@gmail.com>
[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  */
6
7 #include <utils/mono-time.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10
11 #define MTICKS_PER_SEC 10000000
12
13 #ifdef PLATFORM_WIN32
14 #include <windows.h>
15
16 guint32
17 mono_msec_ticks (void)
18 {
19         /* GetTickCount () is reportedly monotonic */
20         return GetTickCount ();
21 }
22
23 /* Returns the number of 100ns ticks from unspecified time: this should be monotonic */
24 gint64
25 mono_100ns_ticks (void)
26 {
27         static LARGE_INTEGER freq;
28         LARGE_INTEGER value;
29
30         if (!freq.QuadPart && !QueryPerformanceFrequency (&freq))
31                 return mono_100ns_datetime ();
32         QueryPerformanceCounter (&value);
33         return value.QuadPart * MTICKS_PER_SEC / freq.QuadPart;
34 }
35
36 /*
37  * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
38  */
39 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
40
41 /* Returns the number of 100ns ticks since 1/1/1, UTC timezone */
42 gint64
43 mono_100ns_datetime (void)
44 {
45         SYSTEMTIME st;
46         FILETIME ft;
47
48         GetSystemTime (&st);
49         SystemTimeToFileTime (&st, &ft);
50         return (gint64) FILETIME_ADJUST + ((((gint64)ft.dwHighDateTime)<<32) | ft.dwLowDateTime);
51 }
52
53 #else
54
55 #ifdef HAVE_SYS_TIME_H
56 #include <sys/time.h>
57 #endif
58
59 #include <time.h>
60
61 static gint64
62 get_boot_time (void)
63 {
64         /* FIXME: use sysctl (kern.boottime) on OSX */
65         FILE *uptime = fopen ("/proc/uptime", "r");
66         if (uptime) {
67                 double upt;
68                 if (fscanf (uptime, "%lf", &upt) == 1) {
69                         gint64 now = mono_100ns_ticks ();
70                         fclose (uptime);
71                         return now - (gint64)(upt * MTICKS_PER_SEC);
72                 }
73                 fclose (uptime);
74         }
75         /* a made up uptime of 300 seconds */
76         return (gint64)300 * MTICKS_PER_SEC;
77 }
78
79 /* Returns the number of milliseconds from boot time: this should be monotonic */
80 guint32
81 mono_msec_ticks (void)
82 {
83         static gint64 boot_time = 0;
84         gint64 now;
85         if (!boot_time)
86                 boot_time = get_boot_time ();
87         now = mono_100ns_ticks ();
88         /*printf ("now: %llu (boot: %llu) ticks: %llu\n", (gint64)now, (gint64)boot_time, (gint64)(now - boot_time));*/
89         return (now - boot_time)/10000;
90 }
91
92 /* Returns the number of 100ns ticks from unspecified time: this should be monotonic */
93 gint64
94 mono_100ns_ticks (void)
95 {
96         struct timeval tv;
97 #ifdef CLOCK_MONOTONIC
98         struct timespec tspec;
99         static struct timespec tspec_freq = {0};
100         static int can_use_clock = 0;
101         if (!tspec_freq.tv_nsec) {
102                 can_use_clock = clock_getres (CLOCK_MONOTONIC, &tspec_freq) == 0;
103                 /*printf ("resolution: %lu.%lu\n", tspec_freq.tv_sec, tspec_freq.tv_nsec);*/
104         }
105         if (can_use_clock) {
106                 if (clock_gettime (CLOCK_MONOTONIC, &tspec) == 0) {
107                         /*printf ("time: %lu.%lu\n", tspec.tv_sec, tspec.tv_nsec); */
108                         return ((gint64)tspec.tv_sec * MTICKS_PER_SEC + tspec.tv_nsec / 100);
109                 }
110         }
111         
112 #endif
113         if (gettimeofday (&tv, NULL) == 0)
114                 return ((gint64)tv.tv_sec * 1000000 + tv.tv_usec) * 10;
115         return 0;
116 }
117
118 /*
119  * Magic number to convert a time which is relative to
120  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
121  */
122 #define EPOCH_ADJUST    ((guint64)62135596800LL)
123
124 /* Returns the number of 100ns ticks since 1/1/1, UTC timezone */
125 gint64
126 mono_100ns_datetime (void)
127 {
128         struct timeval tv;
129         if (gettimeofday (&tv, NULL) == 0)
130                 return (((gint64)tv.tv_sec + EPOCH_ADJUST) * 1000000 + tv.tv_usec) * 10;
131         return 0;
132 }
133
134 #endif
135