gcc hacks: busy_loop and prevent_reorder

This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-11-08 00:00:00 +00:00
parent 6936bd6ba9
commit a06672a20d
3 changed files with 79 additions and 0 deletions

29
userland/gcc/busy_loop.c Normal file
View File

@@ -0,0 +1,29 @@
/* https://cirosantilli.com/linux-kernel-module-cheat#compilers */
#include <stdlib.h>
void __attribute__ ((noinline)) busy_loop(
unsigned long long max,
unsigned long long max2
) {
for (unsigned i = 0; i < max; i++) {
for (unsigned j = 0; j < max2; j++) {
__asm__ __volatile__ ("" : "+g" (j), "+g" (j) : :);
}
}
}
int main(int argc, char **argv) {
unsigned long long max, max2;
if (argc > 1) {
max = strtoll(argv[1], NULL, 0);
} else {
max = 1;
}
if (argc > 2) {
max2 = strtoll(argv[2], NULL, 0);
} else {
max2 = 1;
}
busy_loop(max, max2);
}

View File

@@ -0,0 +1,43 @@
/* https://cirosantilli.com/linux-kernel-module-cheat#compilers */
#include <chrono>
#include <iostream>
#include <string>
// noinline ensures that the ::now() cannot be split from the __asm__
template <class T>
__attribute__((noinline)) auto get_clock(T& value) {
// Make the compiler think we actually use / modify the value.
// It can't "see" what is going on inside the assembly string.
__asm__ __volatile__ ("" : "+g" (value));
return std::chrono::high_resolution_clock::now();
}
template <class T>
static T foo(T niters) {
T result = 42;
for (T i = 0; i < niters; ++i) {
result = (result * result) - (3 * result) + 1;
}
return result;
}
int main(int argc, char **argv) {
unsigned long long input;
if (argc > 1) {
input = std::stoull(argv[1], NULL, 0);
} else {
input = 1;
}
// Must come before because it could modify input
// which is passed as a reference.
auto t1 = get_clock(input);
auto output = foo(input);
// Must come after as it could use the output.
auto t2 = get_clock(output);
std::cout << "output " << output << std::endl;
std::cout << "time (ns) "
<< std::chrono::duration_cast<std::chrono::nanoseconds>(t2 - t1).count()
<< std::endl;
}