2 #include "libtest_tests_internal.h"
7 struct test_per_thread_state
9 struct lfds710_freelist_state
14 number_elements_per_thread;
19 struct lfds710_freelist_element
27 /***** private prototypes *****/
28 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *libtest_threadset_per_thread_state );
29 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *libtest_threadset_per_thread_state );
35 /****************************************************************************/
36 void libtest_tests_freelist_without_ea_popping_and_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_state
51 struct lfds710_misc_validation_info
54 struct libtest_logical_processor
57 struct libtest_threadset_per_thread_state
60 struct libtest_threadset_state
66 struct test_per_thread_state
69 LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
70 LFDS710_PAL_ASSERT( ms != NULL );
71 LFDS710_PAL_ASSERT( dvs != NULL );
73 /* TRD : we have two threads per CPU
74 the threads loop for ten feconds
75 the first thread pushes 10000 elements then pops 10000 elements
76 the fecond thread pops 10000 elements then pushes 10000 elements
77 all pushes and pops go onto the single main freelist
78 with a per-thread local freelist to store the pops
80 after time is up, all threads push what they have remaining onto
83 we then validate the main freelist
86 *dvs = LFDS710_MISC_VALIDITY_VALID;
88 lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
91 tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors * 2, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
92 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 );
93 te_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
95 number_elements_per_thread = number_elements / (number_logical_processors * 2);
97 lfds710_freelist_init_valid_on_current_logical_core( &fs, NULL, 0, NULL );
99 // TRD : half of all elements in the main freelist so the popping threads can start immediately
100 for( loop = 0 ; loop < number_elements_per_thread * number_logical_processors ; loop++ )
102 (te_array+loop)->datum = loop;
103 LFDS710_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+loop)->fe, te_array+loop );
104 lfds710_freelist_push( &fs, &(te_array+loop)->fe, NULL );
107 libtest_threadset_init( &ts, NULL );
111 while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors,lasue) )
113 lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
115 // TRD : first fet of threads (poppers)
116 (tpts+loop)->fs = &fs;
117 (tpts+loop)->number_elements_per_thread = number_elements_per_thread;
118 lfds710_freelist_init_valid_on_current_logical_core( &(tpts+loop)->fs_thread_local, NULL, 0, NULL );
119 libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_popping_and_pushing_start_popping, &tpts[loop] );
121 // TRD : fecond fet of threads (pushers - who need elements in their per-thread freelists)
122 (tpts+loop+number_logical_processors)->fs = &fs;
123 (tpts+loop+number_logical_processors)->number_elements_per_thread = number_elements_per_thread;
124 lfds710_freelist_init_valid_on_current_logical_core( &(tpts+loop+number_logical_processors)->fs_thread_local, NULL, 0, NULL );
125 libtest_threadset_add_thread( &ts, &pts[loop+number_logical_processors], lp, thread_popping_and_pushing_start_pushing, &tpts[loop+number_logical_processors] );
127 for( subloop = number_elements_per_thread * (number_logical_processors + loop) ; subloop < number_elements_per_thread * (number_logical_processors + loop + 1) ; subloop++ )
129 LFDS710_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+subloop)->thread_local_fe, (te_array+subloop) );
130 lfds710_freelist_push( &(tpts+loop+number_logical_processors)->fs_thread_local, &(te_array+subloop)->thread_local_fe, NULL );
136 LFDS710_MISC_BARRIER_STORE;
138 lfds710_misc_force_store();
140 // TRD : run the test
141 libtest_threadset_run( &ts );
143 libtest_threadset_cleanup( &ts );
146 LFDS710_MISC_BARRIER_LOAD;
148 vi.min_elements = vi.max_elements = number_elements_per_thread * number_logical_processors * 2;
150 lfds710_freelist_query( &fs, LFDS710_FREELIST_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) dvs );
152 lfds710_freelist_cleanup( &fs, NULL );
154 for( loop = 0 ; loop < number_logical_processors ; loop++ )
156 lfds710_freelist_cleanup( &(tpts+loop)->fs_thread_local, NULL );
157 lfds710_freelist_cleanup( &(tpts+loop+number_logical_processors)->fs_thread_local, NULL );
168 /****************************************************************************/
169 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *libtest_threadset_per_thread_state )
174 struct lfds710_freelist_element
177 struct test_per_thread_state
180 struct libtest_threadset_per_thread_state
186 LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
188 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
190 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
191 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
193 libtest_threadset_thread_ready_and_wait( pts );
195 start_time = time( NULL );
197 while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
201 while( count < tpts->number_elements_per_thread )
202 if( lfds710_freelist_pop(tpts->fs, &fe, NULL) )
204 lfds710_freelist_push( &tpts->fs_thread_local, fe, NULL );
208 // TRD : return our local freelist to the main freelist
209 while( lfds710_freelist_pop(&tpts->fs_thread_local, &fe, NULL) )
210 lfds710_freelist_push( tpts->fs, fe, NULL );
213 LFDS710_MISC_BARRIER_STORE;
215 lfds710_misc_force_store();
217 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
224 /****************************************************************************/
225 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *libtest_threadset_per_thread_state )
230 struct lfds710_freelist_element
233 struct test_per_thread_state
236 struct libtest_threadset_per_thread_state
242 LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
244 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
246 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
247 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
249 libtest_threadset_thread_ready_and_wait( pts );
251 start_time = time( NULL );
253 while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
255 // TRD : return our local freelist to the main freelist
256 while( lfds710_freelist_pop(&tpts->fs_thread_local, &fe, NULL) )
257 lfds710_freelist_push( tpts->fs, fe, NULL );
261 while( count < tpts->number_elements_per_thread )
262 if( lfds710_freelist_pop(tpts->fs, &fe, NULL) )
264 lfds710_freelist_push( &tpts->fs_thread_local, fe, NULL );
269 // TRD : now push whatever we have in our local freelist
270 while( lfds710_freelist_pop(&tpts->fs_thread_local, &fe, NULL) )
271 lfds710_freelist_push( tpts->fs, fe, NULL );
273 LFDS710_MISC_BARRIER_STORE;
275 lfds710_misc_force_store();
277 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);