11 struct lfds700_stack_state
20 struct lfds700_stack_element
28 /***** private prototypes *****/
29 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_pushing( void *util_thread_starter_thread_state );
35 /****************************************************************************/
36 void test_lfds700_stack_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
38 enum lfds700_misc_validity
39 dvs = LFDS700_MISC_VALIDITY_VALID;
44 number_logical_processors,
47 struct lfds700_list_asu_element
50 struct lfds700_misc_prng_state
53 struct lfds700_stack_element
56 struct lfds700_stack_state
59 struct lfds700_misc_validation_info
62 struct test_pal_logical_processor
65 struct util_thread_starter_state
75 test_pal_thread_state_t
78 assert( list_of_logical_processors != NULL );
79 // TRD : memory_in_megabytes can be any value in its range
81 /* TRD : we create an empty stack
83 we then create one thread per CPU, where each thread
84 pushes 100,000 elements each as quickly as possible to the stack
85 (the threads themselves alloc these elements, to obtain NUMA closeness)
87 the data pushed is a counter and a thread ID
89 the threads exit when the stack is full
91 we then validate the stack;
93 checking that the counts increment on a per unique ID basis
94 and that the number of elements we pop equals 100,000 per thread
95 (since each element has an incrementing counter which is
96 unique on a per unique ID basis, we can know we didn't lose
99 there's no CAS+GC code, as we only push
102 internal_display_test_name( "Pushing" );
104 lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
106 lfds700_misc_prng_init( &ps );
108 number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
110 ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
112 // TRD : the main stack
113 lfds700_stack_init_valid_on_current_logical_core( &ss, NULL );
115 for( loop = 0 ; loop < number_logical_processors ; loop++ )
118 (ts+loop)->thread_number = loop;
119 (ts+loop)->number_elements = number_elements;
122 thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
124 util_thread_starter_new( &tts, number_logical_processors );
126 LFDS700_MISC_BARRIER_STORE;
128 lfds700_misc_force_store();
133 while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
135 lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
136 util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_pushing, ts+loop );
140 util_thread_starter_run( tts );
142 for( loop = 0 ; loop < number_logical_processors ; loop++ )
143 test_pal_thread_wait( thread_handles[loop] );
145 util_thread_starter_delete( tts );
147 free( thread_handles );
149 LFDS700_MISC_BARRIER_LOAD;
151 // TRD : the stack is now fully pushed; time to verify
152 per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
154 for( loop = 0 ; loop < number_logical_processors ; loop++ )
155 *(per_thread_counters+loop) = number_elements - 1;
157 vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
159 lfds700_stack_query( &ss, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
161 while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_stack_pop(&ss, &se, &ps) )
163 te = LFDS700_STACK_GET_VALUE_FROM_ELEMENT( *se );
165 if( first_te == NULL )
168 if( te->thread_number >= number_logical_processors )
170 dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
174 if( te->datum > per_thread_counters[te->thread_number] )
175 dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
177 if( te->datum < per_thread_counters[te->thread_number] )
178 dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
180 if( te->datum == per_thread_counters[te->thread_number] )
181 per_thread_counters[te->thread_number]--;
185 for( loop = 0 ; loop < number_logical_processors ; loop++ )
186 util_aligned_free( (ts+loop)->te_array );
188 free( per_thread_counters );
192 lfds700_stack_cleanup( &ss, NULL );
194 // TRD : print the test result
195 internal_display_test_result( 1, "stack", dvs );
204 /****************************************************************************/
205 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_pushing( void *util_thread_starter_thread_state )
210 struct lfds700_misc_prng_state
216 struct util_thread_starter_thread_state
219 LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
221 assert( util_thread_starter_thread_state != NULL );
223 tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
224 ts = (struct test_state *) tsts->thread_user_state;
226 lfds700_misc_prng_init( &ps );
228 // TRD : alloc local 100,000 elements
229 ts->te_array = util_aligned_malloc( sizeof(struct test_element) * ts->number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
231 for( loop = 0 ; loop < ts->number_elements ; loop++ )
233 (ts->te_array+loop)->thread_number = ts->thread_number;
234 (ts->te_array+loop)->datum = loop;
237 util_thread_starter_ready_and_wait( tsts );
239 for( loop = 0 ; loop < ts->number_elements ; loop++ )
241 LFDS700_STACK_SET_VALUE_IN_ELEMENT( (ts->te_array+loop)->se, ts->te_array+loop );
242 lfds700_stack_push( ts->ss, &(ts->te_array+loop)->se, &ps );
245 LFDS700_MISC_BARRIER_STORE;
247 lfds700_misc_force_store();
249 return( (test_pal_thread_return_t) EXIT_SUCCESS );