2 #include "libtest_tests_internal.h"
7 struct lfds710_list_aso_element
15 struct test_per_thread_state
21 number_elements_per_thread;
23 struct lfds710_list_aso_state
30 /***** private prototypes *****/
31 static int new_ordered_with_cursor_compare_function( void const *value_new, void const *value_in_list );
32 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION new_ordered_with_cursor_insert_thread( void *libtest_threadset_per_thread_state );
33 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION new_ordered_with_cursor_cursor_thread( void *libtest_threadset_per_thread_state );
39 /****************************************************************************/
40 void libtest_tests_list_aso_new_ordered_with_cursor( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
45 number_elements_per_thread,
46 number_elements_total,
47 number_logical_processors,
51 struct lfds710_list_aso_state
54 struct lfds710_list_asu_element
57 struct lfds710_prng_state
60 struct lfds710_misc_validation_info
63 struct libtest_logical_processor
66 struct libtest_threadset_per_thread_state
69 struct libtest_threadset_state
75 struct test_per_thread_state
78 LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
79 LFDS710_PAL_ASSERT( ms != NULL );
80 LFDS710_PAL_ASSERT( dvs != NULL );
82 /* TRD : run two threads per logical processor
84 the test runs for 10 seconds
86 the first thread loops over a pre-set list of random numbers
87 continually adding them using ordered insert
89 the second thread keeps iterating over the list, checking that
90 each element is larger than its predecessor
93 *dvs = LFDS710_MISC_VALIDITY_VALID;
95 lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
96 tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors * 2, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
97 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 );
98 element_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
100 number_elements_per_thread = number_elements / number_logical_processors;
102 lfds710_prng_init_valid_on_current_logical_core( &ps, LFDS710_PRNG_SEED );
104 lfds710_list_aso_init_valid_on_current_logical_core( &lasos, new_ordered_with_cursor_compare_function, LFDS710_LIST_ASO_INSERT_RESULT_FAILURE_EXISTING_KEY, NULL );
106 /* TRD : create randomly ordered number array with unique elements
108 unique isn't necessary - the list will sort anyway - but
109 it permits slightly better validation
112 // TRD : or the test takes a looooooong time...
113 if( number_elements_per_thread > 1000 )
114 number_elements_per_thread = 1000;
116 number_elements_total = number_elements_per_thread * number_logical_processors;
118 for( loop = 0 ; loop < number_elements_total ; loop++ )
119 (element_array+loop)->element_number = loop;
121 for( loop = 0 ; loop < number_elements_total ; loop++ )
123 LFDS710_PRNG_GENERATE( ps, offset );
124 offset %= number_elements_total;
125 temp = (element_array + offset)->element_number;
126 (element_array + offset)->element_number = (element_array + loop)->element_number;
127 (element_array + loop)->element_number = temp;
130 // TRD : get the threads ready
131 libtest_threadset_init( &ts, NULL );
135 while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors,lasue) )
137 lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
139 // TRD : the insert threads
140 (tpts+loop)->lasos = &lasos;
141 (tpts+loop)->element_array = element_array + number_elements_per_thread*loop;
142 (tpts+loop)->error_flag = LOWERED;
143 (tpts+loop)->number_elements_per_thread = number_elements_per_thread;
144 libtest_threadset_add_thread( &ts, &pts[loop], lp, new_ordered_with_cursor_insert_thread, &tpts[loop] );
146 // TRD : the cursor threads
147 (tpts+loop+number_logical_processors)->lasos = &lasos;
148 (tpts+loop+number_logical_processors)->element_array = NULL;
149 (tpts+loop+number_logical_processors)->error_flag = LOWERED;
150 libtest_threadset_add_thread( &ts, &pts[loop+number_logical_processors], lp, new_ordered_with_cursor_cursor_thread, &tpts[loop+number_logical_processors] );
155 LFDS710_MISC_BARRIER_STORE;
157 lfds710_misc_force_store();
159 libtest_threadset_run( &ts );
161 libtest_threadset_cleanup( &ts );
163 /* TRD : validate the resultant list
165 the cursor threads were checking for orderedness
166 if that failed, they raise their error_flag
167 so validate the list, then check error_flags
170 LFDS710_MISC_BARRIER_LOAD;
172 vi.min_elements = vi.max_elements = number_elements_total;
174 lfds710_list_aso_query( &lasos, LFDS710_LIST_ASO_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
176 if( *dvs == LFDS710_MISC_VALIDITY_VALID )
177 for( loop = number_logical_processors ; loop < number_logical_processors * 2 ; loop++ )
178 if( (tpts+loop)->error_flag == RAISED )
179 *dvs = LFDS710_MISC_VALIDITY_INVALID_ORDER;
181 lfds710_list_aso_cleanup( &lasos, NULL );
190 /****************************************************************************/
191 #pragma warning( disable : 4100 )
193 static int new_ordered_with_cursor_compare_function( void const *value_new, void const *value_in_list )
202 // TRD : value_new can be any value in its range
203 // TRD : value_in_list can be any value in its range
205 e1 = (struct test_element *) value_new;
206 e2 = (struct test_element *) value_in_list;
208 if( e1->element_number < e2->element_number )
211 if( e1->element_number > e2->element_number )
217 #pragma warning( default : 4100 )
223 /****************************************************************************/
224 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION new_ordered_with_cursor_insert_thread( void *libtest_threadset_per_thread_state )
229 struct libtest_threadset_per_thread_state
232 struct test_per_thread_state
235 LFDS710_MISC_BARRIER_LOAD;
237 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
239 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
240 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
242 libtest_threadset_thread_ready_and_wait( pts );
244 for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
246 LFDS710_LIST_ASO_SET_KEY_IN_ELEMENT( (tpts->element_array+loop)->lasoe, tpts->element_array+loop );
247 LFDS710_LIST_ASO_SET_VALUE_IN_ELEMENT( (tpts->element_array+loop)->lasoe, tpts->element_array+loop );
248 lfds710_list_aso_insert( tpts->lasos, &(tpts->element_array+loop)->lasoe, NULL );
251 LFDS710_MISC_BARRIER_STORE;
253 lfds710_misc_force_store();
255 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
262 /****************************************************************************/
263 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION new_ordered_with_cursor_cursor_thread( void *libtest_threadset_per_thread_state )
271 struct lfds710_list_aso_element
277 struct libtest_threadset_per_thread_state
280 struct test_per_thread_state
287 LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
289 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
291 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
292 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
294 libtest_threadset_thread_ready_and_wait( pts );
296 current_time = start_time = time( NULL );
298 while( current_time < start_time + TEST_DURATION_IN_SECONDS )
300 prev_element_number = 0;
302 lasoe = LFDS710_LIST_ASO_GET_START( *tpts->lasos );
304 // TRD : we may get start before any element has been added to the list
308 element = LFDS710_LIST_ASO_GET_VALUE_FROM_ELEMENT( *lasoe );
310 if( element->element_number < prev_element_number )
311 tpts->error_flag = RAISED;
313 prev_element_number = element->element_number;
315 lasoe = LFDS710_LIST_ASO_GET_NEXT( *lasoe );
317 while( lasoe != NULL )
319 element = LFDS710_LIST_ASO_GET_VALUE_FROM_ELEMENT( *lasoe );
321 if( element->element_number <= prev_element_number )
322 tpts->error_flag = RAISED;
324 prev_element_number = element->element_number;
326 lasoe = LFDS710_LIST_ASO_GET_NEXT( *lasoe );
329 if( time_loop++ == REDUCED_TIME_LOOP_COUNT )
332 time( ¤t_time );
336 LFDS710_MISC_BARRIER_STORE;
338 lfds710_misc_force_store();
340 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);