From: Ivan Maidanski Date: Wed, 14 Jun 2017 09:16:00 +0000 (+0300) Subject: Add test_atomic_ops to perform minimal testing of used atomic primitives X-Git-Tag: v8.0.0~689 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=066e0ca;p=gc Add test_atomic_ops to perform minimal testing of used atomic primitives The main purpose of test_atomic_ops is to be able to check whether it is safe to use compiler atomic intrinsics (enabled by defining GC_BUILTIN_ATOMIC macro). * tests/test_atomic_ops.c: New file. * tests/tests.am [THREADS] (TESTS, check_PROGRAMS): Add test_atomic_ops. * tests/tests.am [THREADS] (test_atomic_ops_SOURCES, test_atomic_ops_LDADD): New variable. * tests/tests.am (check-without-test-driver): Run test_atomic_ops (if available). --- diff --git a/tests/test_atomic_ops.c b/tests/test_atomic_ops.c new file mode 100644 index 00000000..f7675338 --- /dev/null +++ b/tests/test_atomic_ops.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017 Ivan Maidanski + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + */ + +/* Minimal testing of atomic operations used by the BDWGC. Primary use */ +/* is to determine whether compiler atomic intrinsics can be relied on. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#if defined(GC_BUILTIN_ATOMIC) || defined(PARALLEL_MARK) \ + || (defined(GC_THREADS) && !defined(_WIN32) && !defined(_MSC_VER) \ + && !defined(__CYGWIN__) && !defined(__MINGW32__)) + +# include + +# ifdef PARALLEL_MARK +# define AO_REQUIRE_CAS +# endif + +# include "private/gc_atomic_ops.h" + +# define TA_assert(e) \ + if (!(e)) { \ + fprintf(stderr, "Assertion failure, line %d: " #e "\n", __LINE__); \ + exit(-1); \ + } + + int main(void) { + AO_t x = 13; +# ifdef AO_HAVE_test_and_set_acquire + AO_TS_t z = AO_TS_INITIALIZER; + + TA_assert(AO_test_and_set_acquire(&z) == AO_TS_CLEAR); + TA_assert(AO_test_and_set_acquire(&z) == AO_TS_SET); + AO_CLEAR(&z); +# endif + AO_compiler_barrier(); + AO_nop_full(); +# ifdef AO_HAVE_load_acquire + TA_assert(AO_load_acquire(&x) == 13); +# endif +# if defined(AO_HAVE_fetch_and_add) && defined(AO_HAVE_fetch_and_add1) + TA_assert(AO_fetch_and_add(&x, 42) == 13); + TA_assert(AO_fetch_and_add(&x, (AO_t)(-43)) == 55); + TA_assert(AO_fetch_and_add1(&x) == 12); +# endif +# if defined(AO_REQUIRE_CAS) && defined(AO_HAVE_compare_and_swap) \ + && defined(AO_HAVE_compare_and_swap_release) + TA_assert(!AO_compare_and_swap(&x, 14, 42)); + TA_assert(x == 13); + TA_assert(AO_compare_and_swap_release(&x, 13, 42)); + TA_assert(x == 42); +# else + if (*(volatile AO_t *)&x == 13) + *(volatile AO_t *)&x = 42; +# endif +# ifdef AO_HAVE_or + AO_or(&x, 66); + TA_assert(x == 106); +# endif +# ifdef AO_HAVE_store_release + AO_store_release(&x, 113); + TA_assert(x == 113); +# endif + return 0; + } + +#else + + int main(void) + { + printf("test_atomic_ops skipped\n"); + return 0; + } + +#endif diff --git a/tests/tests.am b/tests/tests.am index 90fbfe0e..b851f35a 100644 --- a/tests/tests.am +++ b/tests/tests.am @@ -70,6 +70,12 @@ endif if THREADS +TESTS += test_atomic_ops$(EXEEXT) +check_PROGRAMS += test_atomic_ops +test_atomic_ops_SOURCES = tests/test_atomic_ops.c +# Really should need only $(ATOMIC_OPS_LIBS) +test_atomic_ops_LDADD = $(test_ldadd) $(THREADDLLIBS) + TESTS += threadleaktest$(EXEEXT) check_PROGRAMS += threadleaktest threadleaktest_SOURCES = tests/thread_leak_test.c @@ -134,6 +140,7 @@ check-without-test-driver: $(TESTS) test ! -f disclaim_test$(EXEEXT) || ./disclaim_test$(EXEEXT) test ! -f initsecondarythread_test$(EXEEXT) \ || ./initsecondarythread_test$(EXEEXT) + test ! -f test_atomic_ops$(EXEEXT) || ./test_atomic_ops$(EXEEXT) test ! -f threadkey_test$(EXEEXT) || ./threadkey_test$(EXEEXT) test ! -f threadleaktest$(EXEEXT) || ./threadleaktest$(EXEEXT) test ! -f subthreadcreate_test$(EXEEXT) || ./subthreadcreate_test$(EXEEXT)