10 struct lfds700_queue_state
16 struct lfds700_queue_element
20 /***** private prototypes *****/
21 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_dequeuer( void *util_thread_starter_thread_state );
27 /****************************************************************************/
28 void test_lfds700_queue_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
30 enum lfds700_misc_validity
31 dvs = LFDS700_MISC_VALIDITY_VALID;
35 number_elements_with_dummy_element,
36 number_elements_without_dummy_element,
37 number_logical_processors;
39 struct lfds700_list_asu_element
42 struct lfds700_misc_prng_state
45 struct lfds700_queue_state
48 struct lfds700_misc_validation_info
51 struct test_pal_logical_processor
54 struct util_thread_starter_state
63 test_pal_thread_state_t
66 assert( list_of_logical_processors != NULL );
67 // TRD : memory_in_megabytes can be any value in its range
69 /* TRD : create a queue, add 1,000,000 elements
71 use a single thread to enqueue every element
72 each elements user data is an incrementing counter
74 then run one thread per CPU
75 where each busy-works dequeuing
77 when an element is dequeued, we check (on a per-thread basis) the
78 value dequeued is greater than the element previously dequeued
80 note we have no variation in the test for CAS+GC vs DWCAS
81 this is because all we do is dequeue
82 what we actually want to stress test is the queue
84 so it's better to let the dequeue run as fast as possible
87 internal_display_test_name( "Dequeuing" );
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);
94 number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
96 te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
98 lfds700_queue_init_valid_on_current_logical_core( &qs, &(te_array + number_elements_without_dummy_element)->qe, &ps, NULL );
100 for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
102 LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (te_array+loop)->qe, loop );
103 lfds700_queue_enqueue( &qs, &(te_array+loop)->qe, &ps );
106 ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
108 for( loop = 0 ; loop < number_logical_processors ; loop++ )
111 (ts+loop)->error_flag = LOWERED;
114 thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
116 util_thread_starter_new( &tts, number_logical_processors );
118 LFDS700_MISC_BARRIER_STORE;
120 lfds700_misc_force_store();
125 while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
127 lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
128 util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_dequeuer, ts+loop );
132 util_thread_starter_run( tts );
134 for( loop = 0 ; loop < number_logical_processors ; loop++ )
135 test_pal_thread_wait( thread_handles[loop] );
137 util_thread_starter_delete( tts );
139 free( thread_handles );
141 LFDS700_MISC_BARRIER_LOAD;
143 // TRD : check queue is empty
144 lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
146 // TRD : check for raised error flags
147 for( loop = 0 ; loop < number_logical_processors ; loop++ )
148 if( (ts+loop)->error_flag == RAISED )
149 dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
153 util_aligned_free( te_array );
155 lfds700_queue_cleanup( &qs, NULL );
157 internal_display_test_result( 1, "queue", dvs );
166 /****************************************************************************/
167 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_dequeuer( void *util_thread_starter_thread_state )
173 struct lfds700_misc_prng_state
176 struct lfds700_queue_element
182 struct util_thread_starter_thread_state
185 LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
187 assert( util_thread_starter_thread_state != NULL );
189 tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
190 ts = (struct test_state *) tsts->thread_user_state;
192 lfds700_misc_prng_init( &ps );
194 lfds700_queue_dequeue( ts->qs, &qe, &ps );
195 prev_value = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
197 util_thread_starter_ready_and_wait( tsts );
199 while( lfds700_queue_dequeue(ts->qs, &qe, &ps) )
201 value = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
203 if( value <= prev_value )
204 ts->error_flag = RAISED;
209 LFDS700_MISC_BARRIER_STORE;
211 lfds700_misc_force_store();
213 return( (test_pal_thread_return_t) EXIT_SUCCESS );