1
/*
2
*******************************************************************************
3
\file tm.c
4
\brief Time and timers
5
\project bee2 [cryptographic library]
6
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
7
\created 2012.05.10
8
\version 2015.11.25
9
\license This program is released under the GNU General Public License 
10
version 3. See Copyright Notices in bee2/info.h.
11
*******************************************************************************
12
*/
13

14
#include "bee2/core/mem.h"
15
#include "bee2/core/mt.h"
16
#include "bee2/core/tm.h"
17

18
/*
19
*******************************************************************************
20
Таймер
21

22
\todo Протестировать все возможности.
23

24
\todo Определять частоту без временной задержки.
25
*******************************************************************************
26
*/
27

28
#if defined(_MSC_VER)
29

30
#if defined(_M_IX86) || defined (_M_IA64) || defined (_M_X64)
31

32
#pragma intrinsic(__rdtsc)
33
tm_ticks_t tmTicks()
34
{
35
	return (tm_ticks_t)__rdtsc();
36
}
37

38
tm_ticks_t tmFreq()
39
{
40
	static tm_ticks_t freq = 0;
41
	if (freq == 0)
42
	{
43
		tm_ticks_t start = tmTicks();
44
		tm_ticks_t overhead = tmTicks() - start;
45
		start = tmTicks();
46
		Sleep(100);
47
		freq = tmTicks() - start - overhead;
48
		freq *= 10;
49
	}
50
	return freq;
51
}
52

53
#else
54

55
#include <windows.h>
56

57
tm_ticks_t tmTicks()
58
{
59
	LARGE_INTEGER ctr;
60
	if (QueryPerformanceCounter(&ctr))
61
		return (tm_ticks_t)ctr.QuadPart;
62
	return (tm_ticks_t)clock();
63
}
64

65
tm_ticks_t tmFreq()
66
{
67
	LARGE_INTEGER freq;
68
	if (QueryPerformanceFrequency(&freq))
69
		return (tm_ticks_t)freq.QuadPart;
70
	return (tm_ticks_t)CLOCKS_PER_SEC;
71
}
72

73
#endif
74

75
#elif defined(__GNUC__)
76

77
#if defined(__i386__) || defined(__x86_64__)
78

79
#if defined(__i386__) || (B_PER_W == 16)
80

81
tm_ticks_t tmTicks()
82
{
83
	register tm_ticks_t x;
84
	__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
85
	return x;
86
}
87

88
#else
89

90 1
tm_ticks_t tmTicks()
91
{
92
	register u32 hi;
93
	register u32 lo;
94 1
	__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
95 1
	return (tm_ticks_t)lo | (tm_ticks_t)hi << 32;
96
}
97

98
#endif
99

100 1
tm_ticks_t tmFreq()
101
{
102
	static tm_ticks_t freq = 0;
103 1
	if (freq == 0)
104
	{
105
		struct timespec ts;
106
		tm_ticks_t start;
107
		tm_ticks_t overhead;
108 1
		ts.tv_sec = 0, ts.tv_nsec = 100000000;
109 1
		start = tmTicks();
110 1
		overhead = tmTicks() - start;
111 1
		nanosleep(&ts, 0);
112 1
		freq = tmTicks() - start - overhead;
113 1
		freq *= 10;
114
	}
115 1
	return freq;
116
}
117

118
#elif (B_PER_W > 16)
119

120
tm_ticks_t tmTicks()
121
{
122
	struct timespec ts;
123
	tm_ticks_t ticks;
124
	if (clock_gettime(CLOCK_MONOTONIC, &ts))
125
		return 0;
126
	ticks = (tm_ticks_t)ts.tv_sec;
127
	ticks *= 1000000000u;
128
	ticks += (tm_ticks_t)ts.tv_nsec;
129
	return ticks;
130
}
131

132
tm_ticks_t tmFreq()
133
{
134
	struct timespec ts;
135
	tm_ticks_t freq;
136
	if (clock_getres(CLOCK_MONOTONIC, &ts) || ts.tv_sec || !ts.tv_nsec)
137
		return 0;
138
	freq = 1000000000u;
139
	freq /= (tm_ticks_t)ts.tv_nsec;
140
	return freq;
141
}
142

143
#else
144

145
tm_ticks_t tmTicks()
146
{
147
	return (tm_ticks_t)clock();
148
}
149

150
tm_ticks_t tmFreq()
151
{
152
	return (tm_ticks_t)CLOCKS_PER_SEC;
153
}
154

155
#endif
156

157
#else
158

159
tm_ticks_t tmTicks()
160
{
161
	return (tm_ticks_t)clock();
162
}
163

164
tm_ticks_t tmFreq()
165
{
166
	return (tm_ticks_t)CLOCKS_PER_SEC;
167
}
168

169
#endif
170

171 1
size_t tmSpeed(size_t reps, tm_ticks_t ticks)
172
{
173 1
	return ticks ? (size_t)((dword)reps * tmFreq() / ticks) : SIZE_MAX;
174
}
175

176
/*
177
*******************************************************************************
178
Время
179

180
\todo Гарантировать 64-битовый счетчик.
181
\todo Поддержать представление времени в формате ISO 8601.
182
*******************************************************************************
183
*/
184

185 1
tm_time_t tmTime()
186
{
187 1
	return time(0);
188
}
189

190 1
tm_time_t tmTimeRound(tm_time_t t0, tm_time_t ts)
191
{
192 1
	register tm_time_t t = tmTime();
193 1
	if (ts == 0 || t < t0)
194 0
		return TIME_ERR;
195 1
	t = (t - t0) / ts;
196 1
	return t;
197
}

Read our documentation on viewing source code .

Loading