Blame src/ctests/prof_utils.c

Packit 577717
/*
Packit 577717
* File:    prof_utils.c
Packit 577717
* Author:  Dan Terpstra
Packit 577717
*          terpstra@cs.utk.edu
Packit 577717
*/
Packit 577717
Packit 577717
/* This file contains utility functions useful for all profiling tests
Packit 577717
   It can be used by:
Packit 577717
   - profile.c,
Packit 577717
   - sprofile.c,
Packit 577717
   - profile_pthreads.c,
Packit 577717
   - profile_twoevents.c,
Packit 577717
   - earprofile.c,
Packit 577717
   - future profiling tests.
Packit 577717
*/
Packit 577717
Packit 577717
#include <stdio.h>
Packit 577717
#include <stdlib.h>
Packit 577717
#include <string.h>
Packit 577717
Packit 577717
#include "papi.h"
Packit 577717
#include "papi_test.h"
Packit 577717
Packit 577717
#include "do_loops.h"
Packit 577717
Packit 577717
#include "prof_utils.h"
Packit 577717
Packit 577717
/* variables global to profiling tests */
Packit 577717
long long **values;
Packit 577717
char event_name[PAPI_MAX_STR_LEN];
Packit 577717
int PAPI_event;
Packit 577717
int EventSet = PAPI_NULL;
Packit 577717
void *profbuf[5];
Packit 577717
Packit 577717
Packit 577717
/* Many profiling tests count one of {FP_INS, FP_OPS, TOT_INS} and TOT_CYC.
Packit 577717
   This function creates an event set containing the appropriate pair of events.
Packit 577717
   It also initializes the global event_name string to the event selected.
Packit 577717
   Assumed globals: EventSet, PAPI_event, event_name.
Packit 577717
*/
Packit 577717
int
Packit 577717
prof_events( int num_tests)
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
	int num_events, mask;
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
	EventSet = add_two_nonderived_events( &num_events, &PAPI_event, &mask );
Packit 577717
Packit 577717
	if (num_events==0) {
Packit 577717
		return 0;
Packit 577717
	}
Packit 577717
Packit 577717
	values = allocate_test_space( num_tests, num_events );
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
	return mask;
Packit 577717
}
Packit 577717
Packit 577717
/* This function displays info from the prginfo structure in a standardized format.
Packit 577717
*/
Packit 577717
void
Packit 577717
prof_print_address( const char *title, const PAPI_exe_info_t * prginfo )
Packit 577717
{
Packit 577717
	printf( "%s\n", title );
Packit 577717
	printf
Packit 577717
		( "----------------------------------------------------------------\n" );
Packit 577717
	printf( "Text start: %p, Text end: %p, Text length: %#x\n",
Packit 577717
			prginfo->address_info.text_start, prginfo->address_info.text_end,
Packit 577717
			( unsigned int ) ( prginfo->address_info.text_end -
Packit 577717
							   prginfo->address_info.text_start ) );
Packit 577717
	printf( "Data start: %p, Data end: %p\n", prginfo->address_info.data_start,
Packit 577717
			prginfo->address_info.data_end );
Packit 577717
	printf( "BSS start : %p, BSS end : %p\n", prginfo->address_info.bss_start,
Packit 577717
			prginfo->address_info.bss_end );
Packit 577717
Packit 577717
	printf
Packit 577717
		( "----------------------------------------------------------------\n" );
Packit 577717
}
Packit 577717
Packit 577717
/* This function displays profining information useful for several profile tests.
Packit 577717
   It (probably inappropriately) assumes use of a common THRESHOLD. This should
Packit 577717
   probably be a passed parameter.
Packit 577717
   Assumed globals: event_name, start, stop.
Packit 577717
*/
Packit 577717
void
Packit 577717
prof_print_prof_info( caddr_t start, caddr_t end, int threshold,
Packit 577717
					  char *event_name )
