21 struct lfds700_ringbuffer_state
25 /***** private prototypes *****/
26 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_writer( void *util_thread_starter_thread_state );
32 /****************************************************************************/
33 void test_lfds700_ringbuffer_writing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
35 enum lfds700_misc_validity
36 dvs[2] = { LFDS700_MISC_VALIDITY_VALID, LFDS700_MISC_VALIDITY_VALID };
40 number_elements_with_dummy_element,
41 number_elements_without_dummy_element,
42 number_logical_processors,
45 test_pal_thread_state_t
48 struct lfds700_list_asu_element
51 struct lfds700_misc_prng_state
54 struct lfds700_ringbuffer_element
57 struct lfds700_ringbuffer_state
60 struct lfds700_misc_validation_info
63 struct test_pal_logical_processor
66 struct util_thread_starter_state
76 assert( list_of_logical_processors != NULL );
77 // TRD : memory_in_megabytes can be any value in its range
79 /* TRD : we create a single ringbuffer
81 we create n test elements
82 which are thread_number/counter pairs
83 init them to safe values
84 and fully populate the ringbuffer
86 we create one thread per CPU
87 where each thread busy-works writing
88 for ten seconds; each thread has one extra element
89 which it uses for the first write and after that
90 it uses the element it picks up from overwriting
92 the user data in each written element is a combination
93 of the thread number and the counter
95 after the threads are complete, we validate by
96 checking the user data counters increment on a per thread
100 internal_display_test_name( "Writing (%d seconds)", TEST_DURATION_IN_SECONDS );
102 lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
104 lfds700_misc_prng_init( &ps );
106 number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) + sizeof(struct lfds700_ringbuffer_element) );
107 number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
109 vi.min_elements = number_elements_without_dummy_element;
110 vi.max_elements = number_elements_without_dummy_element;
112 re_array = util_aligned_malloc( sizeof(struct lfds700_ringbuffer_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
114 lfds700_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements_with_dummy_element, &ps, NULL );
116 te_array = util_malloc_wrapper( sizeof(struct lfds700_ringbuffer_element) * number_elements_without_dummy_element );
118 // TRD : init the test elements and write them into the ringbuffer
119 for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
121 te_array[loop].thread_number = 0;
122 te_array[loop].datum = 0;
123 lfds700_ringbuffer_write( &rs, NULL, &te_array[loop], NULL, NULL, NULL, &ps );
126 ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
128 for( loop = 0 ; loop < number_logical_processors ; loop++ )
131 (ts+loop)->thread_number = loop;
132 (ts+loop)->write_count = 0;
135 thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
137 util_thread_starter_new( &tts, number_logical_processors );
139 LFDS700_MISC_BARRIER_STORE;
141 lfds700_misc_force_store();
146 while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
148 lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
149 util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_writer, ts+loop );
153 util_thread_starter_run( tts );
155 for( loop = 0 ; loop < number_logical_processors ; loop++ )
156 test_pal_thread_wait( thread_handles[loop] );
158 util_thread_starter_delete( tts );
160 free( thread_handles );
162 LFDS700_MISC_BARRIER_LOAD;
164 // TRD : now check results
165 per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
167 for( loop = 0 ; loop < number_logical_processors ; loop++ )
168 *(per_thread_counters+loop) = 0;
170 lfds700_ringbuffer_query( &rs, LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
172 while( dvs[0] == LFDS700_MISC_VALIDITY_VALID and dvs[1] == LFDS700_MISC_VALIDITY_VALID and lfds700_ringbuffer_read(&rs, NULL, (void **) &te, &ps) )
174 if( te->thread_number >= number_logical_processors )
176 dvs[0] = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
180 if( per_thread_counters[te->thread_number] == 0 )
181 per_thread_counters[te->thread_number] = te->datum;
183 if( te->datum < per_thread_counters[te->thread_number] )
184 dvs[0] = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
186 if( te->datum >= per_thread_counters[te->thread_number] )
187 per_thread_counters[te->thread_number] = te->datum+1;
190 free( per_thread_counters );
192 lfds700_ringbuffer_cleanup( &rs, NULL );
196 util_aligned_free( re_array );
200 internal_display_test_result( 2, "queue", dvs[0], "freelist", dvs[1] );
209 /****************************************************************************/
210 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_writer( void *util_thread_starter_thread_state )
212 enum lfds700_misc_flag
213 overwrite_occurred_flag;
218 struct lfds700_misc_prng_state
227 struct util_thread_starter_thread_state
234 LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
236 assert( util_thread_starter_thread_state != NULL );
238 tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
239 ts = (struct test_state *) tsts->thread_user_state;
241 lfds700_misc_prng_init( &ps );
243 ts->te.thread_number = 0;
246 lfds700_ringbuffer_write( ts->rs, NULL, &ts->te, &overwrite_occurred_flag, NULL, (void **) &te, &ps );
248 util_thread_starter_ready_and_wait( tsts );
250 current_time = start_time = time( NULL );
252 while( current_time < start_time + TEST_DURATION_IN_SECONDS )
254 te->thread_number = ts->thread_number;
255 te->datum = ts->write_count++;
257 lfds700_ringbuffer_write( ts->rs, NULL, te, &overwrite_occurred_flag, NULL, (void **) &te, &ps );
259 if( time_loop++ == TIME_LOOP_COUNT )
262 time( ¤t_time );
266 LFDS700_MISC_BARRIER_STORE;
268 lfds700_misc_force_store();
270 return( (test_pal_thread_return_t) EXIT_SUCCESS );