2 #include "libtest_tests_internal.h"
7 struct lfds710_stack_element
15 struct test_per_thread_state
17 struct lfds710_stack_state
22 number_elements_per_thread;
25 /***** private prototypes *****/
26 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *libtest_threadset_per_thread_state );
27 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *libtest_threadset_per_thread_state );
33 /****************************************************************************/
34 void libtest_tests_stack_popping_and_pushing( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
39 number_elements_per_thread,
40 number_logical_processors,
43 struct lfds710_list_asu_element
46 struct lfds710_stack_state
49 struct lfds710_misc_validation_info
52 struct libtest_logical_processor
55 struct libtest_threadset_per_thread_state
58 struct libtest_threadset_state
64 struct test_per_thread_state
67 LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
68 LFDS710_PAL_ASSERT( ms != NULL );
69 LFDS710_PAL_ASSERT( dvs != NULL );
71 /* TRD : we have two threads per CPU
72 the threads loop for ten seconds
73 the first thread pushes 10000 elements then pops 10000 elements
74 the second thread pops 10000 elements then pushes 10000 elements
75 all pushes and pops go onto the single main stack
76 with a per-thread local stack to store the pops
78 after time is up, all threads push what they have remaining onto
81 we then validate the main stack
85 lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
86 tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors * 2, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
87 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 );
88 te_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
90 number_elements_per_thread = number_elements / (number_logical_processors * 2);
92 lfds710_stack_init_valid_on_current_logical_core( &ss, NULL );
94 // TRD : half of all elements in the main stack so the popping threads can start immediately
95 for( loop = 0 ; loop < number_elements_per_thread * number_logical_processors ; loop++ )
97 (te_array+loop)->datum = loop;
98 LFDS710_STACK_SET_VALUE_IN_ELEMENT( (te_array+loop)->se, te_array+loop );
99 lfds710_stack_push( &ss, &(te_array+loop)->se );
104 libtest_threadset_init( &ts, NULL );
106 while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors,lasue) )
108 lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
110 // TRD : first set of threads (poppers)
111 (tpts+loop)->ss = &ss;
112 (tpts+loop)->number_elements_per_thread = number_elements_per_thread;
113 lfds710_stack_init_valid_on_current_logical_core( &(tpts+loop)->ss_thread_local, NULL );
114 libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_popping_and_pushing_start_popping, &tpts[loop] );
116 // TRD : second set of threads (pushers - who need elements in their per-thread stacks)
117 (tpts+loop+number_logical_processors)->ss = &ss;
118 (tpts+loop+number_logical_processors)->number_elements_per_thread = number_elements_per_thread;
119 lfds710_stack_init_valid_on_current_logical_core( &(tpts+loop+number_logical_processors)->ss_thread_local, NULL );
120 libtest_threadset_add_thread( &ts, &pts[loop+number_logical_processors], lp, thread_popping_and_pushing_start_pushing, &tpts[loop+number_logical_processors] );
122 for( subloop = number_elements_per_thread * (number_logical_processors + loop) ; subloop < number_elements_per_thread * (number_logical_processors + loop + 1) ; subloop++ )
124 LFDS710_STACK_SET_VALUE_IN_ELEMENT( (te_array+subloop)->thread_local_se, (te_array+subloop) );
125 lfds710_stack_push( &(tpts+loop+number_logical_processors)->ss_thread_local, &(te_array+subloop)->thread_local_se );
131 LFDS710_MISC_BARRIER_STORE;
133 lfds710_misc_force_store();
135 // TRD : run the test
136 libtest_threadset_run( &ts );
138 libtest_threadset_cleanup( &ts );
141 LFDS710_MISC_BARRIER_LOAD;
143 vi.min_elements = vi.max_elements = number_elements_per_thread * number_logical_processors * 2;
145 lfds710_stack_query( &ss, LFDS710_STACK_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) dvs );
147 lfds710_stack_cleanup( &ss, NULL );
149 for( loop = 0 ; loop < number_logical_processors ; loop++ )
151 lfds710_stack_cleanup( &(tpts+loop)->ss_thread_local, NULL );
152 lfds710_stack_cleanup( &(tpts+loop+number_logical_processors)->ss_thread_local, NULL );
163 /****************************************************************************/
164 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *libtest_threadset_per_thread_state )
169 struct lfds710_stack_element
172 struct test_per_thread_state
175 struct libtest_threadset_per_thread_state
181 LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
183 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
185 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
186 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
188 libtest_threadset_thread_ready_and_wait( pts );
190 start_time = time( NULL );
192 while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
196 while( count < tpts->number_elements_per_thread )
197 if( lfds710_stack_pop(tpts->ss, &se) )
199 // TRD : we do nothing with the test data, so there'ss no GET or SET here
200 lfds710_stack_push( &tpts->ss_thread_local, se );
204 // TRD : return our local stack to the main stack
205 while( lfds710_stack_pop(&tpts->ss_thread_local, &se) )
206 lfds710_stack_push( tpts->ss, se );
209 LFDS710_MISC_BARRIER_STORE;
211 lfds710_misc_force_store();
213 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
220 /****************************************************************************/
221 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *libtest_threadset_per_thread_state )
226 struct lfds710_stack_element
229 struct test_per_thread_state
232 struct libtest_threadset_per_thread_state
238 LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
240 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
242 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
243 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
245 libtest_threadset_thread_ready_and_wait( pts );
247 start_time = time( NULL );
249 while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
251 // TRD : return our local stack to the main stack
252 while( lfds710_stack_pop(&tpts->ss_thread_local, &se) )
253 lfds710_stack_push( tpts->ss, se );
257 while( count < tpts->number_elements_per_thread )
258 if( lfds710_stack_pop(tpts->ss, &se) )
260 lfds710_stack_push( &tpts->ss_thread_local, se );
265 // TRD : now push whatever we have in our local stack
266 while( lfds710_stack_pop(&tpts->ss_thread_local, &se) )
267 lfds710_stack_push( tpts->ss, se );
269 LFDS710_MISC_BARRIER_STORE;
271 lfds710_misc_force_store();
273 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);