#include #include #include #include #include #include "fifo.h" typedef struct __safe_random_generator { double x; double a; } safe_random_generator_t; typedef struct __thread_data { safe_random_generator_t srg; int nb_elems; } thread_data_t; /* The FIFO will be global as all threads need to have access to it */ fifo_t* global_fifo = NULL; /** * Generate a thread safe random number with a period of 2^44. * Good accuracy, speed. */ double thread_safe_random( safe_random_generator_t* srg ) { long long Lx, La, a1, a2, x1, x2, xa; const double d2m46 = pow(0.5, 46); Lx = srg->x; La = srg->a; a1 = (La >> 23) & ((1ULL << 24) - 1); a2 = La & ((1ULL << 24) - 1); x1 = (Lx >> 23) & ((1ULL << 24) - 1); x2 = Lx & ((1ULL << 24) - 1); xa = a1 * x2 + a2 * x1; xa = (xa & ((1ULL << 24) - 1)) + a2 * x2; Lx = xa & ((1ULL << 47) - 1); srg->x = (double)Lx; return d2m46 * (srg->x); } /** * The main thread function. Each thread will execute this * function based on a different set of arguments. */ void* thread_function( void* args ) { thread_data_t* td = (thread_data_t*)args; int nb_elems = td->nb_elems; int nb_push = nb_elems, nb_pop = nb_elems; long rnd; fifo_elem_t* elem; while( 0 != (nb_push + nb_pop) ) { /* get a thread safe random number to base our action on */ rnd = (long)thread_safe_random( &(td->srg) ); /* Do a push if there is still room ... */ if( 1 == (rnd % 3) ) { force_push: if( nb_push > 0 ) { nb_push--; elem = malloc( sizeof(fifo_elem_t) ); fifo_push( global_fifo, elem ); continue; } } /* otherwise do a pop */ if( nb_pop > 0 ) { nb_pop--; elem = fifo_pop( global_fifo ); free( elem ); } else { /* force the push if no pop possible */ goto force_push; } } return NULL; } #define DELAY(t1, t2) ((t2.tv_sec - t1.tv_sec)*1000000 + (t2.tv_usec - t1.tv_usec)) int main( int argc, char* argv[] ) { int i, num_threads = 1, rc, num_elems = 100000; pthread_t* thread_ids; struct timeval start_time, thread_creation_time, complete_time; thread_data_t* td; /* Create the global fifo */ global_fifo = fifo_create(); thread_ids = (pthread_t*)malloc( sizeof(pthread_t) * num_threads ); td = (thread_data_t*)malloc( sizeof(thread_data_t) * num_threads ); gettimeofday( &start_time, NULL ); for( i = 0; i < num_threads; i++ ) { td[i].srg.x = (double)random(); td[i].srg.a = (double)random(); td[i].nb_elems = num_elems; rc = pthread_create( &thread_ids[i], NULL, thread_function, (void*)&(td[i]) ); if( 0 != rc ) { printf( "Failed to create a thread... Prepare to give up !\n" ); break; } } gettimeofday( &thread_creation_time, NULL ); for( i--; i >= 0; i-- ) { void* return_value; pthread_join( thread_ids[i], &return_value ); } gettimeofday( &complete_time, NULL ); free( thread_ids ); /* Destroy the global fifo */ fifo_destroy( &global_fifo ); printf( "Threads created in %ld micro-seconds\n", DELAY( start_time, thread_creation_time ) ); printf( "Total execution time %ld micro-seconds\n", DELAY( start_time, complete_time ) ); return 0; }