12 struct lfds700_stack_state
17 *ss_thread_local_te_array;
22 struct lfds700_stack_element
30 /***** private prototypes *****/
31 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state );
32 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state );
38 /****************************************************************************/
39 void test_lfds700_stack_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
41 enum lfds700_misc_validity
42 dvs = LFDS700_MISC_VALIDITY_VALID;
47 number_logical_processors,
50 struct lfds700_list_asu_element
53 struct lfds700_misc_prng_state
56 struct lfds700_stack_state
59 struct lfds700_misc_validation_info
62 struct test_pal_logical_processor
65 struct util_thread_starter_state
74 test_pal_thread_state_t
77 assert( list_of_logical_processors != NULL );
78 // TRD : memory_in_megabytes can be any value in its range
80 /* TRD : we have two threads per CPU
81 the threads loop for ten seconds
82 the first thread pushes 10000 elements then pops 10000 elements
83 the second thread pops 10000 elements then pushes 10000 elements
84 all pushes and pops go onto the single main stack
86 after time is up, all threads push what they have remaining onto
89 we then validate the main stack
92 internal_display_test_name( "Popping and pushing (%d seconds)", TEST_DURATION_IN_SECONDS );
94 lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
96 lfds700_misc_prng_init( &ps );
98 number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors * 2 );
100 lfds700_stack_init_valid_on_current_logical_core( &ss, NULL );
102 te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
104 // TRD : some initial elements so the pushing threads can start immediately
105 for( loop = 0 ; loop < number_elements * number_logical_processors ; loop++ )
107 (te_array+loop)->datum = loop;
108 LFDS700_STACK_SET_VALUE_IN_ELEMENT( (te_array+loop)->se, te_array+loop );
109 lfds700_stack_push( &ss, &(te_array+loop)->se, &ps );
112 ts = util_aligned_malloc( sizeof(struct test_state) * number_logical_processors * 2, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
114 for( loop = 0 ; loop < number_logical_processors ; loop++ )
116 // TRD : first set of threads
118 (ts+loop)->number_elements = number_elements;
119 lfds700_stack_init_valid_on_current_logical_core( &(ts+loop)->ss_thread_local, NULL );
121 // TRD : second set of threads
122 (ts+loop+number_logical_processors)->ss = &ss;
123 (ts+loop+number_logical_processors)->number_elements = number_elements;
124 lfds700_stack_init_valid_on_current_logical_core( &(ts+loop+number_logical_processors)->ss_thread_local, NULL );
126 // TRD : fill the pushing thread stacks
127 (ts+loop+number_logical_processors)->ss_thread_local_te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
129 for( subloop = 0 ; subloop < number_elements ; subloop++ )
131 ((ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop)->datum = loop;
132 LFDS700_STACK_SET_VALUE_IN_ELEMENT( ((ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop)->thread_local_se, (ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop );
133 lfds700_stack_push( &(ts+loop+number_logical_processors)->ss_thread_local, &((ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop)->thread_local_se, &ps );
137 thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors * 2 );
139 util_thread_starter_new( &tts, number_logical_processors * 2 );
141 LFDS700_MISC_BARRIER_STORE;
143 lfds700_misc_force_store();
148 while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
150 lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
151 util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_popping_and_pushing_start_popping, ts+loop );
152 util_thread_starter_start( tts, &thread_handles[loop+number_logical_processors], loop+number_logical_processors, lp, thread_popping_and_pushing_start_pushing, ts+loop+number_logical_processors );
156 util_thread_starter_run( tts );
158 for( loop = 0 ; loop < number_logical_processors * 2 ; loop++ )
159 test_pal_thread_wait( thread_handles[loop] );
161 util_thread_starter_delete( tts );
163 free( thread_handles );
165 LFDS700_MISC_BARRIER_LOAD;
167 vi.min_elements = vi.max_elements = number_elements * number_logical_processors * 2;
169 lfds700_stack_query( &ss, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
171 lfds700_stack_cleanup( &ss, NULL );
173 for( loop = 0 ; loop < number_logical_processors ; loop++ )
175 lfds700_stack_cleanup( &(ts+loop)->ss_thread_local, NULL );
176 lfds700_stack_cleanup( &(ts+loop+number_logical_processors)->ss_thread_local, NULL );
177 util_aligned_free( (ts+loop+number_logical_processors)->ss_thread_local_te_array );
180 util_aligned_free( ts );
182 util_aligned_free( te_array );
184 // TRD : print the test result
185 internal_display_test_result( 1, "stack", dvs );
195 /****************************************************************************/
196 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state )
201 struct lfds700_misc_prng_state
204 struct lfds700_stack_element
210 struct util_thread_starter_thread_state
216 LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
218 assert( util_thread_starter_thread_state != NULL );
220 tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
221 ts = (struct test_state *) tsts->thread_user_state;
223 lfds700_misc_prng_init( &ps );
225 util_thread_starter_ready_and_wait( tsts );
227 start_time = time( NULL );
229 while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
233 while( count < ts->number_elements )
234 if( lfds700_stack_pop(ts->ss, &se, &ps) )
236 lfds700_stack_push( &ts->ss_thread_local, se, &ps );
240 // TRD : return our local stack to the main stack
241 while( lfds700_stack_pop(&ts->ss_thread_local, &se, &ps) )
242 lfds700_stack_push( ts->ss, se, &ps );
245 LFDS700_MISC_BARRIER_STORE;
247 lfds700_misc_force_store();
249 return( (test_pal_thread_return_t) EXIT_SUCCESS );
256 /****************************************************************************/
257 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state )
262 struct lfds700_misc_prng_state
265 struct lfds700_stack_element
271 struct util_thread_starter_thread_state
277 LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
279 assert( util_thread_starter_thread_state != NULL );
281 tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
282 ts = (struct test_state *) tsts->thread_user_state;
284 lfds700_misc_prng_init( &ps );
286 util_thread_starter_ready_and_wait( tsts );
288 start_time = time( NULL );
290 while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
292 // TRD : return our local stack to the main stack
293 while( lfds700_stack_pop(&ts->ss_thread_local, &se, &ps) )
294 lfds700_stack_push( ts->ss, se, &ps );
298 while( count < ts->number_elements )
299 if( lfds700_stack_pop(ts->ss, &se, &ps) )
301 lfds700_stack_push( &ts->ss_thread_local, se, &ps );
306 // TRD : now push whatever we have in our local stack
307 while( lfds700_stack_pop(&ts->ss_thread_local, &se, &ps) )
308 lfds700_stack_push( ts->ss, se, &ps );
310 LFDS700_MISC_BARRIER_STORE;
312 lfds700_misc_force_store();
314 return( (test_pal_thread_return_t) EXIT_SUCCESS );