PAPI  5.0.1.0
overflow_pthreads.c
Go to the documentation of this file.
00001 /* This file performs the following test: overflow dispatch with pthreads
00002 
00003    - This tests the dispatch of overflow calls from PAPI. These are counted 
00004    in the default counting domain and default granularity, depending on 
00005    the platform. Usually this is the user domain (PAPI_DOM_USER) and 
00006    thread context (PAPI_GRN_THR).
00007 
00008      The Eventset contains:
00009      + PAPI_FP_INS (overflow monitor)
00010      + PAPI_TOT_CYC
00011 
00012    - Set up overflow
00013    - Start eventset 1
00014    - Do flops
00015    - Stop eventset 1
00016 */
00017 
00018 #include <pthread.h>
00019 #include "papi_test.h"
00020 
00021 static const PAPI_hw_info_t *hw_info = NULL;
00022 static int total[NUM_THREADS];
00023 static int expected[NUM_THREADS];
00024 static pthread_t myid[NUM_THREADS];
00025 
00026 void
00027 handler( int EventSet, void *address, long long overflow_vector, void *context )
00028 {
00029 #if 0
00030     printf( "handler(%d,0x%lx,%llx) Overflow %d in thread %lx\n",
00031             EventSet, ( unsigned long ) address, overflow_vector,
00032             total[EventSet], PAPI_thread_id(  ) );
00033     printf( "%lx vs %lx\n", myid[EventSet], PAPI_thread_id(  ) );
00034 #else  /* eliminate unused parameter warning message */
00035     ( void ) address;
00036     ( void ) overflow_vector;
00037     ( void ) context;
00038 #endif
00039     total[EventSet]++;
00040 }
00041 
00042 long long mythreshold=0;
00043 
00044 void *
00045 Thread( void *arg )
00046 {
00047     int retval, num_tests = 1;
00048     int EventSet1 = PAPI_NULL;
00049     int mask1, papi_event;
00050     int num_events1;
00051     long long **values;
00052     long long elapsed_us, elapsed_cyc;
00053     char event_name[PAPI_MAX_STR_LEN];
00054 
00055     retval = PAPI_register_thread(  );
00056     if ( retval != PAPI_OK )
00057         test_fail( __FILE__, __LINE__, "PAPI_register_thread", retval );
00058 
00059     /* add PAPI_TOT_CYC and one of the events in PAPI_FP_INS, PAPI_FP_OPS or
00060        PAPI_TOT_INS, depends on the availability of the event on the 
00061        platform */
00062     EventSet1 =
00063         add_two_nonderived_events( &num_events1, &papi_event, &mask1 );
00064 
00065     if (EventSet1 < 0) return NULL;
00066 
00067     /* Wait, we're indexing a per-thread array with the EventSet number? */
00068     /* does that make any sense at all???? -- vmw                        */
00069     expected[EventSet1] = *( int * ) arg / mythreshold;
00070     myid[EventSet1] = PAPI_thread_id(  );
00071 
00072     values = allocate_test_space( num_tests, num_events1 );
00073 
00074     elapsed_us = PAPI_get_real_usec(  );
00075 
00076     elapsed_cyc = PAPI_get_real_cyc(  );
00077 
00078     if ((retval = PAPI_overflow( EventSet1, papi_event, 
00079                      mythreshold, 0, handler ) ) != PAPI_OK ) {
00080        test_fail( __FILE__, __LINE__, "PAPI_overflow", retval );
00081     }
00082 
00083     /* start_timer(1); */
00084     if ( ( retval = PAPI_start( EventSet1 ) ) != PAPI_OK )
00085         test_fail( __FILE__, __LINE__, "PAPI_start", retval );
00086 
00087     do_stuff(  );
00088 
00089     if ( ( retval = PAPI_stop( EventSet1, values[0] ) ) != PAPI_OK )
00090         test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
00091 
00092     elapsed_us = PAPI_get_real_usec(  ) - elapsed_us;
00093 
00094     elapsed_cyc = PAPI_get_real_cyc(  ) - elapsed_cyc;
00095 
00096     if ( ( retval =
00097            PAPI_overflow( EventSet1, papi_event, 0, 0, NULL ) ) != PAPI_OK )
00098         test_fail( __FILE__, __LINE__, "PAPI_overflow", retval );
00099 
00100     remove_test_events( &EventSet1, mask1 );
00101 
00102     if ( ( retval =
00103            PAPI_event_code_to_name( papi_event, event_name ) ) != PAPI_OK )
00104         test_fail( __FILE__, __LINE__, "PAPI_event_code_to_name", retval );
00105 
00106     if ( !TESTS_QUIET ) {
00107         printf( "Thread 0x%x %s : \t%lld\n", ( int ) pthread_self(  ),
00108                 event_name, ( values[0] )[0] );
00109         printf( "Thread 0x%x PAPI_TOT_CYC: \t%lld\n", ( int ) pthread_self(  ),
00110                 ( values[0] )[1] );
00111         printf( "Thread 0x%x Real usec   : \t%lld\n", ( int ) pthread_self(  ),
00112                 elapsed_us );
00113         printf( "Thread 0x%x Real cycles : \t%lld\n", ( int ) pthread_self(  ),
00114                 elapsed_cyc );
00115     }
00116     free_test_space( values, num_tests );
00117     retval = PAPI_unregister_thread(  );
00118     if ( retval != PAPI_OK )
00119         test_fail( __FILE__, __LINE__, "PAPI_unregister_thread", retval );
00120     return ( NULL );
00121 }
00122 
00123 int
00124 main( int argc, char **argv )
00125 {
00126     pthread_t id[NUM_THREADS];
00127     int flops[NUM_THREADS];
00128     int i, rc, retval;
00129     pthread_attr_t attr;
00130     float ratio;
00131 
00132     memset( total, 0x0, NUM_THREADS * sizeof ( *total ) );
00133     memset( expected, 0x0, NUM_THREADS * sizeof ( *expected ) );
00134     memset( myid, 0x0, NUM_THREADS * sizeof ( *myid ) );
00135     tests_quiet( argc, argv );  /* Set TESTS_QUIET variable */
00136 
00137     if ( ( retval =
00138            PAPI_library_init( PAPI_VER_CURRENT ) ) != PAPI_VER_CURRENT )
00139         test_fail( __FILE__, __LINE__, "PAPI_library_init", retval );
00140 
00141     hw_info = PAPI_get_hardware_info(  );
00142     if ( hw_info == NULL )
00143         test_fail( __FILE__, __LINE__, "PAPI_get_hardware_info", 2 );
00144 
00145     if ( ( retval =
00146            PAPI_thread_init( ( unsigned
00147                                long ( * )( void ) ) ( pthread_self ) ) ) !=
00148          PAPI_OK ) {
00149         if ( retval == PAPI_ECMP )
00150             test_skip( __FILE__, __LINE__, "PAPI_thread_init", retval );
00151         else
00152             test_fail( __FILE__, __LINE__, "PAPI_thread_init", retval );
00153     }
00154 #if defined(linux)
00155     mythreshold = hw_info->cpu_max_mhz * 10000 * 2;
00156 #else
00157     mythreshold = THRESHOLD * 2;
00158 #endif
00159 
00160     pthread_attr_init( &attr );
00161 #ifdef PTHREAD_CREATE_UNDETACHED
00162     pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_UNDETACHED );
00163 #endif
00164 #ifdef PTHREAD_SCOPE_SYSTEM
00165     retval = pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM );
00166     if ( retval != 0 )
00167         test_skip( __FILE__, __LINE__, "pthread_attr_setscope", retval );
00168 #endif
00169 
00170     for ( i = 0; i < NUM_THREADS; i++ ) {
00171         flops[i] = NUM_FLOPS * ( i + 1 );
00172         rc = pthread_create( &id[i], &attr, Thread, ( void * ) &flops[i] );
00173         if ( rc )
00174             test_fail( __FILE__, __LINE__, "pthread_create", PAPI_ESYS );
00175     }
00176     for ( i = 0; i < NUM_THREADS; i++ )
00177         pthread_join( id[i], NULL );
00178 
00179     pthread_attr_destroy( &attr );
00180 
00181     {
00182         long long t = 0, r = 0;
00183         for ( i = 0; i < NUM_THREADS; i++ ) {
00184             t += ( NUM_FLOPS * ( i + 1 ) ) / mythreshold;
00185             r += total[i];
00186         }
00187         printf( "Expected total overflows: %lld\n", t );
00188         printf( "Received total overflows: %lld\n", r );
00189     }
00190 
00191 /*   ratio = (float)total[0] / (float)expected[0]; */
00192 /*   printf("Ratio of total to expected: %f\n",ratio); */
00193     ratio = 1.0;
00194     for ( i = 0; i < NUM_THREADS; i++ ) {
00195         printf( "Overflows thread %d: %d, expected %d\n",
00196                 i, total[i], ( int ) ( ratio * ( float ) expected[i] ) );
00197     }
00198 
00199     for ( i = 0; i < NUM_THREADS; i++ ) {
00200         if ( total[i] < ( int ) ( ( ratio * ( float ) expected[i] ) / 2.0 ) )
00201             test_fail( __FILE__, __LINE__, "not enough overflows", PAPI_EMISC );
00202     }
00203 
00204     test_pass( __FILE__, NULL, 0 );
00205     pthread_exit( NULL );
00206     exit( 1 );
00207 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines