-
Notifications
You must be signed in to change notification settings - Fork 2
/
cacheutils.h
143 lines (112 loc) · 3.09 KB
/
cacheutils.h
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
#ifndef _CACHEUTILS_H_
#define _CACHEUTILS_H_
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
/* ============================================================
* User configuration
* ============================================================ */
size_t CACHE_MISS = 150;
#define USE_RDTSC_BEGIN_END 0
#define USE_RDTSCP 1
/* ============================================================
* User configuration End
* ============================================================ */
// ---------------------------------------------------------------------------
uint64_t rdtsc() {
uint64_t a, d;
asm volatile("mfence");
#if USE_RDTSCP
asm volatile("rdtscp" : "=a"(a), "=d"(d) :: "rcx");
#else
asm volatile("rdtsc" : "=a"(a), "=d"(d));
#endif
a = (d << 32) | a;
asm volatile("mfence");
return a;
}
// ---------------------------------------------------------------------------
void flush(void *p) { asm volatile("clflush 0(%0)\n" : : "c"(p) : "rax"); }
// ---------------------------------------------------------------------------
void maccess(void *p) { asm volatile("movq (%0), %%rax\n" : : "c"(p) : "rax"); }
// ---------------------------------------------------------------------------
void mfence() { asm volatile("mfence"); }
// --------------------------------------------------------------------------
void delayloop(uint32_t cycles) {
uint64_t start = rdtsc();
while ((rdtsc()-start) < cycles)
;
}
// ---------------------------------------------------------------------------
int flush_reload(void *ptr) {
uint64_t start = 0, end = 0;
#if USE_RDTSC_BEGIN_END
start = rdtsc_begin();
#else
start = rdtsc();
#endif
maccess(ptr);
#if USE_RDTSC_BEGIN_END
end = rdtsc_end();
#else
end = rdtsc();
#endif
mfence();
flush(ptr);
if (end - start < CACHE_MISS) {
return 1;
}
return 0;
}
// ---------------------------------------------------------------------------
int flush_reload_t(void *ptr) {
uint64_t start = 0, end = 0;
#if USE_RDTSC_BEGIN_END
start = rdtsc_begin();
#else
start = rdtsc();
#endif
maccess(ptr);
#if USE_RDTSC_BEGIN_END
end = rdtsc_end();
#else
end = rdtsc();
#endif
mfence();
flush(ptr);
return (int)(end - start);
}
// ---------------------------------------------------------------------------
int reload_t(void *ptr) {
uint64_t start = 0, end = 0;
#if USE_RDTSC_BEGIN_END
start = rdtsc_begin();
#else
start = rdtsc();
#endif
maccess(ptr);
#if USE_RDTSC_BEGIN_END
end = rdtsc_end();
#else
end = rdtsc();
#endif
mfence();
return (int)(end - start);
}
// ---------------------------------------------------------------------------
size_t detect_flush_reload_threshold() {
size_t reload_time = 0, flush_reload_time = 0, i, count = 1000000;
size_t dummy[16];
size_t *ptr = dummy + 8;
maccess(ptr);
for (i = 0; i < count; i++) {
reload_time += reload_t(ptr);
}
for (i = 0; i < count; i++) {
flush_reload_time += flush_reload_t(ptr);
}
reload_time /= count;
flush_reload_time /= count;
return (flush_reload_time + reload_time * 2) / 3;
}
#endif