7 /****************************************************************************/
8 void test_lfds600_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 lfds600_ringbuffer_state
38 struct lfds600_freelist_element
41 struct ringbuffer_test_reading_state
44 struct lfds600_validation_info
47 enum 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 keep 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 lfds600_ringbuffer_new( &rs, 1000000, NULL, NULL );
73 for( loop = 0 ; loop < 1000000 ; loop++ )
75 lfds600_ringbuffer_get_write_element( rs, &fe, NULL );
76 lfds600_freelist_set_user_data_in_element( fe, (void *) (lfds600_atom_t) loop );
77 lfds600_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 lfds600_ringbuffer_query( rs, LFDS600_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] = 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] = VALIDITY_INVALID_MISSING_ELEMENTS;
113 if( total_read > 1000000 )
114 dvs[0] = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
118 lfds600_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 lfds600_freelist_element
142 assert( ringbuffer_test_reading_state != NULL );
144 rtrs = (struct ringbuffer_test_reading_state *) ringbuffer_test_reading_state;
146 lfds600_ringbuffer_get_read_element( rtrs->rs, &fe );
147 lfds600_freelist_get_user_data_from_element( fe, (void **) &prev_user_data );
148 lfds600_ringbuffer_put_read_element( rtrs->rs, fe );
152 while( lfds600_ringbuffer_get_read_element(rtrs->rs, &fe) )
154 lfds600_freelist_get_user_data_from_element( fe, (void **) &user_data );
155 lfds600_ringbuffer_put_read_element( rtrs->rs, fe );
157 if( user_data <= prev_user_data )
158 rtrs->error_flag = RAISED;
160 prev_user_data = user_data;
165 return( (thread_return_t) EXIT_SUCCESS );
172 /****************************************************************************/
173 void ringbuffer_test_writing( void )
182 struct lfds600_ringbuffer_state
185 struct lfds600_freelist_element
188 struct ringbuffer_test_writing_state
191 struct lfds600_validation_info
192 vi = { 100000, 100000 };
194 enum data_structure_validity
201 *per_thread_counters;
203 /* TRD : we create a single ringbuffer
205 the ringbuffers starts empty
207 we create one thread per CPU
208 where each thread busy-works writing
211 the user data in each written element is a combination
212 of the thread number and the counter
214 after the threads are complete, we validate by
215 checking the user data counters increment on a per thread
219 internal_display_test_name( "Writing (10 seconds)" );
221 cpu_count = abstraction_cpu_count();
223 lfds600_ringbuffer_new( &rs, 100000, NULL, NULL );
225 rtws = malloc( sizeof(struct ringbuffer_test_writing_state) * cpu_count );
227 for( loop = 0 ; loop < cpu_count ; loop++ )
229 (rtws+loop)->rs = rs;
230 (rtws+loop)->write_count = (lfds600_atom_t) loop << (sizeof(lfds600_atom_t)*8-8);
233 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
235 for( loop = 0 ; loop < cpu_count ; loop++ )
236 abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_writer, rtws+loop );
238 for( loop = 0 ; loop < cpu_count ; loop++ )
239 abstraction_thread_wait( thread_handles[loop] );
241 free( thread_handles );
243 // TRD : now check results
244 per_thread_counters = malloc( sizeof(lfds600_atom_t) * cpu_count );
246 for( loop = 0 ; loop < cpu_count ; loop++ )
247 *(per_thread_counters+loop) = 0;
249 lfds600_ringbuffer_query( rs, LFDS600_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
251 while( dvs[0] == VALIDITY_VALID and dvs[1] == VALIDITY_VALID and dvs[2] == VALIDITY_VALID and lfds600_ringbuffer_get_read_element(rs, &fe) )
253 lfds600_freelist_get_user_data_from_element( fe, (void *) &user_data );
255 thread = user_data >> (sizeof(lfds600_atom_t)*8-8);
256 count = (user_data << 8) >> 8;
258 if( thread >= cpu_count )
260 dvs[0] = VALIDITY_INVALID_TEST_DATA;
261 lfds600_ringbuffer_put_read_element( rs, fe );
265 if( per_thread_counters[thread] == 0 )
266 per_thread_counters[thread] = count;
268 if( count < per_thread_counters[thread] )
269 dvs[0] = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
271 if( count >= per_thread_counters[thread] )
272 per_thread_counters[thread] = count+1;
274 lfds600_ringbuffer_put_read_element( rs, fe );
277 free( per_thread_counters );
281 lfds600_ringbuffer_delete( rs, NULL, NULL );
283 internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
292 /****************************************************************************/
293 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state )
295 struct ringbuffer_test_writing_state
298 struct lfds600_freelist_element
304 assert( ringbuffer_test_writing_state != NULL );
306 rtws = (struct ringbuffer_test_writing_state *) ringbuffer_test_writing_state;
310 while( time(NULL) < start_time + 10 )
312 lfds600_ringbuffer_get_write_element( rtws->rs, &fe, NULL );
313 lfds600_freelist_set_user_data_in_element( fe, (void *) (lfds600_atom_t) (rtws->write_count++) );
314 lfds600_ringbuffer_put_write_element( rtws->rs, fe );
317 return( (thread_return_t) EXIT_SUCCESS );
324 /****************************************************************************/
325 void ringbuffer_test_reading_and_writing( void )
335 struct lfds600_ringbuffer_state
338 struct ringbuffer_test_reading_and_writing_state
341 struct lfds600_validation_info
344 enum data_structure_validity
347 /* TRD : we create a single ringbuffer
349 the ringbuffers starts empty
351 we create one thread per CPU
352 where each thread busy-works writing
353 and then immediately reading
356 the user data in each written element is a combination
357 of the thread number and the counter
359 while a thread runs, it keeps track of the
360 counters for the other threads and throws an error
361 if it sees the number stay the same or decrease
364 internal_display_test_name( "Reading and writing (10 seconds)" );
366 cpu_count = abstraction_cpu_count();
368 lfds600_ringbuffer_new( &rs, 100000, NULL, NULL );
370 rtrws = malloc( sizeof(struct ringbuffer_test_reading_and_writing_state) * cpu_count );
372 for( loop = 0 ; loop < cpu_count ; loop++ )
374 (rtrws+loop)->rs = rs;
375 (rtrws+loop)->counter = (lfds600_atom_t) loop << (sizeof(lfds600_atom_t)*8-8);
376 (rtrws+loop)->cpu_count = cpu_count;
377 (rtrws+loop)->error_flag = LOWERED;
378 (rtrws+loop)->per_thread_counters = malloc( sizeof(lfds600_atom_t) * cpu_count );
380 for( subloop = 0 ; subloop < cpu_count ; subloop++ )
381 *((rtrws+loop)->per_thread_counters+subloop) = 0;
384 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
386 for( loop = 0 ; loop < cpu_count ; loop++ )
387 abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_reader_writer, rtrws+loop );
389 for( loop = 0 ; loop < cpu_count ; loop++ )
390 abstraction_thread_wait( thread_handles[loop] );
392 free( thread_handles );
394 lfds600_ringbuffer_query( rs, LFDS600_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
396 for( loop = 0 ; loop < cpu_count ; loop++ )
397 if( (rtrws+loop)->error_flag == RAISED )
398 dvs[0] = VALIDITY_INVALID_TEST_DATA;
400 for( loop = 0 ; loop < cpu_count ; loop++ )
401 free( (rtrws+loop)->per_thread_counters );
405 lfds600_ringbuffer_delete( rs, NULL, NULL );
407 internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
416 /****************************************************************************/
417 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state )
419 struct ringbuffer_test_reading_and_writing_state
422 struct lfds600_freelist_element
433 assert( ringbuffer_test_reading_and_writing_state != NULL );
435 rtrws = (struct ringbuffer_test_reading_and_writing_state *) ringbuffer_test_reading_and_writing_state;
439 while( time(NULL) < start_time + 10 )
441 lfds600_ringbuffer_get_write_element( rtrws->rs, &fe, NULL );
442 lfds600_freelist_set_user_data_in_element( fe, (void *) (lfds600_atom_t) (rtrws->counter++) );
443 lfds600_ringbuffer_put_write_element( rtrws->rs, fe );
445 lfds600_ringbuffer_get_read_element( rtrws->rs, &fe );
446 lfds600_freelist_get_user_data_from_element( fe, (void *) &user_data );
448 thread = user_data >> (sizeof(lfds600_atom_t)*8-8);
449 count = (user_data << 8) >> 8;
451 if( thread >= rtrws->cpu_count )
452 rtrws->error_flag = RAISED;
455 if( count < rtrws->per_thread_counters[thread] )
456 rtrws->error_flag = RAISED;
458 if( count >= rtrws->per_thread_counters[thread] )
459 rtrws->per_thread_counters[thread] = count+1;
462 lfds600_ringbuffer_put_read_element( rtrws->rs, fe );
465 return( (thread_return_t) EXIT_SUCCESS );