implemented Setup.hs to build boehm cpp libs and install them;
[hs-boehmgc.git] / gc-7.2 / libatomic_ops / tests / test_atomic.c
1 /*
2  * Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
3  * Original Author: Hans Boehm
4  *
5  * This file may be redistributed and/or modified under the
6  * terms of the GNU General Public License as published by the Free Software
7  * Foundation; either version 2, or (at your option) any later version.
8  *
9  * It is distributed in the hope that it will be useful, but WITHOUT ANY
10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License in the
12  * file doc/COPYING for more details.
13  */
14
15 #if defined(HAVE_CONFIG_H)
16 # include "config.h"
17 #endif
18
19
20 #include "run_parallel.inc"
21
22 #include "test_atomic_include.h"
23
24 #ifdef AO_USE_PTHREAD_DEFS
25 # define NITERS 100000
26 #else
27 # define NITERS 10000000
28 #endif
29
30 void * add1sub1_thr(void * id);
31 int add1sub1_test(void);
32 void * acqrel_thr(void *id);
33 int acqrel_test(void);
34 void * test_and_set_thr(void * id);
35 int test_and_set_test(void);
36
37 #if defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1)
38
39 AO_t counter = 0;
40
41 void * add1sub1_thr(void * id)
42 {
43   int me = (int)(AO_PTRDIFF_T)id;
44
45   int i;
46
47   for (i = 0; i < NITERS; ++i)
48     if (me & 1)
49       AO_fetch_and_sub1(&counter);
50     else
51       AO_fetch_and_add1(&counter);
52
53   return 0;
54 }
55
56 int add1sub1_test(void)
57 {
58   return counter == 0;
59 }
60
61 #endif /* defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1) */
62
63 #if defined(AO_HAVE_store_release_write) && defined(AO_HAVE_load_acquire_read)
64
65 /* Invariant: counter1 >= counter2 */
66 AO_t counter1 = 0;
67 AO_t counter2 = 0;
68
69 void * acqrel_thr(void *id)
70 {
71   int me = (int)(AO_PTRDIFF_T)id;
72
73   int i;
74
75   for (i = 0; i < NITERS; ++i)
76     if (me & 1)
77       {
78         AO_t my_counter1;
79     if (me != 1)
80       fprintf(stderr, "acqrel test: too many threads\n");
81     my_counter1 = AO_load(&counter1);
82     AO_store(&counter1, my_counter1 + 1);
83     AO_store_release_write(&counter2, my_counter1 + 1);
84       }
85     else
86       {
87     AO_t my_counter1a, my_counter2a;
88     AO_t my_counter1b, my_counter2b;
89
90     my_counter2a = AO_load_acquire_read(&counter2);
91     my_counter1a = AO_load(&counter1);
92     /* Redo this, to make sure that the second load of counter1 */
93     /* is not viewed as a common subexpression.         */
94     my_counter2b = AO_load_acquire_read(&counter2);
95     my_counter1b = AO_load(&counter1);
96     if (my_counter1a < my_counter2a)
97       {
98         fprintf(stderr, "Saw release store out of order: %lu < %lu\n",
99             (unsigned long)my_counter1a, (unsigned long)my_counter2a);
100         abort();
101       }
102     if (my_counter1b < my_counter2b)
103       {
104         fprintf(stderr,
105             "Saw release store out of order (bad CSE?): %lu < %lu\n",
106             (unsigned long)my_counter1b, (unsigned long)my_counter2b);
107         abort();
108       }
109       }
110
111   return 0;
112 }
113
114 int acqrel_test(void)
115 {
116   return counter1 == NITERS && counter2 == NITERS;
117 }
118
119 #endif /* AO_HAVE_store_release_write && AO_HAVE_load_acquire_read */
120
121 #if defined(AO_HAVE_test_and_set_acquire)
122
123 AO_TS_T lock = AO_TS_INITIALIZER;
124
125 unsigned long locked_counter;
126 volatile unsigned long junk = 13;
127
128 void * test_and_set_thr(void * id)
129 {
130   unsigned long i;
131
132   for (i = 0; i < NITERS/10; ++i)
133     {
134       while (AO_test_and_set_acquire(&lock) != AO_TS_CLEAR);
135       ++locked_counter;
136       if (locked_counter != 1)
137         {
138           fprintf(stderr, "Test and set failure 1, counter = %ld\n",
139                   locked_counter);
140           abort();
141         }
142       locked_counter *= 2;
143       locked_counter -= 1;
144       locked_counter *= 5;
145       locked_counter -= 4;
146       if (locked_counter != 1)
147         {
148           fprintf(stderr, "Test and set failure 2, counter = %ld\n",
149                   locked_counter);
150           abort();
151         }
152       --locked_counter;
153       AO_CLEAR(&lock);
154       /* Spend a bit of time outside the lock. */
155         junk *= 17;
156         junk *= 17;
157     }
158   return 0;
159 }
160
161 int test_and_set_test(void)
162 {
163   return locked_counter == 0;
164 }
165
166 #endif /* defined(AO_HAVE_test_and_set_acquire) */
167
168 int main(void)
169 {
170   test_atomic();
171   test_atomic_acquire();
172   test_atomic_release();
173   test_atomic_read();
174   test_atomic_write();
175   test_atomic_full();
176   test_atomic_release_write();
177   test_atomic_acquire_read();
178 # if defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1)
179     run_parallel(4, add1sub1_thr, add1sub1_test, "add1/sub1");
180 # endif
181 # if defined(AO_HAVE_store_release_write) && defined(AO_HAVE_load_acquire_read)
182     run_parallel(3, acqrel_thr, acqrel_test,
183          "store_release_write/load_acquire_read");
184 # endif
185 # if defined(AO_HAVE_test_and_set_acquire)
186     run_parallel(5, test_and_set_thr, test_and_set_test,
187          "test_and_set");
188 # endif
189   return 0;
190 }