Packit 577717
{
Packit 577717
	printf( "Profiling event  : %s\n", event_name );
Packit 577717
	printf( "Profile Threshold: %d\n", threshold );
Packit 577717
	printf( "Profile Iters    : %d\n",
Packit 577717
			( getenv( "NUM_ITERS" ) ? atoi( getenv( "NUM_ITERS" ) ) :
Packit 577717
			  NUM_ITERS ) );
Packit 577717
	printf( "Profile Range    : %p to %p\n", start, end );
Packit 577717
	printf
Packit 577717
		( "----------------------------------------------------------------\n" );
Packit 577717
	printf( "\n" );
Packit 577717
}
Packit 577717
Packit 577717
/* Most profile tests begin by counting the eventset with no profiling enabled.
Packit 577717
   This function does that work. It assumes that the 'work' routine is do_both().
Packit 577717
   A better implementation would pass a pointer to the work function.
Packit 577717
   Assumed globals: EventSet, values, event_name.
Packit 577717
*/
Packit 577717
void
Packit 577717
do_no_profile( int quiet )
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
Packit 577717
	if ( ( retval = PAPI_start( EventSet ) ) != PAPI_OK )
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_start", retval );
Packit 577717
Packit 577717
	do_flops( getenv( "NUM_ITERS" ) ? atoi( getenv( "NUM_ITERS" ) ) :
Packit 577717
			  NUM_ITERS );
