Skip to content

Instantly share code, notes, and snippets.

@monoid
Created August 17, 2019 18:04
Show Gist options
  • Select an option

  • Save monoid/d07e5b8043a36795030a7463bd9ba5ad to your computer and use it in GitHub Desktop.

Select an option

Save monoid/d07e5b8043a36795030a7463bd9ba5ad to your computer and use it in GitHub Desktop.
ARM imporper atomic example
#include <atomic>
#include <cstdint>
#include <iostream>
#include <thread>
/* Improper locking (reproducible only with clang)
$ time ./a.out
1000000000 1000000000
real 1m19.583s
user 2m35.465s
sys 0m0.030s
*/
const auto LOCK_MEM_ORDER = std::memory_order_relaxed;
const auto UNLOCK_MEM_ORDER = std::memory_order_relaxed;
/* Proper locking:
$ time ./a.out
2000000000 2000000000
real 2m9.286s
user 3m56.303s
sys 0m0.011s
*/
// const auto LOCK_MEM_ORDER = std::memory_order_acquire;
// const auto UNLOCK_MEM_ORDER = std::memory_order_release;
using LockUnderlyingType = int;
struct Data {
std::atomic<LockUnderlyingType> lock_;
uint32_t var1 = 0;
uint32_t var2 = 0;
void increment(uint32_t count) {
for (uint32_t i = 0; i < count; ++i) {
LockUnderlyingType expected;
do {
expected = 0;
} while (!lock_.compare_exchange_strong(expected, 1, LOCK_MEM_ORDER));
uint32_t v1 = var1;
uint32_t v2 = var2;
var2 = v2 + 1;
var1 = v1 + 1;
lock_.store(0, UNLOCK_MEM_ORDER);
}
}
};
int main() {
Data v;
const auto count = 1000000000;
auto t1 = std::thread([&v]() { v.increment(count); });
auto t2 = std::thread([&v]() { v.increment(count); });
t1.join();
t2.join();
std::cout << v.var1 << ' ' << v.var2 << std::endl;
}
@monoid
Copy link
Author

monoid commented Sep 7, 2021

clang++ -std=c++11 -O3 ./arm_race.cpp

MacOS M1:

1000000000 1000000000

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment