From 37ef4c441cba96f3e4da74f709d22442f9bf5b25 Mon Sep 17 00:00:00 2001 From: Chris Cotter Date: Fri, 13 Sep 2024 22:59:03 -0400 Subject: [PATCH] Add relacy tests into stdexec source tree --- test/rrd/Makefile | 59 ++++++++++++++++++++++++++++++++++++++++ test/rrd/README.md | 42 ++++++++++++++++++++++++++++ test/rrd/async_scope.cpp | 51 ++++++++++++++++++++++++++++++++++ test/rrd/split.cpp | 45 ++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 test/rrd/Makefile create mode 100644 test/rrd/README.md create mode 100644 test/rrd/async_scope.cpp create mode 100644 test/rrd/split.cpp diff --git a/test/rrd/Makefile b/test/rrd/Makefile new file mode 100644 index 000000000..347e40aeb --- /dev/null +++ b/test/rrd/Makefile @@ -0,0 +1,59 @@ +# User-customizable variables: +CXX ?= c++ +CXX_STD ?= c++20 +CXXFLAGS ?= -I relacy -I relacy/relacy/fakestd -O1 -std=$(CXX_STD) -I ../../include -I ../../test -g +DEPFLAGS ?= -MD -MF $(@).d -MP -MT $(@) +build_dir = build + +.SECONDARY: + +test_programs = split async_scope + +test_exe_files = $(foreach name,$(test_programs),$(build_dir)/$(name)) + +exe_files = $(test_exe_files) +o_files = $(exe_files:=.cpp.o) + +ansi_term_csi = [ +ansi_term_bold = $(ansi_term_csi)1m +ansi_term_green = $(ansi_term_csi)32m +ansi_term_red = $(ansi_term_csi)31m +ansi_term_reset = $(ansi_term_csi)m + +COMPILE.cpp = $(CXX) $(DEPFLAGS) $(CXXFLAGS) -c +LINK.cpp = $(CXX) $(CXXFLAGS) + +.PHONY: all +all: tests + +.PHONY: tests +tests: $(test_exe_files) + +$(build_dir)/%.check-result: $(build_dir)/% always-run + @ \ + printf '%s%s ...%s\n' $(ansi_term_bold) $(*) $(ansi_term_reset) >&2; \ + $(<); \ + status="$${?}"; \ + printf %d "$${status}" >$(@); \ + if [ "$${status}" -eq 0 ]; then \ + printf '%s%s %s%s\n' $(ansi_term_green) $(*) OK $(ansi_term_reset); \ + else \ + printf '%s%s %s%s\n' $(ansi_term_red) $(*) FAIL $(ansi_term_reset); \ + fi >&2; \ + exit "$${status}" + +$(build_dir)/%: $(build_dir)/%.cpp.o + $(LINK.cpp) $(^) -o $(@) + +$(build_dir)/%.cpp.o: %.cpp + @mkdir -p $(dir $(@)) + $(COMPILE.cpp) -o $(@) $(<) + +.PHONY: clean +clean: + rm -fr -- $(build_dir)/ + +.PHONY: always-run +always-run: + +-include $(o_files:=.d) diff --git a/test/rrd/README.md b/test/rrd/README.md new file mode 100644 index 000000000..1701aae49 --- /dev/null +++ b/test/rrd/README.md @@ -0,0 +1,42 @@ +## Relacy tests + +[Relacy (RRD)](https://www.1024cores.net/home/relacy-race-detector/rrd-introduction) +is a data race detector. It replaces the OS scheduler with an scheduler that +explores many different thread interleavings, and logs detected races or assertion +failures. Relacy can also simulate relaxed hardware by simulating old values of a +variable as allowed by the C++11 memory model. + +Relacy requires a specialized build. In particular, it is a header only library that +replaces the standard library and pthread APIs at compile time. Since it places some +standard library includes, writing new tests may require working around certain +limitations in terms of what the replacement headers and accompanying runtime can +support. For example, Relacy's atomic replacements cannot support `++x`, so the +stdexec library could needs to use `x.fetch_add(1)` to be compatible with Relacy. + +## Instructions + +Run the following commands from within this directory (`./tests/rrd`). + +``` +# TODO: Merge patches into upstream Relacy @ dvyukov's version +git clone -b stdexec https://github.com/ccotter/relacy +CXX=g++-11 make -j 4 +./build/split +``` + +## Recommended use + +The Relacy tests can be manually built and executed. New tests can be written for +new algorithms, or new use cases in the stdexec library. + +At this time, integrating the tests into CI is not yet recommended. If we can figure +out a more stable build on all environments/compilers, we should revisit this. + +## Supported platforms + +The stdexec Relacy tests have been verified to build and run on + * Linux based GCC+11 with libstdc++ (`x86_64`) + * Mac with Apple Clang 15 with libc++ (`x86_64`) + +G++12 and newer are known to have issues that could be addressed with patches +to Relacy. diff --git a/test/rrd/async_scope.cpp b/test/rrd/async_scope.cpp new file mode 100644 index 000000000..8dc8d55fc --- /dev/null +++ b/test/rrd/async_scope.cpp @@ -0,0 +1,51 @@ +#include "../../relacy/relacy_std.hpp" +#include "../../relacy/relacy_cli.hpp" + +#include +#include +#include +#include +#include + +#include +#include +#include + +using rl::nvar; +using rl::nvolatile; +using rl::mutex; + +namespace ex = stdexec; +using exec::async_scope; + +struct async_scope_bug : rl::test_suite +{ + static size_t const dynamic_thread_count = 2; + + void thread(unsigned) + { + exec::static_thread_pool ctx{1}; + + ex::scheduler auto sch = ctx.get_scheduler(); + + exec::async_scope scope; + std::atomic_bool produced{false}; + ex::sender auto begin = ex::schedule(sch); + { + ex::sender auto ftr = scope.spawn_future(begin | stdexec::then([&]() { produced.store(true); })); + (void) ftr; + } + stdexec::sync_wait(scope.on_empty() | stdexec::then([&]() { + RL_ASSERT(produced.load()); + })); + } +}; + +int main() +{ + rl::test_params p; + p.iteration_count = 50000; + p.execution_depth_limit = 10000; + rl::simulate(p); + return 0; +} diff --git a/test/rrd/split.cpp b/test/rrd/split.cpp new file mode 100644 index 000000000..330ebb39c --- /dev/null +++ b/test/rrd/split.cpp @@ -0,0 +1,45 @@ +#include "../../relacy/relacy_std.hpp" +#include "../../relacy/relacy_cli.hpp" + +#include +#include +#include +#include + +#include +#include +#include + +using rl::nvar; +using rl::nvolatile; +using rl::mutex; + +namespace ex = stdexec; +using exec::async_scope; + +struct split_bug : rl::test_suite +{ + static size_t const dynamic_thread_count = 2; + + void thread(unsigned) + { + exec::static_thread_pool pool{1}; + auto split = ex::schedule(pool.get_scheduler()) // + | ex::then([] { + return 42; + }) + | ex::split(); + + auto [val] = ex::sync_wait(split).value(); + RL_ASSERT(val == 42); + } +}; + +int main() +{ + rl::test_params p; + p.iteration_count = 50000; + p.execution_depth_limit = 10000; + rl::simulate(p); + return 0; +}