From 3a122c7c1a08bff6cbff5b81f357c5c6efaad84d Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 4 Dec 2012 16:54:04 -0800 Subject: [PATCH] dekker-fences: add Dekker's critical section algorithm Now that we support fences, add a test benchmark that uses fences. This one just uses seq-cst fences. Downloaded from: http://www.justsoftwaresolutions.co.uk/threading/ Modified to avoid static construction. i.e., change: std::atomic turn(0); to std::atomic turn; ... turn = 0; And added user_main() method to launch the two threads. --- dekker-fences/.gitignore | 1 + dekker-fences/Makefile | 11 +++++ dekker-fences/dekker-fences.cc | 87 ++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 dekker-fences/.gitignore create mode 100644 dekker-fences/Makefile create mode 100644 dekker-fences/dekker-fences.cc diff --git a/dekker-fences/.gitignore b/dekker-fences/.gitignore new file mode 100644 index 0000000..560aebf --- /dev/null +++ b/dekker-fences/.gitignore @@ -0,0 +1 @@ +/dekker-fences diff --git a/dekker-fences/Makefile b/dekker-fences/Makefile new file mode 100644 index 0000000..1996599 --- /dev/null +++ b/dekker-fences/Makefile @@ -0,0 +1,11 @@ +include ../benchmarks.mk + +TESTNAME = dekker-fences + +all: $(TESTNAME) + +$(TESTNAME): $(TESTNAME).cc + $(CXX) -o $@ $< $(CPPFLAGS) $(LDFLAGS) + +clean: + rm -f $(TESTNAME) *.o diff --git a/dekker-fences/dekker-fences.cc b/dekker-fences/dekker-fences.cc new file mode 100644 index 0000000..81f6098 --- /dev/null +++ b/dekker-fences/dekker-fences.cc @@ -0,0 +1,87 @@ +/* + * Dekker's critical section algorithm, implemented with fences. + * + * URL: + * http://www.justsoftwaresolutions.co.uk/threading/ + */ + +#include +#include + +#include "librace.h" + +std::atomic flag0, flag1; +std::atomic turn; + +uint32_t var = 0; + +void p0(void *arg) +{ + flag0.store(true,std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_seq_cst); + + while (flag1.load(std::memory_order_relaxed)) + { + if (turn.load(std::memory_order_relaxed) != 0) + { + flag0.store(false,std::memory_order_relaxed); + while (turn.load(std::memory_order_relaxed) != 0) + { + } + flag0.store(true,std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_seq_cst); + } + } + std::atomic_thread_fence(std::memory_order_acquire); + + // critical section + store_32(&var, 1); + + turn.store(1,std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_release); + flag0.store(false,std::memory_order_relaxed); +} + +void p1(void *arg) +{ + flag1.store(true,std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_seq_cst); + + while (flag0.load(std::memory_order_relaxed)) + { + if (turn.load(std::memory_order_relaxed) != 1) + { + flag1.store(false,std::memory_order_relaxed); + while (turn.load(std::memory_order_relaxed) != 1) + { + } + flag1.store(true,std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_seq_cst); + } + } + std::atomic_thread_fence(std::memory_order_acquire); + + // critical section + store_32(&var, 2); + + turn.store(0,std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_release); + flag1.store(false,std::memory_order_relaxed); +} + +int user_main(int argc, char **argv) +{ + thrd_t a, b; + + flag0 = false; + flag1 = false; + turn = 0; + + thrd_create(&a, p0, NULL); + thrd_create(&b, p1, NULL); + + thrd_join(a); + thrd_join(b); + + return 0; +} -- 2.34.1