7 /****************************************************************************/
8 void test_lfds611_abstraction( void )
12 "=================\n" );
14 abstraction_test_increment();
15 abstraction_test_cas();
16 abstraction_test_dcas();
25 /****************************************************************************/
26 void abstraction_test_increment( void )
35 LFDS611_ALIGN(LFDS611_ALIGN_SINGLE_POINTER) volatile lfds611_atom_t
37 atomic_shared_counter;
39 /* TRD : here we test lfds611_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 lfds611_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 LFDS611_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, (void *) &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, (void *) &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 LFDS611_BARRIER_LOAD;
111 lfds611_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 LFDS611_BARRIER_LOAD;
127 lfds611_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 LFDS611_ALIGN(LFDS611_ALIGN_SINGLE_POINTER) volatile lfds611_atom_t
155 // TRD : number_logical_processors can be any value in its range
157 /* TRD : here we test lfds611_abstraction_cas
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
168 internal_display_test_name( "Atomic CAS" );
170 cpu_count = abstraction_cpu_count();
174 LFDS611_BARRIER_STORE;
176 atcs = malloc( sizeof(struct abstraction_test_cas_state) * cpu_count );
178 for( loop = 0 ; loop < cpu_count ; loop++ )
180 (atcs+loop)->shared_counter = &shared_counter;
181 (atcs+loop)->local_counter = 0;
184 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
186 for( loop = 0 ; loop < cpu_count ; loop++ )
187 abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_cas, atcs+loop );
189 for( loop = 0 ; loop < cpu_count ; loop++ )
190 abstraction_thread_wait( thread_handles[loop] );
192 free( thread_handles );
195 for( loop = 0 ; loop < cpu_count ; loop++ )
196 local_total += (atcs+loop)->local_counter;
198 if( local_total == shared_counter )
201 if( local_total != shared_counter )
214 /****************************************************************************/
215 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_cas( void *abstraction_test_cas_state )
217 struct abstraction_test_cas_state
220 assert( abstraction_test_cas_state != NULL );
222 atcs = (struct abstraction_test_cas_state *) abstraction_test_cas_state;
224 LFDS611_BARRIER_LOAD;
226 lfds611_liblfds_abstraction_test_helper_cas( atcs->shared_counter, &atcs->local_counter );
228 return( (thread_return_t) EXIT_SUCCESS );
235 /****************************************************************************/
236 void abstraction_test_dcas( void )
245 struct abstraction_test_dcas_state
248 LFDS611_ALIGN(LFDS611_ALIGN_DOUBLE_POINTER) volatile lfds611_atom_t
249 shared_counter[2] = { 0, 0 };
254 /* TRD : here we test lfds611_abstraction_dcas
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
265 internal_display_test_name( "Atomic DCAS" );
267 cpu_count = abstraction_cpu_count();
269 atds = malloc( sizeof(struct abstraction_test_dcas_state) * cpu_count );
271 for( loop = 0 ; loop < cpu_count ; loop++ )
273 (atds+loop)->shared_counter = shared_counter;
274 (atds+loop)->local_counter = 0;
277 LFDS611_BARRIER_STORE;
279 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
281 for( loop = 0 ; loop < cpu_count ; loop++ )
282 abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_dcas, atds+loop );
284 for( loop = 0 ; loop < cpu_count ; loop++ )
285 abstraction_thread_wait( thread_handles[loop] );
287 free( thread_handles );
290 for( loop = 0 ; loop < cpu_count ; loop++ )
291 local_total += (atds+loop)->local_counter;
293 if( local_total == shared_counter[0] )
296 if( local_total != shared_counter[0] )
309 /****************************************************************************/
310 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state )
312 struct abstraction_test_dcas_state
315 assert( abstraction_test_dcas_state != NULL );
317 atds = (struct abstraction_test_dcas_state *) abstraction_test_dcas_state;
319 LFDS611_BARRIER_LOAD;
321 lfds611_liblfds_abstraction_test_helper_dcas( atds->shared_counter, &atds->local_counter );
323 return( (thread_return_t) EXIT_SUCCESS );