summaryrefslogtreecommitdiffstats
path: root/tinySAK/src/tsk_time.c
blob: 0f93df8c8618c4c84feedc26a48350dd96752710 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*	
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*	
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*	
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/

/**@file tsk_time.c
* @brief Datetime functions.
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* @date Created: Sat Nov 8 16:54:58 2009 mdiop
*/
#include "tsk_time.h"

#include "tsk_debug.h"

#if TSK_UNDER_WINDOWS
#	include <Winsock2.h> // timeval
#	include <windows.h>
#	if TSK_UNDER_WINDOWS_CE && HAVE_WCECOMPAT
#		include <sys/time.h>
#	endif
#elif defined(__SYMBIAN32__)
#	include <_timeval.h> 
#else
#	include <sys/time.h>
#endif

#include <time.h>
#if defined (__APPLE__)
#	include <mach/mach.h>
#	include <mach/mach_time.h>
#endif

/**@defgroup tsk_time_group Datetime functions.
*/

#if !HAVE_GETTIMEOFDAY
#if TSK_UNDER_WINDOWS

/* For windows implementation of "gettimeofday" Thanks to "http://www.cpp-programming.net/c-tidbits/gettimeofday-function-for-windows" */
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif

#if TSK_UNDER_WINDOWS_CE
#endif 

struct timezone 
{  
	int  tz_minuteswest; // minutes W of Greenwich  
	int  tz_dsttime;     // type of dst correction
};

static int gettimeofday(struct timeval *tv, struct timezone *tz) 
{  
	FILETIME ft;
	uint64_t tmpres = 0;  
	static int tzflag = 0; 

	if(tv)   
	{    
#if TSK_UNDER_WINDOWS_CE
		SYSTEMTIME st;
		GetSystemTime(&st);
		SystemTimeToFileTime(&st, &ft);
#else
		GetSystemTimeAsFileTime(&ft);
#endif /* TSK_UNDER_WINDOWS_CE */

		tmpres |= ft.dwHighDateTime;   
		tmpres <<= 32; 
		tmpres |= ft.dwLowDateTime;

		/*converting file time to unix epoch*/   
		tmpres /= 10;  /*convert into microseconds*/  
		tmpres -= DELTA_EPOCH_IN_MICROSECS;  
		tv->tv_sec = (long)(tmpres / 1000000UL); 
		tv->tv_usec = (long)(tmpres % 1000000UL); 
	}

#if !TSK_UNDER_WINDOWS_CE
	if (tz){   
		if (!tzflag){
#if !TSK_UNDER_WINDOWS_RT
			_tzset();
#endif /* TSK_UNDER_WINDOWS_RT */
			tzflag++;  
		}   
		tz->tz_minuteswest = _timezone / 60;
		tz->tz_dsttime = _daylight;
	}
#endif /* TSK_UNDER_WINDOWS_CE */

	return 0; 
}

#else
#pragma error "You MUST provide an implement for 'gettimeofday'"
#endif /* WIN32 */

#endif /* !HAVE_GETTIMEOFDAY */

/**@ingroup tsk_time_group
* The tsk_gettimeofday() function shall obtain the current time, expressed as seconds and microseconds since EPOCH (00:00:00 UTC on 1 January 1970). 
* The resolution of the system clock is unspecified.
* @param tv The current time, expressed as seconds and microseconds since EPOCH(00:00:00 UTC on 1 January 1970).
* @param tz The timezone.
* @retval The tsk_gettimeofday() function shall return 0 and no value shall be reserved to indicate an error.
*/
int tsk_gettimeofday(struct timeval *tv, struct timezone *tz)
{
	return gettimeofday(tv, tz);
}

/**@ingroup tsk_time_group
*/
uint64_t tsk_gettimeofday_ms()
{
	struct timeval tv;
	tsk_gettimeofday(&tv, tsk_null);
	return (((uint64_t)tv.tv_sec)*(uint64_t)1000) + (((uint64_t)tv.tv_usec)/(uint64_t)1000);
}

