From e30f53e8a407a0d2dcbf7ee2a9a4a56bf4a2c5d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Wed, 26 Jun 2019 00:00:00 +0000 Subject: [PATCH] cpp: move atomic from cpp-cheat --- README.adoc | 3 +++ userland/cpp/atomic.cpp | 52 +++++++++++++++++++++++++++++++++++++++++ userland/cpp/empty.cpp | 2 +- 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 userland/cpp/atomic.cpp diff --git a/README.adoc b/README.adoc index 5b3018e..c4c9f16 100644 --- a/README.adoc +++ b/README.adoc @@ -11791,7 +11791,10 @@ The implementation lives under `libgomp` in the GCC tree, and is documented at: Programs under link:userland/cpp/[] are examples of link:https://en.wikipedia.org/wiki/C%2B%2B#Standardization[ISO C] programming. +* link:userland/cpp/empty.cpp[] * link:userland/cpp/hello.cpp[] +* `` 32 "Atomic operations library" +** link:userland/cpp/atomic.cpp[] === POSIX diff --git a/userland/cpp/atomic.cpp b/userland/cpp/atomic.cpp new file mode 100644 index 0000000..64a041f --- /dev/null +++ b/userland/cpp/atomic.cpp @@ -0,0 +1,52 @@ +// https://github.com/cirosantilli/linux-kernel-module-cheat#atomic +// +// More restricted than mutex as it can only protect a few operations on integers. +// +// But if that is the use case, may be more efficient. +// +// On GCC 4.8 x86-64, using atomic is a huge peformance improvement +// over the same program with mutexes (5x). + +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +std::atomic_ulong my_atomic_ulong(0); +unsigned long my_non_atomic_ulong = 0; +size_t niters; + +void threadMain() { + for (size_t i = 0; i < niters; ++i) { + my_atomic_ulong++; + my_non_atomic_ulong++; + } +} +#endif + +int main(int argc, char **argv) { +#if __cplusplus >= 201103L + size_t nthreads; + if (argc > 1) { + nthreads = std::stoull(argv[1], NULL, 0); + } else { + nthreads = 2; + } + if (argc > 2) { + niters = std::stoull(argv[2], NULL, 0); + } else { + niters = 1000; + } + std::vector threads(nthreads); + for (size_t i = 0; i < nthreads; ++i) + threads[i] = std::thread(threadMain); + for (size_t i = 0; i < nthreads; ++i) + threads[i].join(); + assert(my_atomic_ulong.load() == nthreads * niters); + // Same as above through `operator T`. + assert(my_atomic_ulong == nthreads * niters); + std::cout << my_non_atomic_ulong << std::endl; +#endif +} diff --git a/userland/cpp/empty.cpp b/userland/cpp/empty.cpp index cbd248e..71630b0 100644 --- a/userland/cpp/empty.cpp +++ b/userland/cpp/empty.cpp @@ -1,4 +1,4 @@ // Sanity checking low level stuff, initially inspired by baremetal. -// https://github.com/cirosantilli/linux-kernel-module-cheat#baremetal-cpp +// https://github.com/cirosantilli/linux-kernel-module-cheat#cpp int main() {}