hce-node application  1.4.3
HCE Hierarchical Cluster Engine node application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cf_clock.h
Go to the documentation of this file.
1 /*
2  * Citrusleaf Foundation
3  * src/clock.c - memory allocation framework
4  *
5  * Copyright 2008-2009 by Citrusleaf. All rights reserved.
6  * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE. THE COPYRIGHT NOTICE
7  * ABOVE DOES NOT EVIDENCE ANY ACTUAL OR INTENDED PUBLICATION.
8  */
9 
10 #pragma once
11 
12 #include <stdint.h>
13 
14 
15 #ifndef CF_WINDOWS
16 //====================================================================
17 // Linux
18 //
19 
20 #include <time.h>
21 #include <bits/time.h>
22 
23 
24 #else // CF_WINDOWS
25 //====================================================================
26 // Windows
27 //
28 
29 #include <WinSock2.h> // for struct timeval
30 #include <pthread.h> // for struct timespec
31 
32 #define CLOCK_REALTIME 0
33 #define CLOCK_MONOTONIC 1
34 #define CLOCK_PROCESS_CPUTIME_ID 2
35 
36 
37 inline static LARGE_INTEGER
38 getFILETIMEoffset()
39 {
40  SYSTEMTIME s;
41  FILETIME f;
42  LARGE_INTEGER t;
43 
44  s.wYear = 1970;
45  s.wMonth = 1;
46  s.wDay = 1;
47  s.wHour = 0;
48  s.wMinute = 0;
49  s.wSecond = 0;
50  s.wMilliseconds = 0;
51  SystemTimeToFileTime(&s, &f);
52  t.QuadPart = f.dwHighDateTime;
53  t.QuadPart <<= 32;
54  t.QuadPart |= f.dwLowDateTime;
55 
56  return (t);
57 }
58 
59 static inline int clock_gettime(int clock_type, struct timespec* p_ts)
60 {
61  LARGE_INTEGER t;
62  FILETIME f;
63  double nanoseconds;
64  static LARGE_INTEGER offset;
65  static double frequencyToNanoseconds;
66  static int initialized = 0;
67  static BOOL usePerformanceCounter = 0;
68 
69  if (!initialized) {
70  LARGE_INTEGER performanceFrequency;
71  initialized = 1;
72  usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
73  if (usePerformanceCounter) {
74  QueryPerformanceCounter(&offset);
75  frequencyToNanoseconds = (double)performanceFrequency.QuadPart / 1000000000.;
76  } else {
77  offset = getFILETIMEoffset();
78  frequencyToNanoseconds = 10000.;
79  }
80  }
81 
82  if (usePerformanceCounter) {
83  QueryPerformanceCounter(&t);
84  }
85  else {
86  GetSystemTimeAsFileTime(&f);
87  t.QuadPart = f.dwHighDateTime;
88  t.QuadPart <<= 32;
89  t.QuadPart |= f.dwLowDateTime;
90  }
91 
92  t.QuadPart -= offset.QuadPart;
93  nanoseconds = (double)t.QuadPart / frequencyToNanoseconds;
94  t.QuadPart = (LONGLONG)nanoseconds;
95  p_ts->tv_sec = t.QuadPart / 1000000000;
96  p_ts->tv_nsec = t.QuadPart % 1000000000;
97 
98  return 0;
99 }
100 
101 #endif // CF_WINDOWS
102 
103 
104 #ifdef __cplusplus
105 extern "C" {
106 #endif
107 
108 #ifdef OSX // Macs aren't posix compliant
109 #include <sys/time.h>
110 #include <mach/mach.h>
111 #include <mach/mach_time.h>
112 #endif
113 
114 inline static uint64_t
115 TIMESPEC_TO_MS( struct timespec *ts )
116 {
117  uint64_t r1 = ts->tv_nsec;
118  r1 /= 1000000;
119  uint64_t r2 = ts->tv_sec;
120  r2 *= 1000;
121  return( r1 + r2 );
122 }
123 
124 
125 // FIXME ought to be cf_clock_getvolatile
126 inline static uint64_t
127 cf_getms() {
128 #ifdef OSX
129  // XXX from what I can tell, mach_absolute_time is a monotonic clock. At least, it appears
130  // to be used that way by game programmers. The literature is unclear about this.
131  // However, to allow people to use mach_absolute_time across multiple platforms, the
132  // designers decided not to specify the units of time that it returned, but instead paired it
133  // with a timebase function that can be used to determine the units.
134  // While this ends up being very fast, it also requires an initialization which is slightly
135  // outside of the current CL architecture. So, instead of changing CL, I'm going to just
136  // use the fact that mach_absolute_time returns nanoseconds on modern macs, and accept
137  // that at some point this implementation may break. Que sera sera. - csw
138  // mach_timebase_info_data_t sTimebaseInfo;
139  // mach_timebase_info(&sTimebaseInfo);
140  // - or -
141  // pthread_once(&mtime_timebase_info_once, mtime_init_timebase);
142  uint64_t date = mach_absolute_time();
143 
144  /* Convert to nanoseconds - we're OSX on the Mac, it's already ns... see above */
145  // date *= sTimebaseInfo.numer;
146  // date /= sTimebaseInfo.denom;
147 
148  /* Convert to milliseconds */
149  return date / 1000000;
150 
151 // nanouptime(&ts);
152 #else
153  struct timespec ts;
154  clock_gettime( CLOCK_MONOTONIC, &ts);
155  return ( TIMESPEC_TO_MS( &ts ) );
156 #endif
157 }
158 
159 
160 static inline uint64_t
161 cf_getmicros()
162 {
163  struct timespec ts = { 0, 0};
164  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
165  uint64_t micro = (ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
166  return(micro);
167 }
168 
169 inline static uint64_t
170 TIMESPEC_TO_US( struct timespec *ts )
171 {
172  uint64_t r1 = ts->tv_nsec;
173  r1 /= 1000;
174  uint64_t r2 = ts->tv_sec;
175  r2 *= 1000000;
176  return( r1 + r2 );
177 }
178 // FIXME ought to be cf_clock_getvolatile
179 inline static uint64_t
180 cf_getus() {
181 #ifdef OSX
182  uint64_t date = mach_absolute_time();
183 
184  /* Convert to nanoseconds - we're OSX on the Mac, it's already ns... see above */
185  // date *= sTimebaseInfo.numer;
186  // date /= sTimebaseInfo.denom;
187 
188  /* Convert to microseconds */
189  return date / 1000;
190 
191 #else
192  struct timespec ts;
193  clock_gettime( CLOCK_MONOTONIC, &ts);
194  return ( TIMESPEC_TO_US( &ts ) );
195 #endif
196 }
197 
198 inline static uint64_t
199 cf_clock_getabsolute() {
200 #ifdef OSX
201  struct timeval tv;
202  gettimeofday(&tv, NULL);
203 
204  uint64_t realtime = tv.tv_sec * 1000000 + tv.tv_usec;
205  return realtime;
206 #else
207  struct timespec ts;
208  clock_gettime(CLOCK_REALTIME, &ts);
209  return(TIMESPEC_TO_MS(&ts));
210 #endif
211 }
212 #ifdef __cplusplus
213 } // end extern "C"
214 #endif
215 
216 //
217 // Citrusleaf Epoch RTC API
218 //
219 
220 #define CITRUSLEAF_EPOCH 1262304000
221 
222 static inline uint32_t
223 cf_clepoch_seconds()
224 {
225  struct timespec ts;
226  clock_gettime(CLOCK_REALTIME, &ts);
227  return (uint32_t)(ts.tv_sec - CITRUSLEAF_EPOCH);
228 }
229