X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=hs-boehmgc.git;a=blobdiff_plain;f=gc-7.2%2Flibatomic_ops%2Ftests%2Ftest_atomic.c;fp=gc-7.2%2Flibatomic_ops%2Ftests%2Ftest_atomic.c;h=e35402470e7b3cbcd2a6f578c1af732753393335;hp=0000000000000000000000000000000000000000;hb=324587ba93dc77f37406d41fd2a20d0e0d94fb1d;hpb=2a4ea609491b225a1ceb06da70396e93916f137a diff --git a/gc-7.2/libatomic_ops/tests/test_atomic.c b/gc-7.2/libatomic_ops/tests/test_atomic.c new file mode 100644 index 0000000..e354024 --- /dev/null +++ b/gc-7.2/libatomic_ops/tests/test_atomic.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. + * Original Author: Hans Boehm + * + * This file may be redistributed and/or modified under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2, or (at your option) any later version. + * + * It is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License in the + * file doc/COPYING for more details. + */ + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + + +#include "run_parallel.inc" + +#include "test_atomic_include.h" + +#ifdef AO_USE_PTHREAD_DEFS +# define NITERS 100000 +#else +# define NITERS 10000000 +#endif + +void * add1sub1_thr(void * id); +int add1sub1_test(void); +void * acqrel_thr(void *id); +int acqrel_test(void); +void * test_and_set_thr(void * id); +int test_and_set_test(void); + +#if defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1) + +AO_t counter = 0; + +void * add1sub1_thr(void * id) +{ + int me = (int)(AO_PTRDIFF_T)id; + + int i; + + for (i = 0; i < NITERS; ++i) + if (me & 1) + AO_fetch_and_sub1(&counter); + else + AO_fetch_and_add1(&counter); + + return 0; +} + +int add1sub1_test(void) +{ + return counter == 0; +} + +#endif /* defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1) */ + +#if defined(AO_HAVE_store_release_write) && defined(AO_HAVE_load_acquire_read) + +/* Invariant: counter1 >= counter2 */ +AO_t counter1 = 0; +AO_t counter2 = 0; + +void * acqrel_thr(void *id) +{ + int me = (int)(AO_PTRDIFF_T)id; + + int i; + + for (i = 0; i < NITERS; ++i) + if (me & 1) + { + AO_t my_counter1; + if (me != 1) + fprintf(stderr, "acqrel test: too many threads\n"); + my_counter1 = AO_load(&counter1); + AO_store(&counter1, my_counter1 + 1); + AO_store_release_write(&counter2, my_counter1 + 1); + } + else + { + AO_t my_counter1a, my_counter2a; + AO_t my_counter1b, my_counter2b; + + my_counter2a = AO_load_acquire_read(&counter2); + my_counter1a = AO_load(&counter1); + /* Redo this, to make sure that the second load of counter1 */ + /* is not viewed as a common subexpression. */ + my_counter2b = AO_load_acquire_read(&counter2); + my_counter1b = AO_load(&counter1); + if (my_counter1a < my_counter2a) + { + fprintf(stderr, "Saw release store out of order: %lu < %lu\n", + (unsigned long)my_counter1a, (unsigned long)my_counter2a); + abort(); + } + if (my_counter1b < my_counter2b) + { + fprintf(stderr, + "Saw release store out of order (bad CSE?): %lu < %lu\n", + (unsigned long)my_counter1b, (unsigned long)my_counter2b); + abort(); + } + } + + return 0; +} + +int acqrel_test(void) +{ + return counter1 == NITERS && counter2 == NITERS; +} + +#endif /* AO_HAVE_store_release_write && AO_HAVE_load_acquire_read */ + +#if defined(AO_HAVE_test_and_set_acquire) + +AO_TS_T lock = AO_TS_INITIALIZER; + +unsigned long locked_counter; +volatile unsigned long junk = 13; + +void * test_and_set_thr(void * id) +{ + unsigned long i; + + for (i = 0; i < NITERS/10; ++i) + { + while (AO_test_and_set_acquire(&lock) != AO_TS_CLEAR); + ++locked_counter; + if (locked_counter != 1) + { + fprintf(stderr, "Test and set failure 1, counter = %ld\n", + locked_counter); + abort(); + } + locked_counter *= 2; + locked_counter -= 1; + locked_counter *= 5; + locked_counter -= 4; + if (locked_counter != 1) + { + fprintf(stderr, "Test and set failure 2, counter = %ld\n", + locked_counter); + abort(); + } + --locked_counter; + AO_CLEAR(&lock); + /* Spend a bit of time outside the lock. */ + junk *= 17; + junk *= 17; + } + return 0; +} + +int test_and_set_test(void) +{ + return locked_counter == 0; +} + +#endif /* defined(AO_HAVE_test_and_set_acquire) */ + +int main(void) +{ + test_atomic(); + test_atomic_acquire(); + test_atomic_release(); + test_atomic_read(); + test_atomic_write(); + test_atomic_full(); + test_atomic_release_write(); + test_atomic_acquire_read(); +# if defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1) + run_parallel(4, add1sub1_thr, add1sub1_test, "add1/sub1"); +# endif +# if defined(AO_HAVE_store_release_write) && defined(AO_HAVE_load_acquire_read) + run_parallel(3, acqrel_thr, acqrel_test, + "store_release_write/load_acquire_read"); +# endif +# if defined(AO_HAVE_test_and_set_acquire) + run_parallel(5, test_and_set_thr, test_and_set_test, + "test_and_set"); +# endif + return 0; +}