7 /****************************************************************************/
8 void test_lfds610_abstraction( void )
12 "=================\n" );
14 abstraction_test_increment();
15 abstraction_test_cas();
16 abstraction_test_dcas();
25 /****************************************************************************/
26 void abstraction_test_increment( void )
37 atomic_shared_counter;
39 /* TRD : here we test lfds610_abstraction_increment
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 "++"
45 second, we repeat the exercise, but this time using
46 lfds610_abstraction_increment()
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
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
56 and of course if the final value in the atomic test is wrong, we know things
60 internal_display_test_name( "Atomic increment" );
62 cpu_count = abstraction_cpu_count();
65 atomic_shared_counter = 0;
67 LFDS610_BARRIER_STORE;
69 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
72 for( loop = 0 ; loop < cpu_count ; loop++ )
73 abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_increment, &shared_counter );
75 for( loop = 0 ; loop < cpu_count ; loop++ )
76 abstraction_thread_wait( thread_handles[loop] );
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 );
82 for( loop = 0 ; loop < cpu_count ; loop++ )
83 abstraction_thread_wait( thread_handles[loop] );
85 free( thread_handles );
88 if( shared_counter < (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) )
91 if( shared_counter == (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) )
92 puts( "indeterminate" );
94 if( atomic_shared_counter < (10000000 * cpu_count) )
104 /****************************************************************************/
105 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter )
107 assert( shared_counter != NULL );
109 LFDS610_BARRIER_LOAD;
111 lfds610_liblfds_abstraction_test_helper_increment_non_atomic( shared_counter );
113 return( (thread_return_t) EXIT_SUCCESS );
120 /****************************************************************************/
121 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter )
123 assert( shared_counter != NULL );
125 LFDS610_BARRIER_LOAD;
127 lfds610_liblfds_abstraction_test_helper_increment_atomic( shared_counter );
129 return( (thread_return_t) EXIT_SUCCESS );
136 /****************************************************************************/
137 void abstraction_test_cas( void )
146 struct abstraction_test_cas_state
149 LFDS610_ALIGN(LFDS610_ALIGN_SINGLE_POINTER) volatile lfds610_atom_t
155 // TRD : number_logical_processors can be any value in its range
157 /* TRD : here we test lfds610_abstraction_cas
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
168 internal_display_test_name( "Atomic CAS" );
170 cpu_count = abstraction_cpu_count();
172 atcs = malloc( sizeof(struct abstraction_test_cas_state) * cpu_count );
174 for( loop = 0 ; loop < cpu_count ; loop++ )
176 (atcs+loop)->shared_counter = &shared_counter;
177 (atcs+loop)->local_counter = 0;
180 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
182 for( loop = 0 ; loop < cpu_count ; loop++ )
183 abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_cas, atcs+loop );
185 for( loop = 0 ; loop < cpu_count ; loop++ )
186 abstraction_thread_wait( thread_handles[loop] );
188 free( thread_handles );
191 for( loop = 0 ; loop < cpu_count ; loop++ )
192 local_total += (atcs+loop)->local_counter;
194 if( local_total == shared_counter )
197 if( local_total != shared_counter )
210 /****************************************************************************/
211 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_cas( void *abstraction_test_cas_state )
213 struct abstraction_test_cas_state
216 assert( abstraction_test_cas_state != NULL );
218 atcs = (struct abstraction_test_cas_state *) abstraction_test_cas_state;
220 LFDS610_BARRIER_LOAD;
222 lfds610_liblfds_abstraction_test_helper_cas( atcs->shared_counter, &atcs->local_counter );
224 return( (thread_return_t) EXIT_SUCCESS );
231 /****************************************************************************/
232 void abstraction_test_dcas( void )
241 struct abstraction_test_dcas_state
244 LFDS610_ALIGN(LFDS610_ALIGN_DOUBLE_POINTER) volatile lfds610_atom_t
245 shared_counter[2] = { 0, 0 };
250 /* TRD : here we test lfds610_abstraction_dcas
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
261 internal_display_test_name( "Atomic DCAS" );
263 cpu_count = abstraction_cpu_count();
265 atds = malloc( sizeof(struct abstraction_test_dcas_state) * cpu_count );
267 for( loop = 0 ; loop < cpu_count ; loop++ )
269 (atds+loop)->shared_counter = shared_counter;
270 (atds+loop)->local_counter = 0;
273 LFDS610_BARRIER_STORE;
275 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
277 for( loop = 0 ; loop < cpu_count ; loop++ )
278 abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_dcas, atds+loop );
280 for( loop = 0 ; loop < cpu_count ; loop++ )
281 abstraction_thread_wait( thread_handles[loop] );
283 free( thread_handles );
286 for( loop = 0 ; loop < cpu_count ; loop++ )
287 local_total += (atds+loop)->local_counter;
289 if( local_total == shared_counter[0] )
292 if( local_total != shared_counter[0] )
305 /****************************************************************************/
306 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state )
308 struct abstraction_test_dcas_state
311 assert( abstraction_test_dcas_state != NULL );
313 atds = (struct abstraction_test_dcas_state *) abstraction_test_dcas_state;
315 LFDS610_BARRIER_LOAD;
317 lfds610_liblfds_abstraction_test_helper_dcas( atds->shared_counter, &atds->local_counter );
319 return( (thread_return_t) EXIT_SUCCESS );