forked from crocs-muni/ECTester
-
Notifications
You must be signed in to change notification settings - Fork 0
/
c_timing.c
254 lines (202 loc) · 6.52 KB
/
c_timing.c
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
246
247
248
249
250
251
252
253
254
#include "c_timing.h"
#if __linux || __posix
#include <unistd.h>
#include <time.h>
#include <string.h>
static unsigned long long tsc_start = 0;
static unsigned long long tsc_end = 0;
static unsigned long long tsc_partial = 0;
static const char *rdtsc_unit = "instr";
static inline unsigned long long rdtsc(void) {
unsigned long long int x;
__asm__ volatile ("rdtsc" : "=A" (x));
return x;
}
static jlong rdtsc_timing_resolution() {
return 1;
}
static void rdtsc_timing_start() {
tsc_partial = 0;
tsc_start = rdtsc();
}
static void rdtsc_timing_pause() {
tsc_end = rdtsc();
tsc_partial += tsc_end - tsc_start;
}
static void rdtsc_timing_restart() {
tsc_start = rdtsc();
}
static void rdtsc_timing_stop() {
tsc_end = rdtsc();
}
static jlong rdtsc_timing_last() {
jlong res = (jlong) ((tsc_end - tsc_start) + tsc_partial);
if (res < 0) {
return 0;
} else {
return res;
}
}
static struct timespec start = {0};
static struct timespec end = {0};
static jlong partial = 0;
static clockid_t clk_id = CLOCK_MONOTONIC_RAW;
static const char *clock_unit = "nano";
static jlong clock_timing_resolution() {
struct timespec timeval;
clock_getres(clk_id, &timeval);
return timeval.tv_nsec;
}
static void clock_timing_start() {
partial = 0;
clock_gettime(clk_id, &start);
}
static void clock_timing_pause() {
clock_gettime(clk_id, &end);
partial += (end.tv_sec - start.tv_sec) * 1000000000 + (end.tv_nsec - start.tv_nsec);
}
static void clock_timing_restart() {
clock_gettime(clk_id, (struct timespec *)&start);
}
static void clock_timing_stop() {
clock_gettime(clk_id, (struct timespec *)&end);
}
static jlong clock_timing_last() {
jlong res = (end.tv_sec - start.tv_sec) * 1000000000 + (end.tv_nsec - start.tv_nsec) + partial;
if (res < 0) {
return 0;
} else {
return res;
}
}
static jlong (*func_timing_resolution)() = &clock_timing_resolution;
static void (*func_timing_start)() = &clock_timing_start;
static void (*func_timing_pause)() = &clock_timing_pause;
static void (*func_timing_restart)() = &clock_timing_restart;
static void (*func_timing_stop)() = &clock_timing_stop;
static jlong (*func_timing_last)() = &clock_timing_last;
static const char *unit = "nano";
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_getNativeTimingSupport(JNIEnv *env, jobject self) {
jclass set_class = (*env)->FindClass(env, "java/util/TreeSet");
jmethodID set_ctr = (*env)->GetMethodID(env, set_class, "<init>", "()V");
jmethodID set_add = (*env)->GetMethodID(env, set_class, "add", "(Ljava/lang/Object;)Z");
jobject result = (*env)->NewObject(env, set_class, set_ctr);
(*env)->CallBooleanMethod(env, result, set_add, (*env)->NewStringUTF(env, "rdtsc"));
(*env)->CallBooleanMethod(env, result, set_add, (*env)->NewStringUTF(env, "monotonic"));
(*env)->CallBooleanMethod(env, result, set_add, (*env)->NewStringUTF(env, "monotonic-raw"));
(*env)->CallBooleanMethod(env, result, set_add, (*env)->NewStringUTF(env, "cputime-processor"));
(*env)->CallBooleanMethod(env, result, set_add, (*env)->NewStringUTF(env, "cputime-thread"));
return result;
}
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_setNativeTimingType(JNIEnv *env, jobject self, jstring type) {
const char *type_data = (*env)->GetStringUTFChars(env, type, NULL);
if (strcmp(type_data, "rdtsc") == 0) {
func_timing_resolution = &rdtsc_timing_resolution;
func_timing_start = &rdtsc_timing_start;
func_timing_pause = &rdtsc_timing_pause;
func_timing_restart = &rdtsc_timing_restart;
func_timing_stop = &rdtsc_timing_stop;
func_timing_last = &rdtsc_timing_last;
unit = rdtsc_unit;
return JNI_TRUE;
} else {
if (strcmp(type_data, "monotonic") == 0) {
clk_id = CLOCK_MONOTONIC;
} else if (strcmp(type_data, "monotonic-raw") == 0) {
clk_id = CLOCK_MONOTONIC_RAW;
} else if (strcmp(type_data, "cputime-processor") == 0) {
clk_id = CLOCK_PROCESS_CPUTIME_ID;
} else if (strcmp(type_data, "cputime-thread") == 0) {
clk_id = CLOCK_THREAD_CPUTIME_ID;
} else {
return JNI_FALSE;
}
func_timing_resolution = &clock_timing_resolution;
func_timing_start = &clock_timing_start;
func_timing_pause = &clock_timing_pause;
func_timing_restart = &clock_timing_restart;
func_timing_stop = &clock_timing_stop;
func_timing_last = &clock_timing_last;
unit = clock_unit;
return JNI_TRUE;
}
}
JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_getNativeTimingResolution(JNIEnv *env, jobject self) {
return native_timing_resolution();
}
JNIEXPORT jstring JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_getNativeTimingUnit(JNIEnv *env, jobject self) {
return (*env)->NewStringUTF(env, unit);
}
JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_getLastNativeTiming(JNIEnv *env, jobject self) {
return native_timing_last();
}
jlong native_timing_resolution() {
return func_timing_resolution();
}
void native_timing_start() {
func_timing_start();
}
void native_timing_pause() {
func_timing_pause();
}
void native_timing_restart() {
func_timing_restart();
}
void native_timing_stop() {
func_timing_stop();
}
jlong native_timing_last() {
return func_timing_last();
}
#elif defined(__WIN32__) || defined(_MSC_VER)
#include <Windows.h>
#error TODO
static LARGE_INTEGER start = {0};
static LARGE_INTEGER end = {0};
static jlong partial = 0;
jboolean native_timing_supported() {
return JNI_TRUE;
}
jlong native_timing_resolution() {
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
return 1000000000 / freq.QuadPart;
}
void native_timing_start() {
partial = 0;
QueryPerformanceCounter(&start);
}
void native_timing_pause() {
QueryPerformanceCounter(&end);
partial = (end.QuadPart - start.QuadPart) * native_timing_resolution();
}
void native_timing_restart() {
QueryPerformanceCounter(&start);
}
void native_timing_stop() {
QueryPerformanceCounter(&end);
}
jlong native_timing_last() {
jlong res = (end.QuadPart - start.QuadPart) * native_timing_resolution() + partial;
if (res < 0) {
return 0;
} else {
return res;
}
}
#else
#error TODO
jboolean native_timing_supported() {
return JNI_FALSE;
}
jlong native_timing_resolution() {
return 0;
}
void native_timing_start() {}
void native_timing_pause() {}
void native_timing_restart() {}
void native_timing_stop() {}
jlong native_timing_last() {
return 0;
}
#endif