2 #include "libtest_tests_internal.h"
5 struct test_per_thread_state
8 number_elements_per_thread,
11 struct lfds710_queue_umm_state
20 struct lfds710_queue_umm_element
28 /***** private prototypes *****/
29 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_simple_enqueuer( void *libtest_threadset_per_thread_state );
35 /****************************************************************************/
36 void libtest_tests_queue_umm_enqueuing( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
42 number_elements_per_thread,
43 number_logical_processors;
45 struct lfds710_list_asu_element
48 struct lfds710_queue_umm_element LFDS710_PAL_ALIGN(LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES)
51 struct lfds710_queue_umm_element
54 struct lfds710_queue_umm_state
57 struct lfds710_misc_validation_info
60 struct libtest_logical_processor
63 struct libtest_threadset_per_thread_state
66 struct libtest_threadset_state
73 struct test_per_thread_state
76 LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
77 LFDS710_PAL_ASSERT( ms != NULL );
78 LFDS710_PAL_ASSERT( dvs != NULL );
80 /* TRD : create an empty queue
81 then run one thread per CPU
82 where each thread busy-works, enqueuing elements from a freelist (one local freelist per thread)
83 until 100000 elements are enqueued, per thread
84 each element's void pointer of user data is a struct containing thread number and element number
85 where element_number is a thread-local counter starting at 0
87 when we're done, we check that all the elements are present
88 and increment on a per-thread basis
91 *dvs = LFDS710_MISC_VALIDITY_VALID;
93 lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
96 lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
97 tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
98 pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
99 per_thread_counters = libshared_memory_alloc_from_unknown_node( ms, sizeof(lfds710_pal_uint_t) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
100 te_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
102 number_elements_per_thread = number_elements / number_logical_processors;
104 lfds710_queue_umm_init_valid_on_current_logical_core( &qs, &dummy_qe, NULL );
106 libtest_threadset_init( &ts, NULL );
108 while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors,lasue) )
110 lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
111 (tpts+loop)->qs = &qs;
112 (tpts+loop)->thread_number = loop;
113 (tpts+loop)->number_elements_per_thread = number_elements_per_thread;
114 (tpts+loop)->te_array = te_array + loop * number_elements_per_thread;
115 libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_simple_enqueuer, &tpts[loop] );
119 LFDS710_MISC_BARRIER_STORE;
121 lfds710_misc_force_store();
123 // TRD : run the test
124 libtest_threadset_run( &ts );
126 libtest_threadset_cleanup( &ts );
129 LFDS710_MISC_BARRIER_LOAD;
131 /* TRD : first, validate the queue
134 we expect to find element numbers increment on a per thread basis
137 vi.min_elements = vi.max_elements = number_elements_per_thread * number_logical_processors;
139 lfds710_queue_umm_query( &qs, LFDS710_QUEUE_UMM_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
141 for( loop = 0 ; loop < number_logical_processors ; loop++ )
142 *(per_thread_counters+loop) = 0;
144 while( *dvs == LFDS710_MISC_VALIDITY_VALID and lfds710_queue_umm_dequeue(&qs, &qe) )
146 te = LFDS710_QUEUE_UMM_GET_VALUE_FROM_ELEMENT( *qe );
148 if( te->thread_number >= number_logical_processors )
150 *dvs = LFDS710_MISC_VALIDITY_INVALID_TEST_DATA;
154 if( te->counter > per_thread_counters[te->thread_number] )
155 *dvs = LFDS710_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
157 if( te->counter < per_thread_counters[te->thread_number] )
158 *dvs = LFDS710_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
160 if( te->counter == per_thread_counters[te->thread_number] )
161 per_thread_counters[te->thread_number]++;
164 lfds710_queue_umm_cleanup( &qs, NULL );
173 /****************************************************************************/
174 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_simple_enqueuer( void *libtest_threadset_per_thread_state )
179 struct test_per_thread_state
182 struct libtest_threadset_per_thread_state
185 LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
187 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
189 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
190 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
192 for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
194 (tpts->te_array+loop)->thread_number = tpts->thread_number;
195 (tpts->te_array+loop)->counter = loop;
198 libtest_threadset_thread_ready_and_wait( pts );
200 for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
202 LFDS710_QUEUE_UMM_SET_VALUE_IN_ELEMENT( (tpts->te_array+loop)->qe, tpts->te_array+loop );
203 lfds710_queue_umm_enqueue( tpts->qs, &(tpts->te_array+loop)->qe );
206 LFDS710_MISC_BARRIER_STORE;
208 lfds710_misc_force_store();
210 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);