2 #include "libtest_tests_internal.h"
5 struct test_per_thread_state
11 struct lfds710_queue_umm_state
17 struct lfds710_queue_umm_element
26 /***** private prototypes *****/
27 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_rapid_enqueuer_and_dequeuer( void *libtest_threadset_per_thread_state );
33 /****************************************************************************/
34 void libtest_tests_queue_umm_rapid_enqueuing_and_dequeuing( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
38 number_logical_processors,
41 struct lfds710_list_asu_element
44 struct lfds710_queue_umm_element LFDS710_PAL_ALIGN(LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES)
47 struct lfds710_queue_umm_element
50 struct lfds710_misc_validation_info
53 struct lfds710_queue_umm_state
56 struct libtest_logical_processor
59 struct libtest_threadset_per_thread_state
62 struct libtest_threadset_state
69 struct test_per_thread_state
72 LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
73 LFDS710_PAL_ASSERT( ms != NULL );
74 LFDS710_PAL_ASSERT( dvs != NULL );
76 /* TRD : we create a single queue with 50,000 elements
77 we don't want too many elements, so we ensure plenty of element re-use
78 each thread simply loops dequeuing and enqueuing
79 where the user data indicates thread number and an increment counter
80 vertification is that the counter increments on a per-thread basis
83 *dvs = LFDS710_MISC_VALIDITY_VALID;
85 lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
87 lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
88 tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
89 pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
90 per_thread_counters = libshared_memory_alloc_from_unknown_node( ms, sizeof(lfds710_pal_uint_t) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
91 te_array = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_element) * 10000 * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
93 vi.min_elements = vi.max_elements = 10000;
95 lfds710_queue_umm_init_valid_on_current_logical_core( &qs, &qe_dummy, NULL );
97 // TRD : we assume the test will iterate at least once (or we'll have a false negative)
98 for( loop = 0 ; loop < 10000 ; loop++ )
100 (te_array+loop)->thread_number = loop;
101 (te_array+loop)->counter = 0;
102 LFDS710_QUEUE_UMM_SET_VALUE_IN_ELEMENT( (te_array+loop)->qe, te_array+loop );
103 lfds710_queue_umm_enqueue( &qs, &(te_array+loop)->qe );
106 libtest_threadset_init( &ts, NULL );
110 while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors,lasue) )
112 lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
113 (tpts+loop)->qs = &qs;
114 (tpts+loop)->thread_number = loop;
115 (tpts+loop)->counter = 0;
116 libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_rapid_enqueuer_and_dequeuer, &tpts[loop] );
120 // TRD : run the test
121 libtest_threadset_run( &ts );
123 libtest_threadset_cleanup( &ts );
126 LFDS710_MISC_BARRIER_LOAD;
128 lfds710_queue_umm_query( &qs, LFDS710_QUEUE_UMM_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
130 // TRD : now check results
131 for( loop = 0 ; loop < number_logical_processors ; loop++ )
132 *(per_thread_counters+loop) = 0;
134 while( *dvs == LFDS710_MISC_VALIDITY_VALID and lfds710_queue_umm_dequeue(&qs, &qe) )
136 te = LFDS710_QUEUE_UMM_GET_VALUE_FROM_ELEMENT( *qe );
138 if( te->thread_number >= number_logical_processors )
140 *dvs = LFDS710_MISC_VALIDITY_INVALID_TEST_DATA;
144 if( per_thread_counters[te->thread_number] == 0 )
145 per_thread_counters[te->thread_number] = te->counter;
147 if( te->counter > per_thread_counters[te->thread_number] )
148 *dvs = LFDS710_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
150 if( te->counter < per_thread_counters[te->thread_number] )
151 *dvs = LFDS710_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
153 if( te->counter == per_thread_counters[te->thread_number] )
154 per_thread_counters[te->thread_number]++;
157 lfds710_queue_umm_cleanup( &qs, NULL );
166 /****************************************************************************/
167 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_rapid_enqueuer_and_dequeuer( void *libtest_threadset_per_thread_state )
172 struct lfds710_queue_umm_element
178 struct test_per_thread_state
181 struct libtest_threadset_per_thread_state
188 LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
190 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
192 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
193 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
195 libtest_threadset_thread_ready_and_wait( pts );
197 current_time = start_time = time( NULL );
199 while( current_time < start_time + TEST_DURATION_IN_SECONDS )
201 lfds710_queue_umm_dequeue( tpts->qs, &qe );
202 te = LFDS710_QUEUE_UMM_GET_VALUE_FROM_ELEMENT( *qe );
204 te->thread_number = tpts->thread_number;
205 te->counter = tpts->counter++;
207 LFDS710_QUEUE_UMM_SET_VALUE_IN_ELEMENT( *qe, te );
208 lfds710_queue_umm_enqueue( tpts->qs, qe );
210 if( time_loop++ == TIME_LOOP_COUNT )
213 time( ¤t_time );
217 LFDS710_MISC_BARRIER_STORE;
219 lfds710_misc_force_store();
221 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);