Packit 577717
Packit 577717
	if ( ( retval = PAPI_stop( EventSet, values[0] ) ) != PAPI_OK )
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
Packit 577717
Packit 577717
	if (!quiet) {
Packit 577717
		printf( "Test type   : \t%s\n", "No profiling" );
Packit 577717
		printf( TAB1, event_name, ( values[0] )[0] );
Packit 577717
		printf( TAB1, "PAPI_TOT_CYC", ( values[0] )[1] );
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
/* This routine allocates and initializes up to 5 equal sized profiling buffers.
Packit 577717
   They need to be freed when profiling is completed.
Packit 577717
   The number and size are passed parameters.
Packit 577717
   The profbuf[] array of void * pointers is an assumed global.
Packit 577717
   It should be cast to the required type by the parent routine.
Packit 577717
*/
Packit 577717
void
Packit 577717
prof_alloc( int num, unsigned long blength )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
Packit 577717
	for ( i = 0; i < num; i++ ) {
Packit 577717
		profbuf[i] = malloc( blength );
Packit 577717
		if ( profbuf[i] == NULL ) {
Packit 577717
			test_fail( __FILE__, __LINE__, "malloc", PAPI_ESYS );
Packit 577717
		}
Packit 577717
		memset( profbuf[i], 0x00, blength );
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
/* Given the profiling type (16, 32, or 64) this function returns the 
Packit 577717
   bucket size in bytes. NOTE: the bucket size does not ALWAYS correspond
Packit 577717
   to the expected value, esp on architectures like Cray with weird data types.
Packit 577717
   This is necessary because the posix_profile routine in extras.c relies on
Packit 577717
   the data types and sizes produced by the compiler.
Packit 577717
*/
Packit 577717
int
Packit 577717
prof_buckets( int bucket )
Packit 577717
{
Packit 577717
	int bucket_size;
Packit 577717
	switch ( bucket ) {
Packit 577717
	case PAPI_PROFIL_BUCKET_16:
Packit 577717
		bucket_size = sizeof ( short );
Packit 577717
		break;
Packit 577717
	case PAPI_PROFIL_BUCKET_32:
Packit 577717
		bucket_size = sizeof ( int );
Packit 577717
		break;
Packit 577717
	case PAPI_PROFIL_BUCKET_64:
Packit 577717
		bucket_size = sizeof ( unsigned long long );
Packit 577717
		break;
Packit 577717
	default:
Packit 577717
		bucket_size = 0;
Packit 577717
		break;
Packit 577717
	}
Packit 577717
	return ( bucket_size );
Packit 577717
}
Packit 577717
Packit 577717
/* A standardized header printing routine. No assumed globals.
Packit 577717
*/
Packit 577717
void
Packit 577717
prof_head( unsigned long blength, int bucket, int num_buckets, const char *header )
Packit 577717
{
Packit 577717
	int bucket_size = prof_buckets( bucket );
Packit 577717
	printf
Packit 577717
		( "\n------------------------------------------------------------\n" );
Packit 577717
	printf( "PAPI_profil() hash table, Bucket size: %d bits.\n",
Packit 577717
			bucket_size * 8 );
Packit 577717
	printf( "Number of buckets: %d.\nLength of buffer: %ld bytes.\n",
Packit 577717
			num_buckets, blength );
Packit 577717
	printf( "------------------------------------------------------------\n" );
Packit 577717
	printf( "%s\n", header );
Packit 577717
}
Packit 577717
Packit 577717
/* This function prints a standardized profile output based on the bucket size.
Packit 577717
   A row consisting of an address and 'n' data elements is displayed for each
Packit 577717
   address with at least one non-zero bucket.
Packit 577717
   Assumes global profbuf[] array pointers.
Packit 577717
*/
Packit 577717
void
Packit 577717
prof_out( caddr_t start, int n, int bucket, int num_buckets,
Packit 577717
		  unsigned int scale )
Packit 577717
{
Packit 577717
	int i, j;
Packit 577717
	unsigned short buf_16;
Packit 577717
	unsigned int buf_32;
Packit 577717
	unsigned long long buf_64;
Packit 577717
	unsigned short **buf16 = ( unsigned short ** ) profbuf;
Packit 577717
	unsigned int **buf32 = ( unsigned int ** ) profbuf;
Packit 577717
	unsigned long long **buf64 = ( unsigned long long ** ) profbuf;
Packit 577717
Packit 577717
	if ( !TESTS_QUIET ) {
Packit 577717
		/* printf("%#lx\n",(unsigned long) start + (unsigned long) (2 * i)); */
Packit 577717
		/* printf("start: %p; i: %#x; scale: %#x; i*scale: %#x; i*scale >>15: %#x\n", start, i, scale, i*scale, (i*scale)>>15); */
Packit 577717
		switch ( bucket ) {
Packit 577717
		case PAPI_PROFIL_BUCKET_16:
Packit 577717
			for ( i = 0; i < num_buckets; i++ ) {
Packit 577717
				for ( j = 0, buf_16 = 0; j < n; j++ )
Packit 577717
					buf_16 |= ( buf16[j] )[i];
Packit 577717
				if ( buf_16 ) {
Packit 577717
/* On 32bit builds with gcc 4.3 gcc complained about casting caddr_t => long long
Packit 577717
 * Thus the unsigned long to long long cast */
Packit 577717
					printf( "%#-16llx",
Packit 577717
						(long long) (unsigned long)start +
Packit 577717
						( ( ( long long ) i * scale ) >> 15 ) );
Packit 577717
					for ( j = 0, buf_16 = 0; j < n; j++ )
Packit 577717
						printf( "\t%d", ( buf16[j] )[i] );
Packit 577717
					printf( "\n" );
Packit 577717
				}
Packit 577717
			}
Packit 577717
			break;
Packit 577717
		case PAPI_PROFIL_BUCKET_32:
Packit 577717
			for ( i = 0; i < num_buckets; i++ ) {
Packit 577717
				for ( j = 0, buf_32 = 0; j < n; j++ )
Packit 577717
					buf_32 |= ( buf32[j] )[i];
Packit 577717
				if ( buf_32 ) {
Packit 577717
					printf( "%#-16llx",
Packit 577717
						(long long) (unsigned long)start +
Packit 577717
						( ( ( long long ) i * scale ) >> 15 ) );
Packit 577717
					for ( j = 0, buf_32 = 0; j < n; j++ )
Packit 577717
						printf( "\t%d", ( buf32[j] )[i] );
Packit 577717
					printf( "\n" );
Packit 577717
				}
Packit 577717
			}
Packit 577717
			break;
Packit 577717
		case PAPI_PROFIL_BUCKET_64:
Packit 577717
			for ( i = 0; i < num_buckets; i++ ) {
Packit 577717
				for ( j = 0, buf_64 = 0; j < n; j++ )
Packit 577717
					buf_64 |= ( buf64[j] )[i];
Packit 577717
				if ( buf_64 ) {
Packit 577717
					printf( "%#-16llx",
Packit 577717
						(long long) (unsigned long)start +
Packit 577717
					        ( ( ( long long ) i * scale ) >> 15 ) );
Packit 577717
					for ( j = 0, buf_64 = 0; j < n; j++ )
Packit 577717
						printf( "\t%lld", ( buf64[j] )[i] );
Packit 577717
					printf( "\n" );
Packit 577717
				}
Packit 577717
			}
Packit 577717
			break;
Packit 577717
		}
Packit 577717
		printf
Packit 577717
			( "------------------------------------------------------------\n\n" );
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
/* This function checks to make sure that some buffer value somewhere is nonzero.
Packit 577717
   If all buffers are empty, zero is returned. This usually indicates a profiling
Packit 577717
   failure. Assumes global profbuf[].
Packit 577717
*/
Packit 577717
int
Packit 577717
prof_check( int n, int bucket, int num_buckets )
Packit 577717
{
Packit 577717
	int i, j;
Packit 577717
	int retval = 0;
Packit 577717
	unsigned short **buf16 = ( unsigned short ** ) profbuf;
Packit 577717
	unsigned int **buf32 = ( unsigned int ** ) profbuf;
Packit 577717
	unsigned long long **buf64 = ( unsigned long long ** ) profbuf;
Packit 577717
Packit 577717
	switch ( bucket ) {
Packit 577717
	case PAPI_PROFIL_BUCKET_16:
Packit 577717
		for ( i = 0; i < num_buckets; i++ )
Packit 577717
			for ( j = 0; j < n; j++ )
Packit 577717
				retval = retval || buf16[j][i];
Packit 577717
		break;
Packit 577717
	case PAPI_PROFIL_BUCKET_32:
Packit 577717
		for ( i = 0; i < num_buckets; i++ )
Packit 577717
			for ( j = 0; j < n; j++ )
Packit 577717
				retval = retval || buf32[j][i];
Packit 577717
		break;
Packit 577717
	case PAPI_PROFIL_BUCKET_64:
Packit 577717
		for ( i = 0; i < num_buckets; i++ )
Packit 577717
			for ( j = 0; j < n; j++ )
Packit 577717
				retval = retval || buf64[j][i];
Packit 577717
		break;
Packit 577717
	}
Packit 577717
	return ( retval );
Packit 577717
}
Packit 577717
Packit 577717
/* Computes the length (in bytes) of the buffer required for profiling.
Packit 577717
   'plength' is the profile length, or address range to be profiled.
Packit 577717
   By convention, it is assumed that there are half as many buckets as addresses.
Packit 577717
   The scale factor is a fixed point fraction in which 0xffff = ~1
Packit 577717
                                                         0x8000 = 1/2
Packit 577717
                                                         0x4000 = 1/4, etc.
Packit 577717
   Thus, the number of profile buckets is (plength/2) * (scale/65536),
Packit 577717
   and the length (in bytes) of the profile buffer is buckets * bucket size.
Packit 577717
   */
Packit 577717
unsigned long
Packit 577717
prof_size( unsigned long plength, unsigned scale, int bucket, int *num_buckets )
Packit 577717
{
Packit 577717
	unsigned long blength;
Packit 577717
	long long llength = ( ( long long ) plength * scale );
Packit 577717
	int bucket_size = prof_buckets( bucket );
Packit 577717
	*num_buckets = ( int ) ( llength / 65536 / 2 );
Packit 577717
	blength = ( unsigned long ) ( *num_buckets * bucket_size );
Packit 577717
	return ( blength );
Packit 577717
}