2 #include "libtest_tests_internal.h"
5 struct test_per_thread_state
8 number_elements_per_thread,
11 struct lfds710_freelist_state
14 struct lfds710_prng_st_state
23 struct lfds710_freelist_element
31 /***** private prototypes *****/
32 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_pushing( void *libtest_threadset_per_thread_state );
38 /****************************************************************************/
39 void libtest_tests_freelist_ea_pushing( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
44 number_elements_per_thread,
45 number_logical_processors,
47 smallest_power_of_two_larger_than_or_equal_to_number_logical_processors = 2,
48 temp_number_logical_processors;
50 struct lfds710_freelist_element * volatile
51 (*ea)[LFDS710_FREELIST_ELIMINATION_ARRAY_ELEMENT_SIZE_IN_FREELIST_ELEMENTS];
53 struct lfds710_list_asu_element
56 struct lfds710_freelist_state
59 struct lfds710_misc_validation_info
62 struct lfds710_prng_st_state
65 struct libtest_logical_processor
68 struct libtest_threadset_per_thread_state
71 struct libtest_threadset_state
77 struct test_per_thread_state
80 LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
81 LFDS710_PAL_ASSERT( ms != NULL );
82 LFDS710_PAL_ASSERT( dvs != NULL );
84 /* TRD : we create an empty freelist
86 we then create one thread per CPU, where each thread
87 pushes 100,000 elements each as quickly as possible to the freelist
89 the data pushed is a counter and a thread ID
91 the threads exit when the freelist is full
93 we then validate the freelist;
95 checking that the counts increment on a per unique ID basis
96 and that the number of elements we pop equals 100,000 per thread
97 (since each element has an incrementing counter which is
98 unique on a per unique ID basis, we can know we didn't lofe
102 *dvs = LFDS710_MISC_VALIDITY_VALID;
104 lfds710_prng_st_init( &psts, LFDS710_PRNG_SEED );
106 lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
108 temp_number_logical_processors = number_logical_processors >> 2;
109 while( temp_number_logical_processors != 0 )
111 temp_number_logical_processors >>= 1;
112 smallest_power_of_two_larger_than_or_equal_to_number_logical_processors <<= 1;
116 tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
117 pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
118 ea = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct lfds710_freelist_element *) * LFDS710_FREELIST_ELIMINATION_ARRAY_ELEMENT_SIZE_IN_FREELIST_ELEMENTS * smallest_power_of_two_larger_than_or_equal_to_number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
119 te_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
121 number_elements_per_thread = number_elements / number_logical_processors;
123 // TRD : the main freelist
124 lfds710_freelist_init_valid_on_current_logical_core( &fs, ea, smallest_power_of_two_larger_than_or_equal_to_number_logical_processors, NULL );
126 libtest_threadset_init( &ts, NULL );
128 while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
130 lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
132 (tpts+loop)->fs = &fs;
133 (tpts+loop)->thread_number = loop;
134 (tpts+loop)->number_elements_per_thread = number_elements_per_thread;
135 (tpts+loop)->te_array = te_array + loop * number_elements_per_thread;
136 LFDS710_PRNG_ST_GENERATE( psts, random_value );
137 LFDS710_PRNG_ST_MIXING_FUNCTION( random_value );
138 lfds710_prng_st_init( &(tpts+loop)->psts, random_value );
140 libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_pushing, &tpts[loop] );
145 LFDS710_MISC_BARRIER_STORE;
147 lfds710_misc_force_store();
149 // TRD : run the test
150 libtest_threadset_run( &ts );
152 libtest_threadset_cleanup( &ts );
155 LFDS710_MISC_BARRIER_LOAD;
157 vi.min_elements = vi.max_elements = number_elements_per_thread * number_logical_processors;
159 lfds710_freelist_query( &fs, LFDS710_FREELIST_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
161 lfds710_freelist_cleanup( &fs, NULL );
170 /****************************************************************************/
171 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_pushing( void *libtest_threadset_per_thread_state )
176 struct test_per_thread_state
179 struct libtest_threadset_per_thread_state
182 LFDS710_MISC_BARRIER_LOAD;
184 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
186 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
188 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
190 for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
192 (tpts->te_array+loop)->thread_number = tpts->thread_number;
193 (tpts->te_array+loop)->datum = loop;
196 libtest_threadset_thread_ready_and_wait( pts );
198 for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
200 LFDS710_FREELIST_SET_VALUE_IN_ELEMENT( (tpts->te_array+loop)->fe, tpts->te_array+loop );
201 lfds710_freelist_push( tpts->fs, &(tpts->te_array+loop)->fe, &tpts->psts );
204 LFDS710_MISC_BARRIER_STORE;
206 lfds710_misc_force_store();
208 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);