]> pd.if.org Git - liblfds/blob - liblfds/liblfds6.1.1/test/src/test_abstraction.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds6.1.1 / test / src / test_abstraction.c
1 #include "internal.h"
2
3
4
5
6
7 /****************************************************************************/
8 void test_lfds611_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   LFDS611_ALIGN(LFDS611_ALIGN_SINGLE_POINTER) volatile lfds611_atom_t
36     shared_counter,
37     atomic_shared_counter;
38
39   /* TRD : here we test lfds611_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            lfds611_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   LFDS611_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, (void *) &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, (void *) &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   LFDS611_BARRIER_LOAD;
110
111   lfds611_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   LFDS611_BARRIER_LOAD;
126
127   lfds611_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   LFDS611_ALIGN(LFDS611_ALIGN_SINGLE_POINTER) volatile lfds611_atom_t
150     shared_counter;
151
152   lfds611_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 lfds611_abstraction_cas
158
159            we run one thread per CPU
160            we use lfds611_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   shared_counter = 0;
173
174   LFDS611_BARRIER_STORE;
175
176   atcs = malloc( sizeof(struct abstraction_test_cas_state) * cpu_count );
177
178   for( loop = 0 ; loop < cpu_count ; loop++ )
179   {
180     (atcs+loop)->shared_counter = &shared_counter;
181     (atcs+loop)->local_counter = 0;
182   }
183
184   thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
185
186   for( loop = 0 ; loop < cpu_count ; loop++ )
187     abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_cas, atcs+loop );
188
189   for( loop = 0 ; loop < cpu_count ; loop++ )
190     abstraction_thread_wait( thread_handles[loop] );
191
192   free( thread_handles );
193
194   // TRD : results
195   for( loop = 0 ; loop < cpu_count ; loop++ )
196     local_total += (atcs+loop)->local_counter;
197
198   if( local_total == shared_counter )
199     puts( "passed" );
200
201   if( local_total != shared_counter )
202     puts( "failed" );
203
204   // TRD : cleanup
205   free( atcs );
206
207   return;
208 }
209
210
211
212
213
214 /****************************************************************************/
215 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_cas( void *abstraction_test_cas_state )
216 {
217   struct abstraction_test_cas_state
218     *atcs;
219
220   assert( abstraction_test_cas_state != NULL );
221
222   atcs = (struct abstraction_test_cas_state *) abstraction_test_cas_state;
223
224   LFDS611_BARRIER_LOAD;
225
226   lfds611_liblfds_abstraction_test_helper_cas( atcs->shared_counter, &atcs->local_counter );
227
228   return( (thread_return_t) EXIT_SUCCESS );
229 }
230
231
232
233
234
235 /****************************************************************************/
236 void abstraction_test_dcas( void )
237 {
238   unsigned int
239     loop,
240     cpu_count;
241
242   thread_state_t
243     *thread_handles;
244
245   struct abstraction_test_dcas_state
246     *atds;
247
248   LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) volatile lfds611_atom_t
249     shared_counter[2] = { 0, 0 };
250
251   lfds611_atom_t
252     local_total = 0;
253
254   /* TRD : here we test lfds611_abstraction_dcas
255
256            we run one thread per CPU
257            we use lfds611_abstraction_dcas() to increment a shared counter
258            every time a thread successfully increments the counter,
259            it increments a thread local counter
260            the threads run for ten seconds
261            after the threads finish, we total the local counters
262            they should equal the shared counter
263   */
264
265   internal_display_test_name( "Atomic DCAS" );
266
267   cpu_count = abstraction_cpu_count();
268
269   atds = malloc( sizeof(struct abstraction_test_dcas_state) * cpu_count );
270
271   for( loop = 0 ; loop < cpu_count ; loop++ )
272   {
273     (atds+loop)->shared_counter = shared_counter;
274     (atds+loop)->local_counter = 0;
275   }
276
277   LFDS611_BARRIER_STORE;
278
279   thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
280
281   for( loop = 0 ; loop < cpu_count ; loop++ )
282     abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_dcas, atds+loop );
283
284   for( loop = 0 ; loop < cpu_count ; loop++ )
285     abstraction_thread_wait( thread_handles[loop] );
286
287   free( thread_handles );
288
289   // TRD : results
290   for( loop = 0 ; loop < cpu_count ; loop++ )
291     local_total += (atds+loop)->local_counter;
292
293   if( local_total == shared_counter[0] )
294     puts( "passed" );
295
296   if( local_total != shared_counter[0] )
297     puts( "failed" );
298
299   // TRD : cleanup
300   free( atds );
301
302   return;
303 }
304
305
306
307
308
309 /****************************************************************************/
310 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state )
311 {
312   struct abstraction_test_dcas_state
313     *atds;
314
315   assert( abstraction_test_dcas_state != NULL );
316
317   atds = (struct abstraction_test_dcas_state *) abstraction_test_dcas_state;
318
319   LFDS611_BARRIER_LOAD;
320
321   lfds611_liblfds_abstraction_test_helper_dcas( atds->shared_counter, &atds->local_counter );
322
323   return( (thread_return_t) EXIT_SUCCESS );
324 }
325