1 #include "internal.h"
\r
7 /****************************************************************************/
\r
8 void test_lfds601_ringbuffer( void )
\r
11 "Ringbuffer Tests\n"
\r
12 "================\n" );
\r
14 ringbuffer_test_reading();
\r
15 ringbuffer_test_writing();
\r
16 ringbuffer_test_reading_and_writing();
\r
25 /****************************************************************************/
\r
26 void ringbuffer_test_reading( void )
\r
35 struct lfds601_ringbuffer_state
\r
38 struct lfds601_freelist_element
\r
41 struct ringbuffer_test_reading_state
\r
44 struct lfds601_validation_info
\r
47 enum lfds601_data_structure_validity
\r
53 /* TRD : we create a single ringbuffer
\r
54 with 1,000,000 elements
\r
55 we populate the ringbuffer, where the
\r
56 user data is an incrementing counter
\r
58 we create one thread per CPU
\r
59 where each thread busy-works,
\r
60 reading until the ringbuffer is empty
\r
62 each thread keep track of the number of reads it manages
\r
63 and that each user data it reads is greater than the
\r
64 previous user data that was read
\r
67 internal_display_test_name( "Reading" );
\r
69 cpu_count = abstraction_cpu_count();
\r
71 lfds601_ringbuffer_new( &rs, 1000000, NULL, NULL );
\r
73 for( loop = 0 ; loop < 1000000 ; loop++ )
\r
75 lfds601_ringbuffer_get_write_element( rs, &fe, NULL );
\r
76 lfds601_freelist_set_user_data_in_element( fe, (void *) (lfds601_atom_t) loop );
\r
77 lfds601_ringbuffer_put_write_element( rs, fe );
\r
80 rtrs = malloc( sizeof(struct ringbuffer_test_reading_state) * cpu_count );
\r
82 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
84 (rtrs+loop)->rs = rs;
\r
85 (rtrs+loop)->read_count = 0;
\r
86 (rtrs+loop)->error_flag = LOWERED;
\r
89 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
\r
91 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
92 abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_reader, rtrs+loop );
\r
94 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
95 abstraction_thread_wait( thread_handles[loop] );
\r
97 free( thread_handles );
\r
99 lfds601_ringbuffer_query( rs, LFDS601_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
\r
101 // TRD : check for raised error flags
\r
102 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
103 if( (rtrs+loop)->error_flag == RAISED )
\r
104 dvs[0] = LFDS601_VALIDITY_INVALID_TEST_DATA;
\r
106 // TRD : check thread reads total to 1,000,000
\r
107 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
108 total_read += (rtrs+loop)->read_count;
\r
110 if( total_read < 1000000 )
\r
111 dvs[0] = LFDS601_VALIDITY_INVALID_MISSING_ELEMENTS;
\r
113 if( total_read > 1000000 )
\r
114 dvs[0] = LFDS601_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
\r
118 lfds601_ringbuffer_delete( rs, NULL, NULL );
\r
120 internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
\r
129 /****************************************************************************/
\r
130 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state )
\r
132 struct ringbuffer_test_reading_state
\r
135 struct lfds601_freelist_element
\r
142 assert( ringbuffer_test_reading_state != NULL );
\r
144 rtrs = (struct ringbuffer_test_reading_state *) ringbuffer_test_reading_state;
\r
146 lfds601_ringbuffer_get_read_element( rtrs->rs, &fe );
\r
147 lfds601_freelist_get_user_data_from_element( fe, (void **) &prev_user_data );
\r
148 lfds601_ringbuffer_put_read_element( rtrs->rs, fe );
\r
150 rtrs->read_count++;
\r
152 while( lfds601_ringbuffer_get_read_element(rtrs->rs, &fe) )
\r
154 lfds601_freelist_get_user_data_from_element( fe, (void **) &user_data );
\r
155 lfds601_ringbuffer_put_read_element( rtrs->rs, fe );
\r
157 if( user_data <= prev_user_data )
\r
158 rtrs->error_flag = RAISED;
\r
160 prev_user_data = user_data;
\r
162 rtrs->read_count++;
\r
165 return( (thread_return_t) EXIT_SUCCESS );
\r
172 /****************************************************************************/
\r
173 void ringbuffer_test_writing( void )
\r
182 struct lfds601_ringbuffer_state
\r
185 struct lfds601_freelist_element
\r
188 struct ringbuffer_test_writing_state
\r
191 struct lfds601_validation_info
\r
192 vi = { 100000, 100000 };
\r
194 enum lfds601_data_structure_validity
\r
201 *per_thread_counters;
\r
203 /* TRD : we create a single ringbuffer
\r
204 with 100000 elements
\r
205 the ringbuffers starts empty
\r
207 we create one thread per CPU
\r
208 where each thread busy-works writing
\r
211 the user data in each written element is a combination
\r
212 of the thread number and the counter
\r
214 after the threads are complete, we validate by
\r
215 checking the user data counters increment on a per thread
\r
219 internal_display_test_name( "Writing (10 seconds)" );
\r
221 cpu_count = abstraction_cpu_count();
\r
223 lfds601_ringbuffer_new( &rs, 100000, NULL, NULL );
\r
225 rtws = malloc( sizeof(struct ringbuffer_test_writing_state) * cpu_count );
\r
227 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
229 (rtws+loop)->rs = rs;
\r
230 (rtws+loop)->write_count = (lfds601_atom_t) loop << (sizeof(lfds601_atom_t)*8-8);
\r
233 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
\r
235 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
236 abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_writer, rtws+loop );
\r
238 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
239 abstraction_thread_wait( thread_handles[loop] );
\r
241 free( thread_handles );
\r
243 // TRD : now check results
\r
244 per_thread_counters = malloc( sizeof(lfds601_atom_t) * cpu_count );
\r
246 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
247 *(per_thread_counters+loop) = 0;
\r
249 lfds601_ringbuffer_query( rs, LFDS601_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
\r
251 while( dvs[0] == LFDS601_VALIDITY_VALID and dvs[1] == LFDS601_VALIDITY_VALID and dvs[2] == LFDS601_VALIDITY_VALID and lfds601_ringbuffer_get_read_element(rs, &fe) )
\r
253 lfds601_freelist_get_user_data_from_element( fe, (void *) &user_data );
\r
255 thread = user_data >> (sizeof(lfds601_atom_t)*8-8);
\r
256 count = (user_data << 8) >> 8;
\r
258 if( thread >= cpu_count )
\r
260 dvs[0] = LFDS601_VALIDITY_INVALID_TEST_DATA;
\r
261 lfds601_ringbuffer_put_read_element( rs, fe );
\r
265 if( per_thread_counters[thread] == 0 )
\r
266 per_thread_counters[thread] = count;
\r
268 if( count < per_thread_counters[thread] )
\r
269 dvs[0] = LFDS601_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
\r
271 if( count >= per_thread_counters[thread] )
\r
272 per_thread_counters[thread] = count+1;
\r
274 lfds601_ringbuffer_put_read_element( rs, fe );
\r
277 free( per_thread_counters );
\r
281 lfds601_ringbuffer_delete( rs, NULL, NULL );
\r
283 internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
\r
292 /****************************************************************************/
\r
293 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state )
\r
295 struct ringbuffer_test_writing_state
\r
298 struct lfds601_freelist_element
\r
304 assert( ringbuffer_test_writing_state != NULL );
\r
306 rtws = (struct ringbuffer_test_writing_state *) ringbuffer_test_writing_state;
\r
308 time( &start_time );
\r
310 while( time(NULL) < start_time + 10 )
\r
312 lfds601_ringbuffer_get_write_element( rtws->rs, &fe, NULL );
\r
313 lfds601_freelist_set_user_data_in_element( fe, (void *) (lfds601_atom_t) (rtws->write_count++) );
\r
314 lfds601_ringbuffer_put_write_element( rtws->rs, fe );
\r
317 return( (thread_return_t) EXIT_SUCCESS );
\r
324 /****************************************************************************/
\r
325 void ringbuffer_test_reading_and_writing( void )
\r
335 struct lfds601_ringbuffer_state
\r
338 struct ringbuffer_test_reading_and_writing_state
\r
341 struct lfds601_validation_info
\r
344 enum lfds601_data_structure_validity
\r
347 /* TRD : we create a single ringbuffer
\r
348 with 100000 elements
\r
349 the ringbuffers starts empty
\r
351 we create one thread per CPU
\r
352 where each thread busy-works writing
\r
353 and then immediately reading
\r
356 the user data in each written element is a combination
\r
357 of the thread number and the counter
\r
359 while a thread runs, it keeps track of the
\r
360 counters for the other threads and throws an error
\r
361 if it sees the number stay the same or decrease
\r
364 internal_display_test_name( "Reading and writing (10 seconds)" );
\r
366 cpu_count = abstraction_cpu_count();
\r
368 lfds601_ringbuffer_new( &rs, 100000, NULL, NULL );
\r
370 rtrws = malloc( sizeof(struct ringbuffer_test_reading_and_writing_state) * cpu_count );
\r
372 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
374 (rtrws+loop)->rs = rs;
\r
375 (rtrws+loop)->counter = (lfds601_atom_t) loop << (sizeof(lfds601_atom_t)*8-8);
\r
376 (rtrws+loop)->cpu_count = cpu_count;
\r
377 (rtrws+loop)->error_flag = LOWERED;
\r
378 (rtrws+loop)->per_thread_counters = malloc( sizeof(lfds601_atom_t) * cpu_count );
\r
380 for( subloop = 0 ; subloop < cpu_count ; subloop++ )
\r
381 *((rtrws+loop)->per_thread_counters+subloop) = 0;
\r
384 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
\r
386 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
387 abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_reader_writer, rtrws+loop );
\r
389 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
390 abstraction_thread_wait( thread_handles[loop] );
\r
392 free( thread_handles );
\r
394 lfds601_ringbuffer_query( rs, LFDS601_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
\r
396 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
397 if( (rtrws+loop)->error_flag == RAISED )
\r
398 dvs[0] = LFDS601_VALIDITY_INVALID_TEST_DATA;
\r
400 for( loop = 0 ; loop < cpu_count ; loop++ )
\r
401 free( (rtrws+loop)->per_thread_counters );
\r
405 lfds601_ringbuffer_delete( rs, NULL, NULL );
\r
407 internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
\r
416 /****************************************************************************/
\r
417 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state )
\r
419 struct ringbuffer_test_reading_and_writing_state
\r
422 struct lfds601_freelist_element
\r
433 assert( ringbuffer_test_reading_and_writing_state != NULL );
\r
435 rtrws = (struct ringbuffer_test_reading_and_writing_state *) ringbuffer_test_reading_and_writing_state;
\r
437 time( &start_time );
\r
439 while( time(NULL) < start_time + 10 )
\r
441 lfds601_ringbuffer_get_write_element( rtrws->rs, &fe, NULL );
\r
442 lfds601_freelist_set_user_data_in_element( fe, (void *) (lfds601_atom_t) (rtrws->counter++) );
\r
443 lfds601_ringbuffer_put_write_element( rtrws->rs, fe );
\r
445 lfds601_ringbuffer_get_read_element( rtrws->rs, &fe );
\r
446 lfds601_freelist_get_user_data_from_element( fe, (void *) &user_data );
\r
448 thread = user_data >> (sizeof(lfds601_atom_t)*8-8);
\r
449 count = (user_data << 8) >> 8;
\r
451 if( thread >= rtrws->cpu_count )
\r
452 rtrws->error_flag = RAISED;
\r
455 if( count < rtrws->per_thread_counters[thread] )
\r
456 rtrws->error_flag = RAISED;
\r
458 if( count >= rtrws->per_thread_counters[thread] )
\r
459 rtrws->per_thread_counters[thread] = count+1;
\r
462 lfds601_ringbuffer_put_read_element( rtrws->rs, fe );
\r
465 return( (thread_return_t) EXIT_SUCCESS );
\r