mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-22 17:55:57 +01:00
gcc hacks: busy_loop and prevent_reorder
This commit is contained in:
@@ -18452,6 +18452,13 @@ west build -b qemu_aarch64 samples/hello_world
|
||||
|
||||
The build system of that project is a bit excessive / wonky. You need an edge CMake not present in Ubuntu 18.04, which I don't want to install right now, and it uses the weird custom `west` build tool frontend.
|
||||
|
||||
== Compilers
|
||||
|
||||
Argh, compilers are boring, let's learn a bit about them.
|
||||
|
||||
* link:userland/gcc/busy_loop.c[]: https://stackoverflow.com/questions/7083482/how-to-prevent-gcc-from-optimizing-out-a-busy-wait-loop/58758133#58758133
|
||||
* link:userland/gcc/prevent_reorder.cpp[]: https://stackoverflow.com/questions/37786547/enforcing-statement-order-in-c/56865717#56865717
|
||||
|
||||
== About this repo
|
||||
|
||||
=== Supported hosts
|
||||
|
||||
29
userland/gcc/busy_loop.c
Normal file
29
userland/gcc/busy_loop.c
Normal 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);
|
||||
}
|
||||
43
userland/gcc/prevent_reorder.cpp
Normal file
43
userland/gcc/prevent_reorder.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user