2 #include "libtest_tests_internal.h"
12 struct test_per_thread_state
21 struct lfds710_ringbuffer_state
25 /***** private prototypes *****/
26 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_simple_writer( void *libtest_threadset_per_thread_state );
32 /****************************************************************************/
33 void libtest_tests_ringbuffer_writing( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
35 enum lfds710_misc_validity
36 local_dvs[2] = { LFDS710_MISC_VALIDITY_VALID, LFDS710_MISC_VALIDITY_VALID };
41 number_logical_processors,
44 struct lfds710_list_asu_element
47 struct lfds710_ringbuffer_element
50 struct lfds710_ringbuffer_state
53 struct lfds710_misc_validation_info
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 ringbuffer
78 we create n test elements
79 which are thread_number/counter pairs
80 init them to safe values
81 and fully populate the ringbuffer
83 we create one thread per CPU
84 where each thread busy-works writing
85 for ten seconds; each thread has one extra element
86 which it uses for the first write and after that
87 it uses the element it picks up from overwriting
89 the user data in each written element is a combination
90 of the thread number and the counter
92 after the threads are complete, we validate by
93 checking the user data counters increment on a per thread
97 *dvs = LFDS710_MISC_VALIDITY_VALID;
99 lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
102 tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
103 pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
104 per_thread_counters = libshared_memory_alloc_from_unknown_node( ms, sizeof(lfds710_pal_uint_t) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
105 re_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element) + sizeof(struct lfds710_ringbuffer_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
106 te_array = (struct test_element *) ( re_array + number_elements );
108 vi.min_elements = number_elements;
109 vi.max_elements = number_elements;
111 lfds710_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements, NULL );
113 // TRD : init the test elements and write them into the ringbuffer
114 for( loop = 1 ; loop < number_elements ; loop++ )
116 te_array[loop].thread_number = 0;
117 te_array[loop].datum = 0;
118 lfds710_ringbuffer_write( &rs, NULL, &te_array[loop], NULL, NULL, NULL );
121 libtest_threadset_init( &ts, NULL );
125 while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors,lasue) )
127 lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
128 (tpts+loop)->rs = &rs;
129 (tpts+loop)->thread_number = loop;
130 (tpts+loop)->write_count = 0;
132 libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_simple_writer, &tpts[loop] );
137 // TRD : run the test
138 libtest_threadset_run( &ts );
140 libtest_threadset_cleanup( &ts );
143 LFDS710_MISC_BARRIER_LOAD;
145 // TRD : now check results
146 for( loop = 0 ; loop < number_logical_processors ; loop++ )
147 *(per_thread_counters+loop) = 0;
149 lfds710_ringbuffer_query( &rs, LFDS710_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, &vi, (void *) local_dvs );
151 if( local_dvs[0] != LFDS710_MISC_VALIDITY_VALID )
154 if( local_dvs[1] != LFDS710_MISC_VALIDITY_VALID )
157 while( *dvs == LFDS710_MISC_VALIDITY_VALID and lfds710_ringbuffer_read(&rs, NULL, (void **) &te) )
159 if( te->thread_number >= number_logical_processors )
161 *dvs = LFDS710_MISC_VALIDITY_INVALID_TEST_DATA;
165 if( per_thread_counters[te->thread_number] == 0 )
166 per_thread_counters[te->thread_number] = te->datum;
168 if( te->datum < per_thread_counters[te->thread_number] )
169 *dvs = LFDS710_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
171 if( te->datum >= per_thread_counters[te->thread_number] )
172 per_thread_counters[te->thread_number] = te->datum+1;
175 lfds710_ringbuffer_cleanup( &rs, NULL );
184 /****************************************************************************/
185 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_simple_writer( void *libtest_threadset_per_thread_state )
187 enum lfds710_misc_flag
188 overwrite_occurred_flag;
193 struct libtest_threadset_per_thread_state
199 struct test_per_thread_state
206 LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
208 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
210 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
211 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
213 tpts->te.thread_number = 0;
216 lfds710_ringbuffer_write( tpts->rs, NULL, &tpts->te, &overwrite_occurred_flag, NULL, (void **) &te );
218 libtest_threadset_thread_ready_and_wait( pts );
220 current_time = start_time = time( NULL );
222 while( current_time < start_time + TEST_DURATION_IN_SECONDS )
224 te->thread_number = tpts->thread_number;
225 te->datum = tpts->write_count++;
227 lfds710_ringbuffer_write( tpts->rs, NULL, te, &overwrite_occurred_flag, NULL, (void **) &te );
229 if( time_loop++ == TIME_LOOP_COUNT )
232 time( ¤t_time );
236 LFDS710_MISC_BARRIER_STORE;
238 lfds710_misc_force_store();
240 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);