]> pd.if.org Git - liblfds/blob - liblfds/liblfds6.1.0/test/src/test_abstraction.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds6.1.0 / test / src / test_abstraction.c
1 #include "internal.h"
2
3
4
5
6
7 /****************************************************************************/
8 void test_lfds610_abstraction( void )
9 {
10   printf( "\n"
11           "Abstraction Tests\n"
12           "=================\n" );
13
14   abstraction_test_increment();
15   abstraction_test_cas();
16   abstraction_test_dcas();
17
18   return;
19 }
20
21
22
23
24
25 /****************************************************************************/
26 void abstraction_test_increment( void )
27 {
28   unsigned int
29     loop,
30     cpu_count;
31
32   thread_state_t
33     *thread_handles;
34
35   lfds610_atom_t
36     shared_counter,
37     atomic_shared_counter;
38
39   /* TRD : here we test lfds610_abstraction_increment
40
41            first, we run one thread per CPU where each thread increments
42            a shared counter 10,000,000 times - however, this first test
43            does NOT use atomic increment; it uses "++"
44
45            second, we repeat the exercise, but this time using
46            lfds610_abstraction_increment()
47
48            if the final value in the first test is less than (10,000,000*cpu_count)
49            then the system is sensitive to non-atomic increments; this means if
50            our atomic version of the test passes, we can have some degree of confidence
51            that it works
52
53            if the final value in the first test is in fact correct, then we can't know
54            that our atomic version has changed anything
55
56            and of course if the final value in the atomic test is wrong, we know things
57            are broken
58   */
59
60   internal_display_test_name( "Atomic increment" );
61
62   cpu_count = abstraction_cpu_count();
63
64   shared_counter = 0;
65   atomic_shared_counter = 0;
66
67   LFDS610_BARRIER_STORE;
68
69   thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
70
71   // TRD : non-atomic
72   for( loop = 0 ; loop < cpu_count ; loop++ )
73     abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_increment, &shared_counter );
74
75   for( loop = 0 ; loop < cpu_count ; loop++ )
76     abstraction_thread_wait( thread_handles[loop] );
77
78   // TRD : atomic
79   for( loop = 0 ; loop < cpu_count ; loop++ )
80     abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_atomic_increment, &atomic_shared_counter );
81
82   for( loop = 0 ; loop < cpu_count ; loop++ )
83     abstraction_thread_wait( thread_handles[loop] );
84
85   free( thread_handles );
86
87   // TRD : results
88   if( shared_counter < (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) )
89     puts( "passed" );
90
91   if( shared_counter == (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) )
92     puts( "indeterminate" );
93
94   if( atomic_shared_counter < (10000000 * cpu_count) )
95     puts( "failed" );
96
97   return;
98 }
99
100
101
102
103
104 /****************************************************************************/
105 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter )
106 {
107   assert( shared_counter != NULL );
108
109   LFDS610_BARRIER_LOAD;
110
111   lfds610_liblfds_abstraction_test_helper_increment_non_atomic( shared_counter );
112
113   return( (thread_return_t) EXIT_SUCCESS );
114 }
115
116
117
118
119
120 /****************************************************************************/
121 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter )
122 {
123   assert( shared_counter != NULL );
124
125   LFDS610_BARRIER_LOAD;
126
127   lfds610_liblfds_abstraction_test_helper_increment_atomic( shared_counter );
128
129   return( (thread_return_t) EXIT_SUCCESS );
130 }
131
132
133
134
135
136 /****************************************************************************/
137 void abstraction_test_cas( void )
138 {
139   unsigned int
140     loop,
141     cpu_count;
142
143   thread_state_t
144     *thread_handles;
145
146   struct abstraction_test_cas_state
147     *atcs;
148
149   LFDS610_ALIGN(LFDS610_ALIGN_SINGLE_POINTER) volatile lfds610_atom_t
150     shared_counter = 0;
151
152   lfds610_atom_t
153     local_total = 0;
154
155   // TRD : number_logical_processors can be any value in its range
156
157   /* TRD : here we test lfds610_abstraction_cas
158
159            we run one thread per CPU
160            we use lfds610_abstraction_cas() to increment a shared counter
161            every time a thread successfully increments the counter,
162            it increments a thread local counter
163            the threads run for ten seconds
164            after the threads finish, we total the local counters
165            they should equal the shared counter
166   */
167
168   internal_display_test_name( "Atomic CAS" );
169
170   cpu_count = abstraction_cpu_count();
171
172   atcs = malloc( sizeof(struct abstraction_test_cas_state) * cpu_count );
173
174   for( loop = 0 ; loop < cpu_count ; loop++ )
175   {
176     (atcs+loop)->shared_counter = &shared_counter;
177     (atcs+loop)->local_counter = 0;
178   }
179
180   thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
181
182   for( loop = 0 ; loop < cpu_count ; loop++ )
183     abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_cas, atcs+loop );
184
185   for( loop = 0 ; loop < cpu_count ; loop++ )
186     abstraction_thread_wait( thread_handles[loop] );
187
188   free( thread_handles );
189
190   // TRD : results
191   for( loop = 0 ; loop < cpu_count ; loop++ )
192     local_total += (atcs+loop)->local_counter;
193
194   if( local_total == shared_counter )
195     puts( "passed" );
196
197   if( local_total != shared_counter )
198     puts( "failed" );
199
200   // TRD : cleanup
201   free( atcs );
202
203   return;
204 }
205
206
207
208
209
210 /****************************************************************************/
211 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_cas( void *abstraction_test_cas_state )
212 {
213   struct abstraction_test_cas_state
214     *atcs;
215
216   assert( abstraction_test_cas_state != NULL );
217
218   atcs = (struct abstraction_test_cas_state *) abstraction_test_cas_state;
219
220   LFDS610_BARRIER_LOAD;
221
222   lfds610_liblfds_abstraction_test_helper_cas( atcs->shared_counter, &atcs->local_counter );
223
224   return( (thread_return_t) EXIT_SUCCESS );
225 }
226
227
228
229
230
231 /****************************************************************************/
232 void abstraction_test_dcas( void )
233 {
234   unsigned int
235     loop,
236     cpu_count;
237
238   thread_state_t
239     *thread_handles;
240
241   struct abstraction_test_dcas_state
242     *atds;
243
244   LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) volatile lfds610_atom_t
245     shared_counter[2] = { 0, 0 };
246
247   lfds610_atom_t
248     local_total = 0;
249
250   /* TRD : here we test lfds610_abstraction_dcas
251
252            we run one thread per CPU
253            we use lfds610_abstraction_dcas() to increment a shared counter
254            every time a thread successfully increments the counter,
255            it increments a thread local counter
256            the threads run for ten seconds
257            after the threads finish, we total the local counters
258            they should equal the shared counter
259   */
260
261   internal_display_test_name( "Atomic DCAS" );
262
263   cpu_count = abstraction_cpu_count();
264
265   atds = malloc( sizeof(struct abstraction_test_dcas_state) * cpu_count );
266
267   for( loop = 0 ; loop < cpu_count ; loop++ )
268   {
269     (atds+loop)->shared_counter = shared_counter;
270     (atds+loop)->local_counter = 0;
271   }
272
273   LFDS610_BARRIER_STORE;
274
275   thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
276
277   for( loop = 0 ; loop < cpu_count ; loop++ )
278     abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_dcas, atds+loop );
279
280   for( loop = 0 ; loop < cpu_count ; loop++ )
281     abstraction_thread_wait( thread_handles[loop] );
282
283   free( thread_handles );
284
285   // TRD : results
286   for( loop = 0 ; loop < cpu_count ; loop++ )
287     local_total += (atds+loop)->local_counter;
288
289   if( local_total == shared_counter[0] )
290     puts( "passed" );
291
292   if( local_total != shared_counter[0] )
293     puts( "failed" );
294
295   // TRD : cleanup
296   free( atds );
297
298   return;
299 }
300
301
302
303
304
305 /****************************************************************************/
306 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state )
307 {
308   struct abstraction_test_dcas_state
309     *atds;
310
311   assert( abstraction_test_dcas_state != NULL );
312
313   atds = (struct abstraction_test_dcas_state *) abstraction_test_dcas_state;
314
315   LFDS610_BARRIER_LOAD;
316
317   lfds610_liblfds_abstraction_test_helper_dcas( atds->shared_counter, &atds->local_counter );
318
319   return( (thread_return_t) EXIT_SUCCESS );
320 }
321