Files
openairinterface5g/openair2/UTIL/LFDS/liblfds6.1.1/test/src/test_ringbuffer.c
T
Lionel Gauthier 059a0a3fdc astyle --recursive --indent=spaces=2 --style=kr --indent-col1-comments --break-blocks --convert-tabs --max-code-length=200
This is done for better merging branch/LG_PRE_RELEASE_0.3 into trunk (same process is applied on this branch)

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7073 818b1a75-f10b-46b9-bf7c-635c3b92a50f
2015-04-09 09:29:12 +00:00

473 lines
13 KiB
C

#include "internal.h"
/****************************************************************************/
void test_lfds611_ringbuffer( void )
{
printf( "\n"
"Ringbuffer Tests\n"
"================\n" );
ringbuffer_test_reading();
ringbuffer_test_writing();
ringbuffer_test_reading_and_writing();
return;
}
/****************************************************************************/
void ringbuffer_test_reading( void )
{
unsigned int
loop,
cpu_count;
thread_state_t
*thread_handles;
struct lfds611_ringbuffer_state
*rs;
struct lfds611_freelist_element
*fe;
struct ringbuffer_test_reading_state
*rtrs;
struct lfds611_validation_info
vi = { 0, 0 };
enum lfds611_data_structure_validity
dvs[3];
lfds611_atom_t
total_read = 0;
/* TRD : we create a single ringbuffer
with 1,000,000 elements
we populate the ringbuffer, where the
user data is an incrementing counter
we create one thread per CPU
where each thread busy-works,
reading until the ringbuffer is empty
each thread keeps track of the number of reads it manages
and that each user data it reads is greater than the
previous user data that was read
*/
internal_display_test_name( "Reading" );
cpu_count = abstraction_cpu_count();
lfds611_ringbuffer_new( &rs, 1000000, NULL, NULL );
for( loop = 0 ; loop < 1000000 ; loop++ ) {
lfds611_ringbuffer_get_write_element( rs, &fe, NULL );
lfds611_freelist_set_user_data_in_element( fe, (void *) (lfds611_atom_t) loop );
lfds611_ringbuffer_put_write_element( rs, fe );
}
rtrs = malloc( sizeof(struct ringbuffer_test_reading_state) * cpu_count );
for( loop = 0 ; loop < cpu_count ; loop++ ) {
(rtrs+loop)->rs = rs;
(rtrs+loop)->read_count = 0;
(rtrs+loop)->error_flag = LOWERED;
}
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
for( loop = 0 ; loop < cpu_count ; loop++ )
abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_reader, rtrs+loop );
for( loop = 0 ; loop < cpu_count ; loop++ )
abstraction_thread_wait( thread_handles[loop] );
free( thread_handles );
lfds611_ringbuffer_query( rs, LFDS611_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
// TRD : check for raised error flags
for( loop = 0 ; loop < cpu_count ; loop++ )
if( (rtrs+loop)->error_flag == RAISED )
dvs[0] = LFDS611_VALIDITY_INVALID_TEST_DATA;
// TRD : check thread reads total to 1,000,000
for( loop = 0 ; loop < cpu_count ; loop++ )
total_read += (rtrs+loop)->read_count;
if( total_read < 1000000 )
dvs[0] = LFDS611_VALIDITY_INVALID_MISSING_ELEMENTS;
if( total_read > 1000000 )
dvs[0] = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
free( rtrs );
lfds611_ringbuffer_delete( rs, NULL, NULL );
internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
return;
}
/****************************************************************************/
thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state )
{
struct ringbuffer_test_reading_state
*rtrs;
struct lfds611_freelist_element
*fe;
lfds611_atom_t
*prev_user_data,
*user_data;
assert( ringbuffer_test_reading_state != NULL );
rtrs = (struct ringbuffer_test_reading_state *) ringbuffer_test_reading_state;
lfds611_ringbuffer_use( rtrs->rs );
/* TRD : read an initial element to load a value into prev_user_data
it may be (under valgrind for example) that by the time we start
there are no elements remaining to read
*/
lfds611_ringbuffer_get_read_element( rtrs->rs, &fe );
if( fe == NULL )
return( (thread_return_t) EXIT_SUCCESS );
lfds611_freelist_get_user_data_from_element( fe, (void **) &prev_user_data );
lfds611_ringbuffer_put_read_element( rtrs->rs, fe );
rtrs->read_count++;
while( lfds611_ringbuffer_get_read_element(rtrs->rs, &fe) ) {
lfds611_freelist_get_user_data_from_element( fe, (void **) &user_data );
lfds611_ringbuffer_put_read_element( rtrs->rs, fe );
if( user_data <= prev_user_data )
rtrs->error_flag = RAISED;
prev_user_data = user_data;
rtrs->read_count++;
}
return( (thread_return_t) EXIT_SUCCESS );
}
/****************************************************************************/
void ringbuffer_test_writing( void )
{
unsigned int
loop,
cpu_count;
thread_state_t
*thread_handles;
struct lfds611_ringbuffer_state
*rs;
struct lfds611_freelist_element
*fe;
struct ringbuffer_test_writing_state
*rtws;
struct lfds611_validation_info
vi = { 100000, 100000 };
enum lfds611_data_structure_validity
dvs[3];
lfds611_atom_t
thread,
count,
user_data,
*per_thread_counters;
/* TRD : we create a single ringbuffer
with 100000 elements
the ringbuffers starts empty
we create one thread per CPU
where each thread busy-works writing
for ten seconds
the user data in each written element is a combination
of the thread number and the counter
after the threads are complete, we validate by
checking the user data counters increment on a per thread
basis
*/
internal_display_test_name( "Writing (10 seconds)" );
cpu_count = abstraction_cpu_count();
lfds611_ringbuffer_new( &rs, 100000, NULL, NULL );
rtws = malloc( sizeof(struct ringbuffer_test_writing_state) * cpu_count );
for( loop = 0 ; loop < cpu_count ; loop++ ) {
(rtws+loop)->rs = rs;
(rtws+loop)->write_count = (lfds611_atom_t) loop << (sizeof(lfds611_atom_t)*8-8);
}
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
for( loop = 0 ; loop < cpu_count ; loop++ )
abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_writer, rtws+loop );
for( loop = 0 ; loop < cpu_count ; loop++ )
abstraction_thread_wait( thread_handles[loop] );
free( thread_handles );
// TRD : now check results
per_thread_counters = malloc( sizeof(lfds611_atom_t) * cpu_count );
for( loop = 0 ; loop < cpu_count ; loop++ )
*(per_thread_counters+loop) = 0;
lfds611_ringbuffer_query( rs, LFDS611_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
while( dvs[0] == LFDS611_VALIDITY_VALID and dvs[1] == LFDS611_VALIDITY_VALID and dvs[2] == LFDS611_VALIDITY_VALID and lfds611_ringbuffer_get_read_element(rs, &fe) ) {
lfds611_freelist_get_user_data_from_element( fe, (void *) &user_data );
thread = user_data >> (sizeof(lfds611_atom_t)*8-8);
count = (user_data << 8) >> 8;
if( thread >= cpu_count ) {
dvs[0] = LFDS611_VALIDITY_INVALID_TEST_DATA;
lfds611_ringbuffer_put_read_element( rs, fe );
break;
}
if( per_thread_counters[thread] == 0 )
per_thread_counters[thread] = count;
if( count < per_thread_counters[thread] )
dvs[0] = LFDS611_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
if( count >= per_thread_counters[thread] )
per_thread_counters[thread] = count+1;
lfds611_ringbuffer_put_read_element( rs, fe );
}
free( per_thread_counters );
free( rtws );
lfds611_ringbuffer_delete( rs, NULL, NULL );
internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
return;
}
/****************************************************************************/
thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state )
{
struct ringbuffer_test_writing_state
*rtws;
struct lfds611_freelist_element
*fe;
time_t
start_time;
assert( ringbuffer_test_writing_state != NULL );
rtws = (struct ringbuffer_test_writing_state *) ringbuffer_test_writing_state;
lfds611_ringbuffer_use( rtws->rs );
time( &start_time );
while( time(NULL) < start_time + 10 ) {
lfds611_ringbuffer_get_write_element( rtws->rs, &fe, NULL );
lfds611_freelist_set_user_data_in_element( fe, (void *) (lfds611_atom_t) (rtws->write_count++) );
lfds611_ringbuffer_put_write_element( rtws->rs, fe );
}
return( (thread_return_t) EXIT_SUCCESS );
}
/****************************************************************************/
void ringbuffer_test_reading_and_writing( void )
{
unsigned int
loop,
subloop,
cpu_count;
thread_state_t
*thread_handles;
struct lfds611_ringbuffer_state
*rs;
struct ringbuffer_test_reading_and_writing_state
*rtrws;
struct lfds611_validation_info
vi = { 0, 0 };
enum lfds611_data_structure_validity
dvs[3];
/* TRD : we create a single ringbuffer
with 100000 elements
the ringbuffers starts empty
we create one thread per CPU
where each thread busy-works writing
and then immediately reading
for ten seconds
the user data in each written element is a combination
of the thread number and the counter
while a thread runs, it keeps track of the
counters for the other threads and throws an error
if it sees the number stay the same or decrease
*/
internal_display_test_name( "Reading and writing (10 seconds)" );
cpu_count = abstraction_cpu_count();
lfds611_ringbuffer_new( &rs, 100000, NULL, NULL );
rtrws = malloc( sizeof(struct ringbuffer_test_reading_and_writing_state) * cpu_count );
for( loop = 0 ; loop < cpu_count ; loop++ ) {
(rtrws+loop)->rs = rs;
(rtrws+loop)->counter = (lfds611_atom_t) loop << (sizeof(lfds611_atom_t)*8-8);
(rtrws+loop)->cpu_count = cpu_count;
(rtrws+loop)->error_flag = LOWERED;
(rtrws+loop)->per_thread_counters = malloc( sizeof(lfds611_atom_t) * cpu_count );
for( subloop = 0 ; subloop < cpu_count ; subloop++ )
*((rtrws+loop)->per_thread_counters+subloop) = 0;
}
thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
for( loop = 0 ; loop < cpu_count ; loop++ )
abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_reader_writer, rtrws+loop );
for( loop = 0 ; loop < cpu_count ; loop++ )
abstraction_thread_wait( thread_handles[loop] );
free( thread_handles );
lfds611_ringbuffer_query( rs, LFDS611_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
for( loop = 0 ; loop < cpu_count ; loop++ )
if( (rtrws+loop)->error_flag == RAISED )
dvs[0] = LFDS611_VALIDITY_INVALID_TEST_DATA;
for( loop = 0 ; loop < cpu_count ; loop++ )
free( (rtrws+loop)->per_thread_counters );
free( rtrws );
lfds611_ringbuffer_delete( rs, NULL, NULL );
internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
return;
}
/****************************************************************************/
thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state )
{
struct ringbuffer_test_reading_and_writing_state
*rtrws;
struct lfds611_freelist_element
*fe;
lfds611_atom_t
user_data,
thread,
count;
time_t
start_time;
assert( ringbuffer_test_reading_and_writing_state != NULL );
rtrws = (struct ringbuffer_test_reading_and_writing_state *) ringbuffer_test_reading_and_writing_state;
lfds611_ringbuffer_use( rtrws->rs );
time( &start_time );
while( time(NULL) < start_time + 10 ) {
lfds611_ringbuffer_get_write_element( rtrws->rs, &fe, NULL );
lfds611_freelist_set_user_data_in_element( fe, (void *) (lfds611_atom_t) (rtrws->counter++) );
lfds611_ringbuffer_put_write_element( rtrws->rs, fe );
lfds611_ringbuffer_get_read_element( rtrws->rs, &fe );
lfds611_freelist_get_user_data_from_element( fe, (void *) &user_data );
thread = user_data >> (sizeof(lfds611_atom_t)*8-8);
count = (user_data << 8) >> 8;
if( thread >= rtrws->cpu_count )
rtrws->error_flag = RAISED;
else {
if( count < rtrws->per_thread_counters[thread] )
rtrws->error_flag = RAISED;
if( count >= rtrws->per_thread_counters[thread] )
rtrws->per_thread_counters[thread] = count+1;
}
lfds611_ringbuffer_put_read_element( rtrws->rs, fe );
}
return( (thread_return_t) EXIT_SUCCESS );
}