12 number_logical_processors,
16 struct lfds700_queue_state
22 struct lfds700_queue_element
31 /***** private prototypes *****/
32 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer_and_dequeuer( void *util_thread_starter_thread_state );
38 /****************************************************************************/
39 void test_lfds700_queue_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors )
41 enum lfds700_misc_validity
42 dvs = LFDS700_MISC_VALIDITY_VALID;
46 number_logical_processors,
49 struct lfds700_list_asu_element
52 struct lfds700_misc_prng_state
55 struct lfds700_queue_state
58 struct lfds700_misc_validation_info
61 struct test_pal_logical_processor
64 struct util_thread_starter_state
73 test_pal_thread_state_t
76 assert( list_of_logical_processors != NULL );
77 // TRD : qt can be any value in its range
79 /* TRD : create a queue with one element per thread
80 each thread constly dequeues and enqueues from that one queue
81 where when enqueuing sets in the element
82 its thread number and counter
83 and when dequeuing, checks the thread number and counter
84 against previously seen counter for that thread
85 where it should always see a higher number
88 internal_display_test_name( "Enqueuing and dequeuing (%d seconds)", TEST_DURATION_IN_SECONDS );
90 lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
92 lfds700_misc_prng_init( &ps );
94 te_array = util_aligned_malloc( sizeof(struct test_element) * (number_logical_processors+1), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
96 lfds700_queue_init_valid_on_current_logical_core( &qs, &(te_array+number_logical_processors)->qe, &ps, NULL );
98 // TRD : we assume the test will iterate at least once (or we'll have a false negative)
99 for( loop = 0 ; loop < number_logical_processors ; loop++ )
101 (te_array+loop)->thread_number = loop;
102 (te_array+loop)->counter = 0;
103 LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (te_array+loop)->qe, te_array+loop );
104 lfds700_queue_enqueue( &qs, &(te_array+loop)->qe, &ps );
107 ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
109 for( loop = 0 ; loop < number_logical_processors ; loop++ )
112 (ts+loop)->thread_number = loop;
113 (ts+loop)->counter = 0;
114 (ts+loop)->error_flag = LOWERED;
115 (ts+loop)->per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
116 (ts+loop)->number_logical_processors = number_logical_processors;
118 for( subloop = 0 ; subloop < number_logical_processors ; subloop++ )
119 *((ts+loop)->per_thread_counters+subloop) = 0;
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_enqueuer_and_dequeuer, 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 vi.min_elements = vi.max_elements = number_logical_processors;
153 lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
155 for( loop = 0 ; loop < number_logical_processors ; loop++ )
156 if( (ts+loop)->error_flag == RAISED )
157 dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
159 for( loop = 0 ; loop < number_logical_processors ; loop++ )
160 free( (ts+loop)->per_thread_counters );
162 util_aligned_free( te_array );
166 lfds700_queue_cleanup( &qs, NULL );
168 internal_display_test_result( 1, "queue", dvs );
177 /****************************************************************************/
178 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer_and_dequeuer( void *util_thread_starter_thread_state )
183 struct lfds700_misc_prng_state
186 struct lfds700_queue_element
195 struct util_thread_starter_thread_state
202 LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
204 assert( util_thread_starter_thread_state != NULL );
206 tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
207 ts = (struct test_state *) tsts->thread_user_state;
209 lfds700_misc_prng_init( &ps );
211 util_thread_starter_ready_and_wait( tsts );
213 current_time = start_time = time( NULL );
215 while( current_time < start_time + TEST_DURATION_IN_SECONDS )
217 lfds700_queue_dequeue( ts->qs, &qe, &ps );
218 te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
220 if( te->thread_number >= ts->number_logical_processors )
221 ts->error_flag = RAISED;
224 if( te->counter < ts->per_thread_counters[te->thread_number] )
225 ts->error_flag = RAISED;
227 if( te->counter >= ts->per_thread_counters[te->thread_number] )
228 ts->per_thread_counters[te->thread_number] = te->counter+1;
231 te->thread_number = ts->thread_number;
232 te->counter = ++ts->counter;
234 LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( *qe, te );
235 lfds700_queue_enqueue( ts->qs, qe, &ps );
237 if( time_loop++ == TIME_LOOP_COUNT )
240 time( ¤t_time );
244 LFDS700_MISC_BARRIER_STORE;
246 lfds700_misc_force_store();
248 return( (test_pal_thread_return_t) EXIT_SUCCESS );