12 number_logical_processors,
16 struct lfds700_ringbuffer_state
27 /***** private prototypes *****/
28 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_reader_writer( void *util_thread_starter_thread_state );
34 /****************************************************************************/
35 void test_lfds700_ringbuffer_reading_and_writing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
37 enum lfds700_misc_validity
38 dvs[2] = { LFDS700_MISC_VALIDITY_VALID, LFDS700_MISC_VALIDITY_VALID };
42 number_elements_with_dummy_element,
43 number_elements_without_dummy_element,
44 number_logical_processors,
47 test_pal_thread_state_t
50 struct lfds700_list_asu_element
53 struct lfds700_misc_prng_state
56 struct lfds700_ringbuffer_element
59 struct lfds700_ringbuffer_state
62 struct lfds700_misc_validation_info
65 struct test_pal_logical_processor
68 struct util_thread_starter_state
77 assert( list_of_logical_processors != NULL );
78 // TRD : memory_in_megabytes can be any value in its range
80 /* TRD : we create a single ringbuffer
82 the ringbuffers starts empty
84 we create one thread per CPU
85 where each thread busy-works writing
86 and then immediately reading
89 the user data in each written element is a combination
90 of the thread number and the counter
92 while a thread runs, it keeps track of the
93 counters for the other threads and throws an error
94 if it sees the number stay the same or decrease
97 internal_display_test_name( "Reading and writing (%d seconds)", TEST_DURATION_IN_SECONDS );
99 lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
101 lfds700_misc_prng_init( &ps );
103 number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) + sizeof(struct lfds700_ringbuffer_element) );
104 number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
107 vi.max_elements = number_elements_without_dummy_element;
109 re_array = util_aligned_malloc( sizeof(struct lfds700_ringbuffer_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
111 lfds700_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements_with_dummy_element, &ps, NULL );
113 te_array = util_malloc_wrapper( sizeof(struct test_element) * number_elements_without_dummy_element );
115 // TRD : populate the ringbuffer
116 for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
118 te_array[loop].thread_number = 0;
119 te_array[loop].datum = (lfds700_pal_uint_t) -1 ;
120 lfds700_ringbuffer_write( &rs, NULL, &te_array[loop], NULL, NULL, NULL, &ps );
123 ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
125 for( loop = 0 ; loop < number_logical_processors ; loop++ )
128 (ts+loop)->thread_number = loop;
129 (ts+loop)->counter = 0;
130 (ts+loop)->number_logical_processors = number_logical_processors;
131 (ts+loop)->error_flag = LOWERED;
132 (ts+loop)->per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
134 for( subloop = 0 ; subloop < number_logical_processors ; subloop++ )
135 *((ts+loop)->per_thread_counters+subloop) = 0;
138 thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
140 util_thread_starter_new( &tts, number_logical_processors );
142 LFDS700_MISC_BARRIER_STORE;
144 lfds700_misc_force_store();
149 while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
151 lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
152 util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_reader_writer, ts+loop );
156 util_thread_starter_run( tts );
158 for( loop = 0 ; loop < number_logical_processors ; loop++ )
159 test_pal_thread_wait( thread_handles[loop] );
161 util_thread_starter_delete( tts );
163 free( thread_handles );
165 LFDS700_MISC_BARRIER_LOAD;
167 lfds700_ringbuffer_query( &rs, LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) dvs );
169 for( loop = 0 ; loop < number_logical_processors ; loop++ )
170 if( (ts+loop)->error_flag == RAISED )
171 dvs[0] = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
173 for( loop = 0 ; loop < number_logical_processors ; loop++ )
174 free( (ts+loop)->per_thread_counters );
178 lfds700_ringbuffer_cleanup( &rs, NULL );
180 util_aligned_free( re_array );
184 internal_display_test_result( 2, "queue", dvs[0], "freelist", dvs[1] );
193 /****************************************************************************/
194 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_reader_writer( void *util_thread_starter_thread_state )
199 struct lfds700_misc_prng_state
208 struct util_thread_starter_thread_state
215 LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
217 assert( util_thread_starter_thread_state != NULL );
219 tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
220 ts = (struct test_state *) tsts->thread_user_state;
222 lfds700_misc_prng_init( &ps );
224 util_thread_starter_ready_and_wait( tsts );
226 current_time = start_time = time( NULL );
228 while( current_time < start_time + TEST_DURATION_IN_SECONDS )
230 lfds700_ringbuffer_read( ts->rs, NULL, (void **) &te, &ps );
232 if( te->thread_number >= ts->number_logical_processors )
233 ts->error_flag = RAISED;
236 if( te->datum < ts->per_thread_counters[te->thread_number] )
237 ts->error_flag = RAISED;
239 if( te->datum >= ts->per_thread_counters[te->thread_number] )
240 ts->per_thread_counters[te->thread_number] = te->datum+1;
243 te->thread_number = ts->thread_number;
244 te->datum = ts->counter++;
246 lfds700_ringbuffer_write( ts->rs, NULL, te, NULL, NULL, NULL, &ps );
248 if( time_loop++ == TIME_LOOP_COUNT )
251 time( ¤t_time );
255 LFDS700_MISC_BARRIER_STORE;
257 lfds700_misc_force_store();
259 return( (test_pal_thread_return_t) EXIT_SUCCESS );