Skip to content

Instantly share code, notes, and snippets.

@RedBeard0531
Created March 14, 2019 18:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RedBeard0531/b8b0a7b41e7bdaddbbddb9d226df2452 to your computer and use it in GitHub Desktop.
Save RedBeard0531/b8b0a7b41e7bdaddbbddb9d226df2452 to your computer and use it in GitHub Desktop.
Example of non-sequential consistency
// {{{
// vim: set foldmethod=marker:
// g++ -O3 -pthread sc.cpp && ./a.out
#include <cstdio>
#include <thread>
#include <atomic>
using namespace std;
constexpr auto load_order = memory_order_acquire;
constexpr auto store_order = memory_order_release;
constexpr bool run_until_boom = false;
// {{{
constexpr int alignment = false ? 4 : 1024*1024;
constexpr long long loops = 10;
constexpr int nThreads = 3; // Includes checker
alignas(alignment) atomic<int> a {0};
alignas(alignment) atomic<int> b {0};
alignas(alignment) atomic<int> barrier1 {0};
alignas(alignment) atomic<int> barrier2 {0};
alignas(alignment) atomic<int> barrier3 {0};
alignas(alignment) atomic<int> r1 {0};
alignas(alignment) atomic<int> r2 {0};
int load(atomic<int>& i) {
asm volatile("":::"memory");
return i.load(load_order);
asm volatile("":::"memory");
}
void store(atomic<int>& i, int val) {
asm volatile("":::"memory");
i.store(val, store_order);
asm volatile("":::"memory");
}
inline void arrive_and_wait(atomic<int>& barrier) {
barrier += 1;
while (barrier.load() < nThreads) {
}
}
template <typename F>
void run(F&& f) {
thread([f = std::forward<F>(f)] {
while(true){
arrive_and_wait(barrier1);
f();
arrive_and_wait(barrier2);
arrive_and_wait(barrier3);
}
}).detach();
}
template <typename F>
auto checker(F&& f) {
arrive_and_wait(barrier1);
for (long long i = 0; i < loops || run_until_boom; i++) {
arrive_and_wait(barrier2);
barrier1 = 0;
const bool test = f();
if (!run_until_boom) {
printf("r1=%d r2=%d %s\n", r1.load(), r2.load(), test ? "!!!" : "");
} else if (test) {
printf("boom after %lld successes\n", i);
return;
} else if (i && i % 1'000'000 == 0) {
printf("%lldM successes\n", i/1'000'000);
}
// Reset state
a = 0;
b = 0;
arrive_and_wait(barrier3);
barrier2 = 0;
arrive_and_wait(barrier1);
barrier3 = 0;
}
}
// }}}
// }}}
int main() {
run([] {
store(a, 1);
r1 = load(b);
});
run([] {
store(b, 1);
r2 = load(a);
});
checker([] {
return r1 == 0 && r2 == 0;
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment