2 #include "libtest_tests_internal.h"
4 /***** private prototyps *****/
5 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_add( void *libtest_threadset_per_thread_state );
6 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_atomic_add( void *libtest_threadset_per_thread_state );
12 /****************************************************************************/
13 void libtest_tests_pal_atomic_add( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
15 lfds710_pal_uint_t volatile LFDS710_PAL_ALIGN(LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES)
16 number_logical_processors,
17 atomic_shared_counter,
23 struct lfds710_list_asu_element
26 struct libtest_logical_processor
29 struct libtest_threadset_per_thread_state
32 struct libtest_threadset_state
35 LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
36 LFDS710_PAL_ASSERT( ms != NULL );
37 LFDS710_PAL_ASSERT( dvs != NULL );
39 /* TRD : here we test abstraction_atomic_add
41 first, we run one thread per CPU where each thread adds
42 a shared counter 10,000,000 times - however, this first test
43 does NOT use atomic add; it uses "++"
45 second, we repeat the exercise, but this time using
48 if the final value in the first test is less than (10,000,000*asi->number_of_components[LFDS710_ABSTRACTION_COMPONENT_LOGICAL_PROCESSOR])
49 then the system is sensitive to non-atomic adds; 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
61 lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
62 pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors * 2, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
65 atomic_shared_counter = 0;
67 LFDS710_MISC_BARRIER_STORE;
71 libtest_threadset_init( &ts, NULL );
73 while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
75 lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
76 libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_add, (void *) &shared_counter );
80 LFDS710_MISC_BARRIER_STORE;
81 lfds710_misc_force_store();
82 libtest_threadset_run( &ts );
83 libtest_threadset_cleanup( &ts );
87 libtest_threadset_init( &ts, NULL );
92 while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
94 lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
95 libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_atomic_add, (void *) &atomic_shared_counter );
99 LFDS710_MISC_BARRIER_STORE;
100 lfds710_misc_force_store();
101 libtest_threadset_run( &ts );
102 libtest_threadset_cleanup( &ts );
103 LFDS710_MISC_BARRIER_LOAD;
107 on a single core, "++" and atomic add should be equal
109 if we find our non-atomic test passes, then we can't really say anything
110 about whether or not the atomic test is really working
113 if( number_logical_processors == 1 )
115 if( shared_counter == (10000000 * number_logical_processors) and atomic_shared_counter == (10000000 * number_logical_processors) )
116 *dvs = LFDS710_MISC_VALIDITY_VALID;
118 if( shared_counter != (10000000 * number_logical_processors) or atomic_shared_counter != (10000000 * number_logical_processors) )
119 *dvs = LFDS710_MISC_VALIDITY_INVALID_ATOMIC_FAILED;
122 if( number_logical_processors >= 2 )
124 if( shared_counter < (10000000 * number_logical_processors) and atomic_shared_counter == (10000000 * number_logical_processors) )
125 *dvs = LFDS710_MISC_VALIDITY_VALID;
127 if( shared_counter == (10000000 * number_logical_processors) and atomic_shared_counter == (10000000 * number_logical_processors) )
128 *dvs = LFDS710_MISC_VALIDITY_INDETERMINATE_NONATOMIC_PASSED;
130 if( atomic_shared_counter < (10000000 * number_logical_processors) )
131 *dvs = LFDS710_MISC_VALIDITY_INVALID_ATOMIC_FAILED;
141 /****************************************************************************/
142 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_add( void *libtest_threadset_per_thread_state )
144 struct libtest_threadset_per_thread_state
147 lfds710_pal_uint_t volatile
150 lfds710_pal_uint_t volatile
153 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
155 LFDS710_MISC_BARRIER_LOAD;
157 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
158 shared_counter = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
160 libtest_threadset_thread_ready_and_wait( pts );
162 while( count++ < 10000000 )
165 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
172 /****************************************************************************/
173 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_atomic_add( void *libtest_threadset_per_thread_state )
175 struct libtest_threadset_per_thread_state
178 lfds710_pal_uint_t volatile
182 lfds710_pal_uint_t volatile
185 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
187 LFDS710_MISC_BARRIER_LOAD;
189 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
190 shared_counter = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
192 libtest_threadset_thread_ready_and_wait( pts );
194 while( count++ < 10000000 )
196 LFDS710_PAL_ATOMIC_ADD( shared_counter, 1, result, lfds710_pal_uint_t );
200 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);