11 struct lfds700_queue_state
20 struct lfds700_queue_element
28 /***** private prototypes *****/
29 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_enqueuer( void *util_thread_starter_thread_state );
35 /****************************************************************************/
36 void test_lfds700_queue_enqueuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
38 enum lfds700_misc_validity
39 dvs = LFDS700_MISC_VALIDITY_VALID;
45 number_logical_processors;
47 struct lfds700_list_asu_element
50 struct lfds700_misc_prng_state
53 struct lfds700_queue_element
57 struct lfds700_queue_state
60 struct lfds700_misc_validation_info
63 struct test_pal_logical_processor
66 struct util_thread_starter_state
75 test_pal_thread_state_t
78 assert( list_of_logical_processors != NULL );
79 // TRD : memory_in_megabytes can be any value in its range
81 /* TRD : create an empty queue
82 then run one thread per CPU
83 where each thread busy-works, enqueuing elements from a freelist (one local freelist per thread)
84 until 100000 elements are enqueued, per thread
85 each element's void pointer of user data is a struct containing thread number and element number
86 where element_number is a thread-local counter starting at 0
88 when we're done, we check that all the elements are present
89 and increment on a per-thread basis
92 internal_display_test_name( "Enqueuing" );
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 );
100 lfds700_queue_init_valid_on_current_logical_core( &qs, &dummy_qe, &ps, NULL );
102 ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
104 for( loop = 0 ; loop < number_logical_processors ; loop++ )
107 (ts+loop)->thread_number = loop;
108 (ts+loop)->number_elements = number_elements;
111 thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
113 util_thread_starter_new( &tts, number_logical_processors );
115 LFDS700_MISC_BARRIER_STORE;
117 lfds700_misc_force_store();
122 while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
124 lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
125 util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_enqueuer, ts+loop );
129 util_thread_starter_run( tts );
131 for( loop = 0 ; loop < number_logical_processors ; loop++ )
132 test_pal_thread_wait( thread_handles[loop] );
134 util_thread_starter_delete( tts );
136 free( thread_handles );
138 LFDS700_MISC_BARRIER_LOAD;
140 /* TRD : first, validate the queue
143 we expect to find element numbers increment on a per thread basis
146 vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
148 lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
150 per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
152 for( loop = 0 ; loop < number_logical_processors ; loop++ )
153 *(per_thread_counters+loop) = 0;
155 while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_queue_dequeue(&qs, &qe, &ps) )
157 te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
159 if( te->thread_number >= number_logical_processors )
161 dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
165 if( te->counter > per_thread_counters[te->thread_number] )
166 dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
168 if( te->counter < per_thread_counters[te->thread_number] )
169 dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
171 if( te->counter == per_thread_counters[te->thread_number] )
172 per_thread_counters[te->thread_number]++;
175 free( per_thread_counters );
177 for( loop = 0 ; loop < number_logical_processors ; loop++ )
178 util_aligned_free( (ts+loop)->te_array );
182 lfds700_queue_cleanup( &qs, NULL );
184 internal_display_test_result( 1, "queue", dvs );
193 /****************************************************************************/
194 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_enqueuer( void *util_thread_starter_thread_state )
199 struct lfds700_misc_prng_state
205 struct util_thread_starter_thread_state
208 LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
210 assert( util_thread_starter_thread_state != NULL );
212 tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
213 ts = (struct test_state *) tsts->thread_user_state;
215 lfds700_misc_prng_init( &ps );
217 ts->te_array = util_aligned_malloc( sizeof(struct test_element) * ts->number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
219 for( loop = 0 ; loop < ts->number_elements ; loop++ )
221 (ts->te_array+loop)->thread_number = ts->thread_number;
222 (ts->te_array+loop)->counter = loop;
225 util_thread_starter_ready_and_wait( tsts );
227 for( loop = 0 ; loop < ts->number_elements ; loop++ )
229 LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (ts->te_array+loop)->qe, ts->te_array+loop );
230 lfds700_queue_enqueue( ts->qs, &(ts->te_array+loop)->qe, &ps );
233 LFDS700_MISC_BARRIER_STORE;
235 lfds700_misc_force_store();
237 return( (test_pal_thread_return_t) EXIT_SUCCESS );