2 #include "libtest_tests_internal.h"
5 struct test_per_thread_state
8 number_elements_per_thread,
11 struct lfds710_freelist_state
20 struct lfds710_freelist_element
28 /***** private prototypes *****/
29 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_pushing( void *libtest_threadset_per_thread_state );
35 /****************************************************************************/
36 void libtest_tests_freelist_without_ea_pushing( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
41 number_elements_per_thread,
42 number_logical_processors,
45 struct lfds710_list_asu_element
48 struct lfds710_freelist_element
51 struct lfds710_freelist_state
54 struct lfds710_misc_validation_info
57 struct libtest_logical_processor
60 struct libtest_threadset_per_thread_state
63 struct libtest_threadset_state
70 struct test_per_thread_state
73 LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
74 LFDS710_PAL_ASSERT( ms != NULL );
75 LFDS710_PAL_ASSERT( dvs != NULL );
77 /* TRD : we create an empty freelist
79 we then create one thread per CPU, where each thread
80 pushes 100,000 elements each as quickly as possible to the freelist
82 the data pushed is a counter and a thread ID
84 the threads exit when the freelist is full
86 we then validate the freelist;
88 checking that the counts increment on a per unique ID basis
89 and that the number of elements we pop equals 100,000 per thread
90 (since each element has an incrementing counter which is
91 unique on a per unique ID basis, we can know we didn't lofe
95 *dvs = LFDS710_MISC_VALIDITY_VALID;
97 lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
100 tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
101 pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
102 per_thread_counters = libshared_memory_alloc_from_unknown_node( ms, sizeof(lfds710_pal_uint_t) * number_logical_processors, sizeof(lfds710_pal_uint_t) );
103 te_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
105 number_elements_per_thread = number_elements / number_logical_processors;
107 // TRD : the main freelist
108 lfds710_freelist_init_valid_on_current_logical_core( &fs, NULL, 0, NULL );
110 libtest_threadset_init( &ts, NULL );
112 while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
114 lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
116 (tpts+loop)->fs = &fs;
117 (tpts+loop)->thread_number = loop;
118 (tpts+loop)->number_elements_per_thread = number_elements_per_thread;
119 (tpts+loop)->te_array = te_array + loop * number_elements_per_thread;
121 libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_pushing, &tpts[loop] );
126 LFDS710_MISC_BARRIER_STORE;
128 lfds710_misc_force_store();
130 // TRD : run the test
131 libtest_threadset_run( &ts );
133 libtest_threadset_cleanup( &ts );
136 LFDS710_MISC_BARRIER_LOAD;
138 /* TRD : no EA flush - it consists of the first elements
139 and flushing would break the order validation check below
142 for( loop = 0 ; loop < number_logical_processors ; loop++ )
143 *(per_thread_counters+loop) = number_elements_per_thread - 1;
145 vi.min_elements = vi.max_elements = number_elements_per_thread * number_logical_processors;
147 lfds710_freelist_query( &fs, LFDS710_FREELIST_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
149 /* TRD : the elimination array will be populates with a random set of freelist elements
150 we expect then up to that many elements to be out of order
153 while( *dvs == LFDS710_MISC_VALIDITY_VALID and lfds710_freelist_pop(&fs, &fe, NULL) )
155 te = LFDS710_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
157 if( te->thread_number >= number_logical_processors )
159 *dvs = LFDS710_MISC_VALIDITY_INVALID_TEST_DATA;
163 if( te->datum > per_thread_counters[te->thread_number] )
164 *dvs = LFDS710_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
166 if( te->datum < per_thread_counters[te->thread_number] )
167 *dvs = LFDS710_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
169 if( te->datum == per_thread_counters[te->thread_number] )
170 per_thread_counters[te->thread_number]--;
173 lfds710_freelist_cleanup( &fs, NULL );
182 /****************************************************************************/
183 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_pushing( void *libtest_threadset_per_thread_state )
188 struct test_per_thread_state
191 struct libtest_threadset_per_thread_state
194 LFDS710_MISC_BARRIER_LOAD;
196 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
198 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
200 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
202 for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
204 (tpts->te_array+loop)->thread_number = tpts->thread_number;
205 (tpts->te_array+loop)->datum = loop;
208 libtest_threadset_thread_ready_and_wait( pts );
210 for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
212 LFDS710_FREELIST_SET_VALUE_IN_ELEMENT( (tpts->te_array+loop)->fe, tpts->te_array+loop );
213 lfds710_freelist_push( tpts->fs, &(tpts->te_array+loop)->fe, NULL );
216 LFDS710_MISC_BARRIER_STORE;
218 lfds710_misc_force_store();
220 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);