/**@ingroup tsk_time_group
* Gets the number of milliseconds in @a tv
* @retval The number of milliseconds
*/
uint64_t tsk_time_get_ms(const struct timeval* tv)
{
	if(!tv){
		TSK_DEBUG_ERROR("Invalid parameter");
		return 0;
	}
	return (((uint64_t)tv->tv_sec)*(uint64_t)1000) + (((uint64_t)tv->tv_usec)/(uint64_t)1000);
}

/**@ingroup tsk_time_group
* Gets the number of milliseconds since the EPOCH.
* @retval The number of milliseconds since EPOCH.
*/
uint64_t tsk_time_epoch()
{
	struct timeval tv;
	gettimeofday(&tv, (struct timezone *)tsk_null);
	return (((uint64_t)tv.tv_sec)*(uint64_t)1000) + (((uint64_t)tv.tv_usec)/(uint64_t)1000);
}

// /!\ NOT CURRENT TIME
// only make sense when comparing two values (e.g. for duration)
uint64_t tsk_time_now()
{
#if TSK_UNDER_WINDOWS
	static int __cpu_count = 0;
	if(__cpu_count == 0){
		SYSTEM_INFO SystemInfo;
#	if TSK_UNDER_WINDOWS_RT
		GetNativeSystemInfo(&SystemInfo);
#	else
		GetSystemInfo(&SystemInfo);
#	endif
		__cpu_count = SystemInfo.dwNumberOfProcessors;
	}
	if(__cpu_count == 1){
		static LARGE_INTEGER __liFrequency = {0};
		LARGE_INTEGER liPerformanceCount;
		if(!__liFrequency.QuadPart){
			QueryPerformanceFrequency(&__liFrequency);
		}
		QueryPerformanceCounter(&liPerformanceCount);
		return (uint64_t)(((double)liPerformanceCount.QuadPart/(double)__liFrequency.QuadPart)*1000.0);
	}
	else{
#	if TSK_UNDER_WINDOWS_RT
		return tsk_time_epoch();
#	else
		return timeGetTime();
#	endif
	}
#elif HAVE_CLOCK_GETTIME || _POSIX_TIMERS > 0
	struct timespec ts;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	return (((uint64_t)ts.tv_sec)*(uint64_t)1000) + (((uint64_t)ts.tv_nsec)/(uint64_t)1000000);
#elif defined(__APPLE__)
    static mach_timebase_info_data_t __apple_timebase_info = {0, 0};
    if (__apple_timebase_info.denom == 0) {
        (void) mach_timebase_info(&__apple_timebase_info);
    }
    return (uint64_t)((mach_absolute_time() * __apple_timebase_info.numer) / (1e+6 * __apple_timebase_info.denom));
#else
	struct timeval tv;
	gettimeofday(&tv, tsk_null); 
	return (((uint64_t)tv.tv_sec)*(uint64_t)1000) + (((uint64_t)tv.tv_usec)/(uint64_t)1000);
#endif
}

// http://en.wikipedia.org/wiki/Network_Time_Protocol
uint64_t tsk_time_ntp()
{
	struct timeval tv;
	gettimeofday(&tv, (struct timezone *)tsk_null);
	return tsk_time_get_ntp_ms(&tv);
}

uint64_t tsk_time_get_ntp_ms(const struct timeval *tv)
{
	static const unsigned long __epoch = 2208988800UL;
	static const double __ntp_scale_frac = 4294967295.0;

	uint64_t tv_ntp;
	uint64_t tv_usecs;

	if(!tv){
		TSK_DEBUG_ERROR("Invalid parameter");
		return 0;
	}

	tv_ntp = tv->tv_sec + __epoch;
#if 0 // ARM floating point calc issue (__aeabi_d2uiz)
	tv_usecs = (tv->tv_usec * 1e-6) * __ntp_scale_frac;
	return ((tv_ntp << 32) | (uint32_t)tv_usecs);
#else
	tv_usecs = ((uint64_t)tv->tv_usec * (uint64_t)__ntp_scale_frac) / (uint64_t)1000000;
	return ((((uint64_t)tv_ntp) << 32) | (uint32_t)tv_usecs);
#endif
}
OpenPOWER on IntegriCloud