Blame src/ctests/overflow_pthreads.c

Packit 577717
/* This file performs the following test: overflow dispatch with pthreads
Packit 577717
Packit 577717
   - This tests the dispatch of overflow calls from PAPI. These are counted
Packit 577717
   in the default counting domain and default granularity, depending on
Packit 577717
   the platform. Usually this is the user domain (PAPI_DOM_USER) and
Packit 577717
   thread context (PAPI_GRN_THR).
Packit 577717
Packit 577717
     The Eventset contains:
Packit 577717
     + PAPI_FP_INS (overflow monitor)
Packit 577717
     + PAPI_TOT_CYC
Packit 577717
Packit 577717
   - Set up overflow
Packit 577717
   - Start eventset 1
Packit 577717
   - Do flops
Packit 577717
   - Stop eventset 1
Packit 577717
*/
Packit 577717
Packit 577717
#include <stdio.h>
Packit 577717
#include <stdlib.h>
Packit 577717
#include <string.h>
Packit 577717
#include <pthread.h>
Packit 577717
Packit 577717
#include "papi.h"
Packit 577717
#include "do_loops.h"
Packit 577717
#include "papi_test.h"
Packit 577717
Packit 577717
static const PAPI_hw_info_t *hw_info = NULL;
Packit 577717
static int total[NUM_THREADS];
Packit 577717
static int expected[NUM_THREADS];
Packit 577717
static pthread_t myid[NUM_THREADS];
Packit 577717
Packit 577717
static void
Packit 577717
handler( int EventSet, void *address, long long overflow_vector, void *context )
Packit 577717
{
Packit 577717
#if 0
Packit 577717
	printf( "handler(%d,%#lx,%llx) Overflow %d in thread %lx\n",
Packit 577717
			EventSet, ( unsigned long ) address, overflow_vector,
Packit 577717
			total[EventSet], PAPI_thread_id(  ) );
Packit 577717
	printf( "%lx vs %lx\n", myid[EventSet], PAPI_thread_id(  ) );
Packit 577717
#else  /* eliminate unused parameter warning message */
Packit 577717
	( void ) address;
Packit 577717
	( void ) overflow_vector;
Packit 577717
	( void ) context;
Packit 577717
#endif
Packit 577717
	total[EventSet]++;
Packit 577717
}
Packit 577717
Packit 577717
static long long mythreshold=0;
Packit 577717
Packit 577717
static void *
Packit 577717
Thread( void *arg )
Packit 577717
{
Packit 577717
	int retval, num_tests = 1;
Packit 577717
	int EventSet1 = PAPI_NULL;
Packit 577717
	int mask1, papi_event;
Packit 577717
	int num_events1;
Packit 577717
	long long **values;
Packit 577717
	long long elapsed_us, elapsed_cyc;
Packit 577717
	char event_name[PAPI_MAX_STR_LEN];
Packit 577717
Packit 577717
	retval = PAPI_register_thread(  );
Packit 577717
	if ( retval != PAPI_OK )
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_register_thread", retval );
Packit 577717
Packit 577717
	/* add PAPI_TOT_CYC and one of the events in PAPI_FP_INS, PAPI_FP_OPS or
Packit 577717
	   PAPI_TOT_INS, depends on the availability of the event on the 
Packit 577717
	   platform */
Packit 577717
	EventSet1 =
Packit 577717
		add_two_nonderived_events( &num_events1, &papi_event, &mask1 );
Packit 577717
Packit 577717
	if (EventSet1 < 0) return NULL;
Packit 577717
Packit 577717
	/* Wait, we're indexing a per-thread array with the EventSet number? */
Packit 577717
	/* does that make any sense at all???? -- vmw                        */
Packit 577717
	expected[EventSet1] = *( int * ) arg / mythreshold;
Packit 577717
	myid[EventSet1] = PAPI_thread_id(  );
Packit 577717
Packit 577717
	values = allocate_test_space( num_tests, num_events1 );
Packit 577717
Packit 577717
	elapsed_us = PAPI_get_real_usec(  );
Packit 577717
Packit 577717
	elapsed_cyc = PAPI_get_real_cyc(  );
Packit 577717
Packit 577717
	if ((retval = PAPI_overflow( EventSet1, papi_event, 
Packit 577717
				     mythreshold, 0, handler ) ) != PAPI_OK ) {
Packit 577717
	   test_fail( __FILE__, __LINE__, "PAPI_overflow", retval );
Packit 577717
	}
Packit 577717
Packit 577717
	/* start_timer(1); */
Packit 577717
	if ( ( retval = PAPI_start( EventSet1 ) ) != PAPI_OK )
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_start", retval );
Packit 577717
Packit 577717
	do_stuff(  );
Packit 577717
Packit 577717
	if ( ( retval = PAPI_stop( EventSet1, values[0] ) ) != PAPI_OK )
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
Packit 577717
Packit 577717
	elapsed_us = PAPI_get_real_usec(  ) - elapsed_us;
Packit 577717
Packit 577717
	elapsed_cyc = PAPI_get_real_cyc(  ) - elapsed_cyc;
Packit 577717
Packit 577717
	retval = PAPI_overflow( EventSet1, papi_event, 0, 0, NULL );
Packit 577717
	if (retval != PAPI_OK ) {
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_overflow", retval );
Packit 577717
	}
Packit 577717
Packit 577717
	remove_test_events( &EventSet1, mask1 );
Packit 577717
Packit 577717
	retval = PAPI_event_code_to_name( papi_event, event_name );
Packit 577717
	if (retval != PAPI_OK ) {
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_event_code_to_name", retval );
Packit 577717
	}
Packit 577717
Packit 577717
	if ( !TESTS_QUIET ) {
Packit 577717
		printf( "Thread %#x %s : \t%lld\n", ( int ) pthread_self(  ),
Packit 577717
				event_name, ( values[0] )[0] );
Packit 577717
		printf( "Thread %#x PAPI_TOT_CYC: \t%lld\n", ( int ) pthread_self(  ),
Packit 577717
				( values[0] )[1] );
Packit 577717
		printf( "Thread %#x Real usec   : \t%lld\n", ( int ) pthread_self(  ),
Packit 577717
				elapsed_us );
Packit 577717
		printf( "Thread %#x Real cycles : \t%lld\n", ( int ) pthread_self(  ),
Packit 577717
				elapsed_cyc );
Packit 577717
	}
Packit 577717
	free_test_space( values, num_tests );
Packit 577717
	retval = PAPI_unregister_thread(  );
Packit 577717
	if ( retval != PAPI_OK )
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_unregister_thread", retval );
Packit 577717
	return ( NULL );
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
main( int argc, char **argv )
Packit 577717
{
Packit 577717
	pthread_t id[NUM_THREADS];
Packit 577717
	int flops[NUM_THREADS];
Packit 577717
	int i, rc, retval;
Packit 577717
	pthread_attr_t attr;
Packit 577717
	float ratio;
Packit 577717
	int quiet;
Packit 577717
Packit 577717
	/* Set TESTS_QUIET variable */
Packit 577717
	quiet = tests_quiet( argc, argv );
Packit 577717
Packit 577717
	memset( total, 0x0, NUM_THREADS * sizeof ( *total ) );
Packit 577717
	memset( expected, 0x0, NUM_THREADS * sizeof ( *expected ) );
Packit 577717
	memset( myid, 0x0, NUM_THREADS * sizeof ( *myid ) );
Packit 577717
Packit 577717
	retval = PAPI_library_init( PAPI_VER_CURRENT );
Packit 577717
	if (retval != PAPI_VER_CURRENT ) {
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_library_init", retval );
Packit 577717
	}
Packit 577717
Packit 577717
	hw_info = PAPI_get_hardware_info(  );
Packit 577717
	if ( hw_info == NULL ) {
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_get_hardware_info", 2 );
Packit 577717
	}
Packit 577717
Packit 577717
	retval = PAPI_thread_init( ( unsigned long ( * )( void ) )
Packit 577717
					( pthread_self ) );
Packit 577717
	if (retval != PAPI_OK ) {
Packit 577717
		if ( retval == PAPI_ECMP )
Packit 577717
			test_skip( __FILE__, __LINE__, "PAPI_thread_init", retval );
Packit 577717
		else
Packit 577717
			test_fail( __FILE__, __LINE__, "PAPI_thread_init", retval );
Packit 577717
	}
Packit 577717
#if defined(linux)
Packit 577717
	mythreshold = ((long long)hw_info->cpu_max_mhz) * 10000 * 2;
Packit 577717
#else
Packit 577717
	mythreshold = THRESHOLD * 2;
Packit 577717
#endif
Packit 577717
Packit 577717
	pthread_attr_init( &attr );
Packit 577717
#ifdef PTHREAD_CREATE_UNDETACHED
Packit 577717
	pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_UNDETACHED );
Packit 577717
#endif
Packit 577717
#ifdef PTHREAD_SCOPE_SYSTEM
Packit 577717
	retval = pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM );
