11 struct lfds700_queue_state
17 struct lfds700_queue_element
26 /***** private prototypes *****/
27 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_enqueuer_and_dequeuer( void *util_thread_starter_thread_state );
33 /****************************************************************************/
34 void test_lfds700_queue_rapid_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
36 enum lfds700_misc_validity
37 dvs = LFDS700_MISC_VALIDITY_VALID;
41 number_elements_with_dummy_element,
42 number_elements_without_dummy_element,
43 number_logical_processors,
46 struct lfds700_list_asu_element
49 struct lfds700_misc_prng_state
52 struct lfds700_queue_element
55 struct lfds700_misc_validation_info
58 struct lfds700_queue_state
61 struct test_pal_logical_processor
64 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 create a single queue with 50,000 elements
81 we don't want too many elements, so we ensure plenty of element re-use
82 each thread simply loops dequeuing and enqueuing
83 where the user data indicates thread number and an increment counter
84 vertification is that the counter increments on a per-thread basis
87 internal_display_test_name( "Rapid enqueuing and dequeuing (%d seconds)", TEST_DURATION_IN_SECONDS );
89 lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
91 lfds700_misc_prng_init( &ps );
93 number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct test_element);
95 if( number_elements_with_dummy_element > (10000 * number_logical_processors) + 1 )
96 number_elements_with_dummy_element = (10000 * number_logical_processors) + 1;
98 number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
100 vi.min_elements = number_elements_without_dummy_element;
101 vi.max_elements = number_elements_without_dummy_element;
103 te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
105 lfds700_queue_init_valid_on_current_logical_core( &qs, &(te_array+number_elements_without_dummy_element)->qe, &ps, NULL );
107 // TRD : we assume the test will iterate at least once (or we'll have a false negative)
108 for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
110 (te_array+loop)->thread_number = loop;
111 (te_array+loop)->counter = 0;
112 LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (te_array+loop)->qe, te_array+loop );
113 lfds700_queue_enqueue( &qs, &(te_array+loop)->qe, &ps );
116 ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
118 for( loop = 0 ; loop < number_logical_processors ; loop++ )
121 (ts+loop)->thread_number = loop;
122 (ts+loop)->counter = 0;
125 thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
127 util_thread_starter_new( &tts, number_logical_processors );
129 LFDS700_MISC_BARRIER_STORE;
131 lfds700_misc_force_store();
136 while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
138 lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
139 util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_rapid_enqueuer_and_dequeuer, ts+loop );
143 util_thread_starter_run( tts );
145 for( loop = 0 ; loop < number_logical_processors ; loop++ )
146 test_pal_thread_wait( thread_handles[loop] );
148 util_thread_starter_delete( tts );
150 free( thread_handles );
152 LFDS700_MISC_BARRIER_LOAD;
154 lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
156 // TRD : now check results
157 per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
159 for( loop = 0 ; loop < number_logical_processors ; loop++ )
160 *(per_thread_counters+loop) = 0;
162 while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_queue_dequeue(&qs, &qe, &ps) )
164 te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
166 if( te->thread_number >= number_logical_processors )
168 dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
172 if( per_thread_counters[te->thread_number] == 0 )
173 per_thread_counters[te->thread_number] = te->counter;
175 if( te->counter > per_thread_counters[te->thread_number] )
176 dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
178 if( te->counter < per_thread_counters[te->thread_number] )
179 dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
181 if( te->counter == per_thread_counters[te->thread_number] )
182 per_thread_counters[te->thread_number]++;
185 free( per_thread_counters );
187 lfds700_queue_cleanup( &qs, NULL );
189 util_aligned_free( te_array );
193 internal_display_test_result( 1, "queue", dvs );
202 /****************************************************************************/
203 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_enqueuer_and_dequeuer( void *util_thread_starter_thread_state )
208 struct lfds700_misc_prng_state
211 struct lfds700_queue_element
220 struct util_thread_starter_thread_state
227 LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
229 assert( util_thread_starter_thread_state != NULL );
231 tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
232 ts = (struct test_state *) tsts->thread_user_state;
234 lfds700_misc_prng_init( &ps );
236 util_thread_starter_ready_and_wait( tsts );
238 current_time = start_time = time( NULL );
240 while( current_time < start_time + TEST_DURATION_IN_SECONDS )
242 lfds700_queue_dequeue( ts->qs, &qe, &ps );
243 te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
245 te->thread_number = ts->thread_number;
246 te->counter = ts->counter++;
248 LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( *qe, te );
249 lfds700_queue_enqueue( ts->qs, qe, &ps );
251 if( time_loop++ == TIME_LOOP_COUNT )
254 time( ¤t_time );
258 LFDS700_MISC_BARRIER_STORE;
260 lfds700_misc_force_store();
262 return( (test_pal_thread_return_t) EXIT_SUCCESS );