7 /****************************************************************************/
8 void test_lfds610_ringbuffer( void )
12 "================\n" );
14 ringbuffer_test_reading();
15 ringbuffer_test_writing();
16 ringbuffer_test_reading_and_writing();
25 /****************************************************************************/
26 void ringbuffer_test_reading( void )
35 struct lfds610_ringbuffer_state
38 struct lfds610_freelist_element
41 struct ringbuffer_test_reading_state
44 struct lfds610_validation_info
47 enum lfds610_data_structure_validity
53 /* TRD : we create a single ringbuffer
54 with 1,000,000 elements
55 we populate the ringbuffer, where the
56 user data is an incrementing counter
58 we create one thread per CPU
59 where each thread busy-works,
60 reading until the ringbuffer is empty
62 each thread keeps track of the number of reads it manages
63 and that each user data it reads is greater than the
64 previous user data that was read
67 internal_display_test_name( "Reading" );
69 cpu_count = abstraction_cpu_count();
71 lfds610_ringbuffer_new( &rs, 1000000, NULL, NULL );
73 for( loop = 0 ; loop < 1000000 ; loop++ )
75 lfds610_ringbuffer_get_write_element( rs, &fe, NULL );
76 lfds610_freelist_set_user_data_in_element( fe, (void *) (lfds610_atom_t) loop );
77 lfds610_ringbuffer_put_write_element( rs, fe );
80 rtrs = malloc( sizeof(struct ringbuffer_test_reading_state) * cpu_count );
82 for( loop = 0 ; loop < cpu_count ; loop++ )
85 (rtrs+loop)->read_count = 0;
86 (rtrs+loop)->error_flag = LOWERED;
89 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
91 for( loop = 0 ; loop < cpu_count ; loop++ )
92 abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_reader, rtrs+loop );
94 for( loop = 0 ; loop < cpu_count ; loop++ )
95 abstraction_thread_wait( thread_handles[loop] );
97 free( thread_handles );
99 lfds610_ringbuffer_query( rs, LFDS610_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
101 // TRD : check for raised error flags
102 for( loop = 0 ; loop < cpu_count ; loop++ )
103 if( (rtrs+loop)->error_flag == RAISED )
104 dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA;
106 // TRD : check thread reads total to 1,000,000
107 for( loop = 0 ; loop < cpu_count ; loop++ )
108 total_read += (rtrs+loop)->read_count;
110 if( total_read < 1000000 )
111 dvs[0] = LFDS610_VALIDITY_INVALID_MISSING_ELEMENTS;
113 if( total_read > 1000000 )
114 dvs[0] = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
118 lfds610_ringbuffer_delete( rs, NULL, NULL );
120 internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
129 /****************************************************************************/
130 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state )
132 struct ringbuffer_test_reading_state
135 struct lfds610_freelist_element
142 assert( ringbuffer_test_reading_state != NULL );
144 rtrs = (struct ringbuffer_test_reading_state *) ringbuffer_test_reading_state;
146 lfds610_ringbuffer_use( rtrs->rs );
148 /* TRD : read an initial element to load a value into prev_user_data
149 it may be (under valgrind for example) that by the time we start
150 there are no elements remaining to read
153 lfds610_ringbuffer_get_read_element( rtrs->rs, &fe );
155 return( (thread_return_t) EXIT_SUCCESS );
156 lfds610_freelist_get_user_data_from_element( fe, (void **) &prev_user_data );
157 lfds610_ringbuffer_put_read_element( rtrs->rs, fe );
161 while( lfds610_ringbuffer_get_read_element(rtrs->rs, &fe) )
163 lfds610_freelist_get_user_data_from_element( fe, (void **) &user_data );
164 lfds610_ringbuffer_put_read_element( rtrs->rs, fe );
166 if( user_data <= prev_user_data )
167 rtrs->error_flag = RAISED;
169 prev_user_data = user_data;
174 return( (thread_return_t) EXIT_SUCCESS );
181 /****************************************************************************/
182 void ringbuffer_test_writing( void )
191 struct lfds610_ringbuffer_state
194 struct lfds610_freelist_element
197 struct ringbuffer_test_writing_state
200 struct lfds610_validation_info
201 vi = { 100000, 100000 };
203 enum lfds610_data_structure_validity
210 *per_thread_counters;
212 /* TRD : we create a single ringbuffer
214 the ringbuffers starts empty
216 we create one thread per CPU
217 where each thread busy-works writing
220 the user data in each written element is a combination
221 of the thread number and the counter
223 after the threads are complete, we validate by
224 checking the user data counters increment on a per thread
228 internal_display_test_name( "Writing (10 seconds)" );
230 cpu_count = abstraction_cpu_count();
232 lfds610_ringbuffer_new( &rs, 100000, NULL, NULL );
234 rtws = malloc( sizeof(struct ringbuffer_test_writing_state) * cpu_count );
236 for( loop = 0 ; loop < cpu_count ; loop++ )
238 (rtws+loop)->rs = rs;
239 (rtws+loop)->write_count = (lfds610_atom_t) loop << (sizeof(lfds610_atom_t)*8-8);
242 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
244 for( loop = 0 ; loop < cpu_count ; loop++ )
245 abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_writer, rtws+loop );
247 for( loop = 0 ; loop < cpu_count ; loop++ )
248 abstraction_thread_wait( thread_handles[loop] );
250 free( thread_handles );
252 // TRD : now check results
253 per_thread_counters = malloc( sizeof(lfds610_atom_t) * cpu_count );
255 for( loop = 0 ; loop < cpu_count ; loop++ )
256 *(per_thread_counters+loop) = 0;
258 lfds610_ringbuffer_query( rs, LFDS610_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
260 while( dvs[0] == LFDS610_VALIDITY_VALID and dvs[1] == LFDS610_VALIDITY_VALID and dvs[2] == LFDS610_VALIDITY_VALID and lfds610_ringbuffer_get_read_element(rs, &fe) )
262 lfds610_freelist_get_user_data_from_element( fe, (void *) &user_data );
264 thread = user_data >> (sizeof(lfds610_atom_t)*8-8);
265 count = (user_data << 8) >> 8;
267 if( thread >= cpu_count )
269 dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA;
270 lfds610_ringbuffer_put_read_element( rs, fe );
274 if( per_thread_counters[thread] == 0 )
275 per_thread_counters[thread] = count;
277 if( count < per_thread_counters[thread] )
278 dvs[0] = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
280 if( count >= per_thread_counters[thread] )
281 per_thread_counters[thread] = count+1;
283 lfds610_ringbuffer_put_read_element( rs, fe );
286 free( per_thread_counters );
290 lfds610_ringbuffer_delete( rs, NULL, NULL );
292 internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
301 /****************************************************************************/
302 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state )
304 struct ringbuffer_test_writing_state
307 struct lfds610_freelist_element
313 assert( ringbuffer_test_writing_state != NULL );
315 rtws = (struct ringbuffer_test_writing_state *) ringbuffer_test_writing_state;
317 lfds610_ringbuffer_use( rtws->rs );
321 while( time(NULL) < start_time + 10 )
323 lfds610_ringbuffer_get_write_element( rtws->rs, &fe, NULL );
324 lfds610_freelist_set_user_data_in_element( fe, (void *) (lfds610_atom_t) (rtws->write_count++) );
325 lfds610_ringbuffer_put_write_element( rtws->rs, fe );
328 return( (thread_return_t) EXIT_SUCCESS );
335 /****************************************************************************/
336 void ringbuffer_test_reading_and_writing( void )
346 struct lfds610_ringbuffer_state
349 struct ringbuffer_test_reading_and_writing_state
352 struct lfds610_validation_info
355 enum lfds610_data_structure_validity
358 /* TRD : we create a single ringbuffer
360 the ringbuffers starts empty
362 we create one thread per CPU
363 where each thread busy-works writing
364 and then immediately reading
367 the user data in each written element is a combination
368 of the thread number and the counter
370 while a thread runs, it keeps track of the
371 counters for the other threads and throws an error
372 if it sees the number stay the same or decrease
375 internal_display_test_name( "Reading and writing (10 seconds)" );
377 cpu_count = abstraction_cpu_count();
379 lfds610_ringbuffer_new( &rs, 100000, NULL, NULL );
381 rtrws = malloc( sizeof(struct ringbuffer_test_reading_and_writing_state) * cpu_count );
383 for( loop = 0 ; loop < cpu_count ; loop++ )
385 (rtrws+loop)->rs = rs;
386 (rtrws+loop)->counter = (lfds610_atom_t) loop << (sizeof(lfds610_atom_t)*8-8);
387 (rtrws+loop)->cpu_count = cpu_count;
388 (rtrws+loop)->error_flag = LOWERED;
389 (rtrws+loop)->per_thread_counters = malloc( sizeof(lfds610_atom_t) * cpu_count );
391 for( subloop = 0 ; subloop < cpu_count ; subloop++ )
392 *((rtrws+loop)->per_thread_counters+subloop) = 0;
395 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
397 for( loop = 0 ; loop < cpu_count ; loop++ )
398 abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_reader_writer, rtrws+loop );
400 for( loop = 0 ; loop < cpu_count ; loop++ )
401 abstraction_thread_wait( thread_handles[loop] );
403 free( thread_handles );
405 lfds610_ringbuffer_query( rs, LFDS610_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
407 for( loop = 0 ; loop < cpu_count ; loop++ )
408 if( (rtrws+loop)->error_flag == RAISED )
409 dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA;
411 for( loop = 0 ; loop < cpu_count ; loop++ )
412 free( (rtrws+loop)->per_thread_counters );
416 lfds610_ringbuffer_delete( rs, NULL, NULL );
418 internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
427 /****************************************************************************/
428 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state )
430 struct ringbuffer_test_reading_and_writing_state
433 struct lfds610_freelist_element
444 assert( ringbuffer_test_reading_and_writing_state != NULL );
446 rtrws = (struct ringbuffer_test_reading_and_writing_state *) ringbuffer_test_reading_and_writing_state;
448 lfds610_ringbuffer_use( rtrws->rs );
452 while( time(NULL) < start_time + 10 )
454 lfds610_ringbuffer_get_write_element( rtrws->rs, &fe, NULL );
455 lfds610_freelist_set_user_data_in_element( fe, (void *) (lfds610_atom_t) (rtrws->counter++) );
456 lfds610_ringbuffer_put_write_element( rtrws->rs, fe );
458 lfds610_ringbuffer_get_read_element( rtrws->rs, &fe );
459 lfds610_freelist_get_user_data_from_element( fe, (void *) &user_data );
461 thread = user_data >> (sizeof(lfds610_atom_t)*8-8);
462 count = (user_data << 8) >> 8;
464 if( thread >= rtrws->cpu_count )
465 rtrws->error_flag = RAISED;
468 if( count < rtrws->per_thread_counters[thread] )
469 rtrws->error_flag = RAISED;
471 if( count >= rtrws->per_thread_counters[thread] )
472 rtrws->per_thread_counters[thread] = count+1;
475 lfds610_ringbuffer_put_read_element( rtrws->rs, fe );
478 return( (thread_return_t) EXIT_SUCCESS );