-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcycles_count.c
134 lines (103 loc) · 2.63 KB
/
cycles_count.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
/*
* SPDX-License-Identifier: LGPL-2.1
*
* Copyright (C) 2020 tnrdd
*/
#include "cycles_count.h"
static inline void count_cycles(uint64_t *cycles)
{
uint32_t i;
uint64_t start_low;
uint64_t start_high;
uint64_t end_low;
uint64_t end_high;
unsigned long flags;
asm volatile ("rdtscp\n\t"
"lfence\n\t"
: "=d" (start_high), "=a" (start_low)
:
: "%rbx", "%rcx");
asm volatile ("rdtscp\n\t"
"lfence\n\t"
: "=d" (end_high), "=a" (end_low)
:
: "%rbx", "%rcx");
for (i = 0; i < REPETITION_COUNT; i++) {
preempt_disable();
raw_local_irq_save(flags);
asm volatile ("rdtscp\n\t"
"lfence\n\t"
: "=d" (start_high), "=a" (start_low)
:
: "%rbx", "%rcx");
/*
**************************************************
*Function to benchmark here
**************************************************
*/
asm volatile ("rdtscp\n\t"
"lfence\n\t"
: "=d" (end_high), "=a" (end_low)
:
: "%rbx", "%rcx");
raw_local_irq_restore(flags);
preempt_enable();
cycles[i] = ((end_high - start_high) << HIGH_HALF_BITS) + (end_low - start_low);
}
}
uint64_t calc_mean(uint64_t *cycles, uint32_t occurrencies)
{
uint32_t i;
uint64_t sum;
sum = 0;
for (i = 0; i < occurrencies; i++) {
sum += cycles[i];
}
return sum / occurrencies;
}
uint64_t calc_variance(uint64_t *cycles, uint64_t mean, uint32_t occurrencies)
{
uint32_t i;
uint64_t variance;
variance = 0;
for (i = 0; i < occurrencies; i++) {
variance += (cycles[i] - mean) * (cycles[i] - mean);
}
variance /= (occurrencies - 1);
return variance;
}
static int __init cycles_count_start(void)
{
uint32_t i;
struct statistics stats = {0};
uint64_t *cycles;
cycles = kmalloc(REPETITION_COUNT * sizeof(uint64_t), GFP_KERNEL);
if (!cycles) {
return -1;
}
count_cycles(cycles);
stats.min = cycles[0];
stats.max = cycles[0];
for (i = 1; i < REPETITION_COUNT; i++) {
if (cycles[i] < stats.min) {
stats.min = cycles[i];
} else if (cycles[i] > stats.max) {
stats.max = cycles[i];
}
}
stats.mean = calc_mean(cycles, REPETITION_COUNT);
stats.variance = calc_variance(cycles, stats.mean, REPETITION_COUNT);
printk("min: %llu cycles\n", stats.min);
printk("max: %llu cycles\n", stats.max);
printk("mean: %llu cycles\n", stats.mean);
printk("variance: %llu cycles\n", stats.variance);
kfree(cycles);
return 0;
}
static void __exit cycles_count_end(void)
{
printk("Exited\n");
}
module_init(cycles_count_start);
module_exit(cycles_count_end);
MODULE_LICENSE("GPL v2");