File: monoclock.c

package info (click to toggle)
python-scrypt 0.9.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 832 kB
  • sloc: ansic: 6,290; python: 733; sh: 99; makefile: 5
file content (224 lines) | stat: -rw-r--r-- 5,514 bytes parent folder | download
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
#include <errno.h>
#include <time.h>

#ifdef _MSC_VER
#include <Windows.h>
#include <sys/time.h> /* Use the Windows stub header */
#else
#include <sys/time.h>
#endif

#include "warnp.h"

#include "monoclock.h"

/* Determine which clock(s) to use. */
#ifndef POSIXFAIL_CLOCK_GETTIME
#ifdef CLOCK_MONOTONIC
#define USE_MONOTONIC
#endif
#ifndef POSIXFAIL_CLOCK_REALTIME
#define USE_REALTIME
#endif
#endif

/**
 * monoclock_get(tv):
 * Store the current time in ${tv}.  If CLOCK_MONOTONIC is available, use
 * that clock; if CLOCK_MONOTONIC is unavailable, use CLOCK_REALTIME (if
 * available) or gettimeofday(2).
 */
int
monoclock_get(struct timeval * tv)
{
#ifdef _MSC_VER
	/* 
	 * Windows doesn't have a monotonic clock, but we can use QueryPerformanceCounter
	 * which is high-resolution and generally monotonic.
	 */
	static LARGE_INTEGER freq = {0};
	LARGE_INTEGER count;
	
	/* Get the frequency on first call */
	if (freq.QuadPart == 0) {
		if (!QueryPerformanceFrequency(&freq)) {
			warnp("QueryPerformanceFrequency");
			goto err0;
		}
	}
	
	/* Get the current counter */
	if (!QueryPerformanceCounter(&count)) {
		warnp("QueryPerformanceCounter");
		goto err0;
	}
	
	/* Convert to timeval */
	tv->tv_sec = (long)(count.QuadPart / freq.QuadPart);
	tv->tv_usec = (long)((count.QuadPart % freq.QuadPart) * 1000000 / freq.QuadPart);
#else
#if defined(USE_MONOTONIC) || defined(USE_REALTIME)
	struct timespec tp;
#endif

#ifdef USE_MONOTONIC
	if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
		tv->tv_sec = tp.tv_sec;
		tv->tv_usec = (suseconds_t)(tp.tv_nsec / 1000);
	} else if ((errno != ENOSYS) && (errno != EINVAL)) {
		warnp("clock_gettime(CLOCK_MONOTONIC)");
		goto err0;
	} else
#endif
#ifdef USE_REALTIME
	if (clock_gettime(CLOCK_REALTIME, &tp) == 0) {
		tv->tv_sec = tp.tv_sec;
		tv->tv_usec = (suseconds_t)(tp.tv_nsec / 1000);
	} else {
		warnp("clock_gettime(CLOCK_REALTIME)");
		goto err0;
	}
#else
	if (gettimeofday(tv, NULL)) {
		warnp("gettimeofday");
		goto err0;
	}
#endif
#endif /* _MSC_VER */

	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}

/**
 * monoclock_get_cputime(tv):
 * Store in ${tv} the duration the process has been running if
 * CLOCK_PROCESS_CPUTIME_ID is available; fall back to monoclock_get()
 * otherwise.
 */
int
monoclock_get_cputime(struct timeval * tv)
{
#ifdef _MSC_VER
	FILETIME createTime, exitTime, kernelTime, userTime;
	ULARGE_INTEGER uUserTime;
	
	/* Get process times */
	if (!GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime,
	    &kernelTime, &userTime)) {
		warnp("GetProcessTimes");
		goto err0;
	}
	
	/* Convert FILETIME to timeval (user time only) */
	uUserTime.LowPart = userTime.dwLowDateTime;
	uUserTime.HighPart = userTime.dwHighDateTime;
	
	/* Windows FILETIME is in 100-nanosecond intervals since Jan 1, 1601 */
	/* Convert to seconds and microseconds */
	tv->tv_sec = (long)(uUserTime.QuadPart / 10000000ULL);
	tv->tv_usec = (long)((uUserTime.QuadPart % 10000000ULL) / 10);
#else
	/* Use CLOCK_PROCESS_CPUTIME_ID if available. */
#ifdef CLOCK_PROCESS_CPUTIME_ID
	struct timespec tp;

	if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp) == 0) {
		tv->tv_sec = tp.tv_sec;
		tv->tv_usec = (suseconds_t)(tp.tv_nsec / 1000);
	} else if ((errno != ENOSYS) && (errno != EINVAL)) {
		warnp("clock_gettime(CLOCK_PROCESS_CPUTIME_ID)");
		goto err0;
	} else
#endif
	/* Fall back to monoclock_get(). */
	if (monoclock_get(tv))
		goto err0;
#endif /* _MSC_VER */

	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}

/**
 * monoclock_getres(resd):
 * Store an upper limit on timer granularity in ${resd}.  If CLOCK_MONOTONIC
 * is available, use that clock; if CLOCK_MONOTONIC is unavailable, use
 * CLOCK_REALTIME (if available) or gettimeofday(2).  For this value to be
 * meaningful, we assume that clock_getres(x) succeeds iff clock_gettime(x)
 * succeeds.
 */
int
monoclock_getres(double * resd)
{
#ifdef _MSC_VER
	static LARGE_INTEGER freq = {0};
	
	/* Get the frequency on first call */
	if (freq.QuadPart == 0) {
		if (!QueryPerformanceFrequency(&freq)) {
			warnp("QueryPerformanceFrequency");
			goto err0;
		}
	}
	
	/* Return resolution in seconds */
	*resd = 1.0 / (double)freq.QuadPart;
#else
#if defined(USE_MONOTONIC) || defined(USE_REALTIME)
	struct timespec res;
#endif

#ifdef USE_MONOTONIC
	if (clock_getres(CLOCK_MONOTONIC, &res) == 0) {
		/* Convert clock resolution to a double. */
		*resd = (double)res.tv_sec + (double)res.tv_nsec * 0.000000001;
	} else if ((errno != ENOSYS) && (errno != EINVAL)) {
		warnp("clock_getres(CLOCK_MONOTONIC)");
		goto err0;
	} else
#endif
#ifdef USE_REALTIME
	if (clock_getres(CLOCK_REALTIME, &res) == 0) {
		/* Convert clock resolution to a double. */
		*resd = (double)res.tv_sec + (double)res.tv_nsec * 0.000000001;
	} else {
		warnp("clock_getres(CLOCK_REALTIME)");
		goto err0;
	}
#else
	/*
	 * We'll be using gettimeofday().  There is no standard way of getting
	 * the resolution of this clock, but it seems safe to assume that it
	 * ticks at a minimum rate of CLOCKS_PER_SEC Hz (even though that is
	 * defined in relation to the measurement of processor time usage, not
	 * wallclock time); on non-broken systems we'll be relying on
	 * clock_gettime and clock_getres anyway.
	 */
	*resd = 1.0 / CLOCKS_PER_SEC;
#endif
#endif /* _MSC_VER */

	/* Success! */
	return (0);

#if !defined(_MSC_VER) && (defined(USE_MONOTONIC) || defined(USE_REALTIME))
err0:
	/* Failure! */
	return (-1);
#endif

#ifdef _MSC_VER
err0:
	/* Failure! */
	return (-1);
#endif
}