Packit 577717
	if ( retval != 0 )
Packit 577717
		test_skip( __FILE__, __LINE__, "pthread_attr_setscope", retval );
Packit 577717
#endif
Packit 577717
Packit 577717
	for ( i = 0; i < NUM_THREADS; i++ ) {
Packit 577717
		flops[i] = NUM_FLOPS * ( i + 1 );
Packit 577717
		rc = pthread_create( &id[i], &attr, Thread, ( void * ) &flops[i] );
Packit 577717
		if ( rc )
Packit 577717
			test_fail( __FILE__, __LINE__, "pthread_create", PAPI_ESYS );
Packit 577717
	}
Packit 577717
	for ( i = 0; i < NUM_THREADS; i++ )
Packit 577717
		pthread_join( id[i], NULL );
Packit 577717
Packit 577717
	pthread_attr_destroy( &attr );
Packit 577717
Packit 577717
	{
Packit 577717
		long long t = 0, r = 0;
Packit 577717
		for ( i = 0; i < NUM_THREADS; i++ ) {
Packit 577717
			t += ( NUM_FLOPS * ( i + 1 ) ) / mythreshold;
Packit 577717
			r += total[i];
Packit 577717
		}
Packit 577717
		if (!quiet) {
Packit 577717
			printf( "Expected total overflows: %lld\n", t );
Packit 577717
			printf( "Received total overflows: %lld\n", r );
Packit 577717
		}
Packit 577717
	}
Packit 577717
// FIXME: are we actually testing this properly?
Packit 577717
Packit 577717
/*   ratio = (float)total[0] / (float)expected[0]; */
Packit 577717
/*   printf("Ratio of total to expected: %f\n",ratio); */
Packit 577717
	ratio = 1.0;
Packit 577717
	for ( i = 0; i < NUM_THREADS; i++ ) {
Packit 577717
		if (!quiet) printf( "Overflows thread %d: %d, expected %d\n",
Packit 577717
				i, total[i], ( int ) ( ratio * ( float ) expected[i] ) );
Packit 577717
	}
Packit 577717
Packit 577717
	for ( i = 0; i < NUM_THREADS; i++ ) {
Packit 577717
		if ( total[i] < ( int ) ( ( ratio * ( float ) expected[i] ) / 2.0 ) )
Packit 577717
			test_fail( __FILE__, __LINE__, "not enough overflows", PAPI_EMISC );
Packit 577717
	}
Packit 577717
Packit 577717
	test_pass( __FILE__ );
Packit 577717
Packit 577717
	pthread_exit( NULL );
Packit 577717
Packit 577717
	return 0;
Packit 577717
Packit 577717
}