PAPI 7.1.0.0
Loading...
Searching...
No Matches
papi_hl.c File Reference

This file contains the 'high level' interface to PAPI. BASIC is a high level language. ;-) More...

Include dependency graph for papi_hl.c:

Go to the source code of this file.

Data Structures

struct  components_t
 
struct  local_components_t
 
struct  reads_t
 
struct  value_t
 
struct  regions_t
 
struct  threads_t
 
struct  binary_tree_t
 

Macros

#define verbose_fprintf    if (verbosity == 1) fprintf
 
#define PAPIHL_NUM_OF_COMPONENTS   10
 
#define PAPIHL_NUM_OF_EVENTS_PER_COMPONENT   10
 
#define PAPIHL_ACTIVE   1
 
#define PAPIHL_DEACTIVATED   0
 
#define PAPIHL_MAX_STACK_SIZE   10
 

Enumerations

enum  region_type { REGION_BEGIN , REGION_READ , REGION_END }
 

Functions

int compar (const void *l, const void *r)
 
static void _internal_hl_library_init (void)
 
static void _internal_hl_onetime_library_init (void)
 
static int _internal_hl_checkCounter (char *counter)
 
static int _internal_hl_determine_rank ()
 
static char * _internal_hl_remove_spaces (char *str, int mode)
 
static int _internal_hl_determine_default_events ()
 
static int _internal_hl_read_user_events ()
 
static int _internal_hl_new_component (int component_id, components_t *component)
 
static int _internal_hl_add_event_to_component (char *event_name, int event, short event_type, components_t *component)
 
static int _internal_hl_create_components ()
 
static int _internal_hl_read_events (const char *events)
 
static int _internal_hl_create_event_sets ()
 
static int _internal_hl_start_counters ()
 
static int _internal_hl_region_id_pop ()
 
static int _internal_hl_region_id_push ()
 
static int _internal_hl_region_id_stack_peak ()
 
static reads_t_internal_hl_insert_read_node (reads_t **head_node)
 
static int _internal_hl_add_values_to_region (regions_t *node, enum region_type reg_typ)
 
static regions_t_internal_hl_insert_region_node (regions_t **head_node, const char *region)
 
static regions_t_internal_hl_find_region_node (regions_t *head_node, const char *region)
 
static threads_t_internal_hl_insert_thread_node (unsigned long tid)
 
static threads_t_internal_hl_find_thread_node (unsigned long tid)
 
static int _internal_hl_store_counters (unsigned long tid, const char *region, enum region_type reg_typ)
 
static int _internal_hl_read_counters ()
 
static int _internal_hl_read_and_store_counters (const char *region, enum region_type reg_typ)
 
static int _internal_hl_create_global_binary_tree ()
 
static int _internal_hl_mkdir (const char *dir)
 
static int _internal_hl_determine_output_path ()
 
static void _internal_hl_json_line_break_and_indent (FILE *f, bool b, int width)
 
static void _internal_hl_json_definitions (FILE *f, bool beautifier)
 
static void _internal_hl_json_region_events (FILE *f, bool beautifier, regions_t *regions)
 
static void _internal_hl_json_regions (FILE *f, bool beautifier, threads_t *thread_node)
 
static void _internal_hl_json_threads (FILE *f, bool beautifier, unsigned long *tids, int threads_num)
 
static int _internal_hl_cmpfunc (const void *a, const void *b)
 
static int _internal_get_sorted_thread_list (unsigned long **tids, int *threads_num)
 
static void _internal_hl_write_json_file (FILE *f, unsigned long *tids, int threads_num)
 
static void _internal_hl_read_json_file (const char *path)
 
static void _internal_hl_write_output ()
 
static void _internal_hl_clean_up_local_data ()
 
static void _internal_hl_clean_up_global_data ()
 
static void _internal_hl_clean_up_all (bool deactivate)
 
static int _internal_hl_check_for_clean_thread_states ()
 
int _internal_PAPI_hl_init ()
 
int _internal_PAPI_hl_cleanup_thread ()
 
int _internal_PAPI_hl_finalize ()
 
int _internal_PAPI_hl_set_events (const char *events)
 
void _internal_PAPI_hl_print_output ()
 
static int _internal_hl_read_user_events (const char *user_events)
 
int PAPI_hl_region_begin (const char *region)
 
int PAPI_hl_read (const char *region)
 
int PAPI_hl_region_end (const char *region)
 
int PAPI_hl_stop ()
 

Variables

components_tcomponents = NULL
 
int num_of_components = 0
 
int max_num_of_components = PAPIHL_NUM_OF_COMPONENTS
 
int total_num_events = 0
 
int num_of_cleaned_threads = 0
 
THREAD_LOCAL_STORAGE_KEYWORD local_components_t_local_components = NULL
 
THREAD_LOCAL_STORAGE_KEYWORD long_long _local_cycles
 
THREAD_LOCAL_STORAGE_KEYWORD volatile bool _local_state = PAPIHL_ACTIVE
 
THREAD_LOCAL_STORAGE_KEYWORD unsigned int _local_region_begin_cnt = 0
 
THREAD_LOCAL_STORAGE_KEYWORD unsigned int _local_region_end_cnt = 0
 
THREAD_LOCAL_STORAGE_KEYWORD unsigned int _local_region_id_stack [PAPIHL_MAX_STACK_SIZE]
 
THREAD_LOCAL_STORAGE_KEYWORD int _local_region_id_top = -1
 
binary_tree_tbinary_tree = NULL
 
char ** requested_event_names = NULL
 
int num_of_requested_events = 0
 
bool hl_initiated = false
 
bool hl_finalized = false
 
bool events_determined = false
 
bool output_generated = false
 
static char * absolute_output_file_path = NULL
 
static int output_counter = 0
 
short verbosity = 0
 
bool state = PAPIHL_ACTIVE
 
static int region_begin_cnt = 0
 
static int region_end_cnt = 0
 
unsigned long master_thread_id = -1
 

Detailed Description

Macro Definition Documentation

◆ PAPIHL_ACTIVE

#define PAPIHL_ACTIVE   1

Definition at line 44 of file papi_hl.c.

◆ PAPIHL_DEACTIVATED

#define PAPIHL_DEACTIVATED   0

Definition at line 45 of file papi_hl.c.

◆ PAPIHL_MAX_STACK_SIZE

#define PAPIHL_MAX_STACK_SIZE   10

Definition at line 48 of file papi_hl.c.

◆ PAPIHL_NUM_OF_COMPONENTS

#define PAPIHL_NUM_OF_COMPONENTS   10

Definition at line 41 of file papi_hl.c.

◆ PAPIHL_NUM_OF_EVENTS_PER_COMPONENT

#define PAPIHL_NUM_OF_EVENTS_PER_COMPONENT   10

Definition at line 42 of file papi_hl.c.

◆ verbose_fprintf

#define verbose_fprintf    if (verbosity == 1) fprintf

Definition at line 37 of file papi_hl.c.

Enumeration Type Documentation

◆ region_type

Enumerator
REGION_BEGIN 
REGION_READ 
REGION_END 

Definition at line 143 of file papi_hl.c.

@ REGION_END
Definition: papi_hl.c:143
@ REGION_READ
Definition: papi_hl.c:143
@ REGION_BEGIN
Definition: papi_hl.c:143

Function Documentation

◆ _internal_get_sorted_thread_list()

static int _internal_get_sorted_thread_list ( unsigned long **  tids,
int threads_num 
)
static

Definition at line 1416 of file papi_hl.c.

1417{
1418 if ( PAPI_list_threads( *tids, threads_num ) != PAPI_OK ) {
1419 verbose_fprintf(stdout, "PAPI-HL Error: PAPI_list_threads call failed!\n");
1420 return -1;
1421 }
1422 if ( ( *tids = malloc( *(threads_num) * sizeof(unsigned long) ) ) == NULL ) {
1423 verbose_fprintf(stdout, "PAPI-HL Error: OOM!\n");
1424 return -1;
1425 }
1426 if ( PAPI_list_threads( *tids, threads_num ) != PAPI_OK ) {
1427 verbose_fprintf(stdout, "PAPI-HL Error: PAPI_list_threads call failed!\n");
1428 return -1;
1429 }
1430
1431 /* sort thread ids in ascending order */
1432 qsort(*tids, *(threads_num), sizeof(unsigned long), _internal_hl_cmpfunc);
1433 return PAPI_OK;
1434}
List the registered thread ids.
#define PAPI_OK
Definition: f90papi.h:73
FILE * stdout
static int _internal_hl_cmpfunc(const void *a, const void *b)
Definition: papi_hl.c:1412
#define verbose_fprintf
Definition: papi_hl.c:37
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_add_event_to_component()

static int _internal_hl_add_event_to_component ( char *  event_name,
int  event,
short  event_type,
components_t component 
)
static

Definition at line 523 of file papi_hl.c.

525{
526 int i, retval;
527
528 /* check if we need to reallocate memory for event_names, event_codes and event_types */
529 if ( component->num_of_events == component->max_num_of_events ) {
530 component->max_num_of_events *= 2;
531
532 component->event_names = (char**)realloc(component->event_names, component->max_num_of_events * sizeof(char*));
533 if ( component->event_names == NULL )
534 return ( PAPI_ENOMEM );
535
536 component->event_codes = (int*)realloc(component->event_codes, component->max_num_of_events * sizeof(int));
537 if ( component->event_codes == NULL )
538 return ( PAPI_ENOMEM );
539
540 component->event_types = (short*)realloc(component->event_types, component->max_num_of_events * sizeof(short));
541 if ( component->event_types == NULL )
542 return ( PAPI_ENOMEM );
543 }
544
545 retval = PAPI_add_event( component->EventSet, event );
546 if ( retval != PAPI_OK ) {
547 const PAPI_component_info_t* cmpinfo;
548 cmpinfo = PAPI_get_component_info( component->component_id );
549 verbose_fprintf(stdout, "PAPI-HL Warning: Cannot add %s to component %s.\n", event_name, cmpinfo->name);
550 verbose_fprintf(stdout, "The following event combination is not supported:\n");
551 for ( i = 0; i < component->num_of_events; i++ )
552 verbose_fprintf(stdout, " %s\n", component->event_names[i]);
554 verbose_fprintf(stdout, "Advice: Use papi_event_chooser to obtain an appropriate event set for this component or set PAPI_MULTIPLEX=1.\n");
555
556 return PAPI_EINVAL;
557 }
558
559 component->event_names[component->num_of_events] = event_name;
560 component->event_codes[component->num_of_events] = event;
561 component->event_types[component->num_of_events] = event_type;
562 component->num_of_events += 1;
563
564 total_num_events += 1;
565
566 return PAPI_OK;
567}
int i
add PAPI preset or native hardware event to an event set
get information about a specific software component
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:29
#define PAPI_EINVAL
Definition: f90papi.h:115
#define PAPI_ENOMEM
Definition: f90papi.h:16
int total_num_events
Definition: papi_hl.c:65
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:627
char ** event_names
Definition: papi_hl.c:56
int num_of_events
Definition: papi_hl.c:54
int * event_codes
Definition: papi_hl.c:57
int max_num_of_events
Definition: papi_hl.c:55
short * event_types
Definition: papi_hl.c:58
int component_id
Definition: papi_hl.c:53
int EventSet
Definition: papi_hl.c:59
int retval
Definition: zero_fork.c:53
Here is the caller graph for this function:

◆ _internal_hl_add_values_to_region()

static int _internal_hl_add_values_to_region ( regions_t node,
enum region_type  reg_typ 
)
inlinestatic

Definition at line 856 of file papi_hl.c.

857{
858 int i, j;
859 long_long ts;
860 int cmp_iter = 2;
861
862 /* get timestamp */
863 ts = PAPI_get_real_nsec();
864
865 if ( reg_typ == REGION_BEGIN ) {
866 /* set first fixed counters */
867 node->values[0].begin = _local_cycles;
868 node->values[1].begin = ts;
869 /* events from components */
870 for ( i = 0; i < num_of_components; i++ )
871 for ( j = 0; j < components[i].num_of_events; j++ )
872 node->values[cmp_iter++].begin = _local_components[i].values[j];
873 } else if ( reg_typ == REGION_READ ) {
874 /* create a new read node and add values*/
875 reads_t* read_node;
876 if ( ( read_node = _internal_hl_insert_read_node(&node->values[0].read_values) ) == NULL )
877 return ( PAPI_ENOMEM );
878 read_node->value = _local_cycles - node->values[0].begin;
879 if ( ( read_node = _internal_hl_insert_read_node(&node->values[1].read_values) ) == NULL )
880 return ( PAPI_ENOMEM );
881 read_node->value = ts - node->values[1].begin;
882 for ( i = 0; i < num_of_components; i++ ) {
883 for ( j = 0; j < components[i].num_of_events; j++ ) {
884 if ( ( read_node = _internal_hl_insert_read_node(&node->values[cmp_iter].read_values) ) == NULL )
885 return ( PAPI_ENOMEM );
886 if ( components[i].event_types[j] == 1 )
887 read_node->value = _local_components[i].values[j];
888 else
889 read_node->value = _local_components[i].values[j] - node->values[cmp_iter].begin;
890 cmp_iter++;
891 }
892 }
893 } else if ( reg_typ == REGION_END ) {
894 /* determine difference of current value and begin */
895 node->values[0].region_value = _local_cycles - node->values[0].begin;
896 node->values[1].region_value = ts - node->values[1].begin;
897 /* events from components */
898 for ( i = 0; i < num_of_components; i++ )
899 for ( j = 0; j < components[i].num_of_events; j++ ) {
900 /* if event type is instantaneous only save last value */
901 if ( components[i].event_types[j] == 1 ) {
902 node->values[cmp_iter].region_value = _local_components[i].values[j];
903 } else {
904 node->values[cmp_iter].region_value = _local_components[i].values[j] - node->values[cmp_iter].begin;
905 }
906 cmp_iter++;
907 }
908 }
909 return ( PAPI_OK );
910}
Get real time counter value in nanoseconds.
#define long_long
Definition: papi.h:559
components_t * components
Definition: papi_hl.c:62
THREAD_LOCAL_STORAGE_KEYWORD local_components_t * _local_components
Definition: papi_hl.c:79
static reads_t * _internal_hl_insert_read_node(reads_t **head_node)
Definition: papi_hl.c:834
int num_of_components
Definition: papi_hl.c:63
THREAD_LOCAL_STORAGE_KEYWORD long_long _local_cycles
Definition: papi_hl.c:80
long_long * values
Definition: papi_hl.c:76
long_long value
Definition: papi_hl.c:97
value_t values[]
Definition: papi_hl.c:114
long_long region_value
Definition: papi_hl.c:103
long_long begin
Definition: papi_hl.c:102
reads_t * read_values
Definition: papi_hl.c:104
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_check_for_clean_thread_states()

static int _internal_hl_check_for_clean_thread_states ( )
static

Definition at line 1741 of file papi_hl.c.

1742{
1743 EventSetInfo_t *ESI;
1745 int i;
1746
1747 for( i = 0; i < map->totalSlots; i++ ) {
1748 ESI = map->dataSlotArray[i];
1749 if ( ESI ) {
1750 if ( ESI->state & PAPI_RUNNING )
1751 return ( PAPI_EISRUN );
1752 }
1753 }
1754 return ( PAPI_OK );
1755}
#define PAPI_RUNNING
Definition: f90papi.h:165
#define PAPI_EISRUN
Definition: f90papi.h:277
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:56
EventSetInfo_t ** dataSlotArray
DynamicArray_t global_eventset_map
Here is the caller graph for this function:

◆ _internal_hl_checkCounter()

static int _internal_hl_checkCounter ( char *  counter)
static

Definition at line 303 of file papi_hl.c.

304{
305 int EventSet = PAPI_NULL;
306 int eventcode;
307 int retval;
308
309 HLDBG("Counter: %s\n", counter);
310 if ( ( retval = PAPI_create_eventset( &EventSet ) ) != PAPI_OK )
311 return ( retval );
312
313 if ( ( retval = PAPI_event_name_to_code( counter, &eventcode ) ) != PAPI_OK ) {
314 HLDBG("Counter %s does not exist\n", counter);
315 return ( retval );
316 }
317
318 if ( ( retval = PAPI_add_event (EventSet, eventcode) ) != PAPI_OK ) {
319 HLDBG("Cannot add counter %s\n", counter);
320 return ( retval );
321 }
322
324 return ( retval );
325
327 return ( retval );
328
329 return ( PAPI_OK );
330}
Empty and destroy an EventSet.
Create a new empty PAPI EventSet.
Empty and destroy an EventSet.
Convert a name to a numeric hardware event code.
#define PAPI_NULL
Definition: f90papi.h:78
static int EventSet
Definition: init_fini.c:8
#define HLDBG(format, args...)
Definition: papi_debug.h:73
Here is the caller graph for this function:

◆ _internal_hl_clean_up_all()

static void _internal_hl_clean_up_all ( bool  deactivate)
static

Definition at line 1688 of file papi_hl.c.

1689{
1690 int i, num_of_threads;
1691
1692 /* we assume that output has been already generated or
1693 * cannot be generated due to previous errors */
1694 output_generated = true;
1695
1696 /* clean up thread local data */
1697 if ( _local_state == PAPIHL_ACTIVE ) {
1698 HLDBG("Clean up thread local data for thread %lu\n", PAPI_thread_id());
1700 }
1701
1702 /* clean up global data */
1703 if ( state == PAPIHL_ACTIVE ) {
1705 if ( state == PAPIHL_ACTIVE ) {
1706
1707 verbose_fprintf(stdout, "PAPI-HL Info: Output generation is deactivated!\n");
1708
1709 HLDBG("Clean up global data for thread %lu\n", PAPI_thread_id());
1711
1712 /* check if all other registered threads have cleaned up */
1713 PAPI_list_threads(NULL, &num_of_threads);
1714
1715 HLDBG("Number of registered threads: %d.\n", num_of_threads);
1716 HLDBG("Number of cleaned threads: %d.\n", num_of_cleaned_threads);
1717
1719 num_of_threads == num_of_cleaned_threads ) {
1720 PAPI_shutdown();
1721 /* clean up components */
1722 for ( i = 0; i < num_of_components; i++ ) {
1723 free(components[i].event_names);
1724 free(components[i].event_codes);
1725 free(components[i].event_types);
1726 }
1727 free(components);
1728 HLDBG("PAPI-HL shutdown!\n");
1729 } else {
1730 verbose_fprintf(stdout, "PAPI-HL Warning: Could not call PAPI_shutdown() since some threads still have running event sets.\n");
1731 }
1732
1733 /* deactivate PAPI-HL */
1734 if ( deactivate )
1736 }
1738 }
1739}
static const char * event_names[2]
Definition: Gamum.c:27
Finish using PAPI and free all related resources.
Get the thread identifier of the current thread.
#define PAPIHL_ACTIVE
Definition: papi_hl.c:44
static void _internal_hl_clean_up_global_data()
Definition: papi_hl.c:1637
#define PAPIHL_DEACTIVATED
Definition: papi_hl.c:45
bool state
Definition: papi_hl.c:155
static int _internal_hl_check_for_clean_thread_states()
Definition: papi_hl.c:1741
static void _internal_hl_clean_up_local_data()
Definition: papi_hl.c:1608
THREAD_LOCAL_STORAGE_KEYWORD volatile bool _local_state
Definition: papi_hl.c:81
bool output_generated
Definition: papi_hl.c:151
int num_of_cleaned_threads
Definition: papi_hl.c:66
#define HIGHLEVEL_LOCK
Definition: papi_internal.h:88
inline_static int _papi_hwi_lock(int lck)
Definition: threads.h:69
inline_static int _papi_hwi_unlock(int lck)
Definition: threads.h:83
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_clean_up_global_data()

static void _internal_hl_clean_up_global_data ( )
static

Definition at line 1637 of file papi_hl.c.

1638{
1639 int i;
1640 int extended_total_num_events;
1641
1642 /* clean up binary tree of recorded events */
1643 threads_t *thread_node;
1644 if ( binary_tree != NULL ) {
1645 while ( binary_tree->root != NULL ) {
1646 thread_node = *(threads_t **)binary_tree->root;
1647
1648 /* clean up double linked list of region data */
1649 regions_t *region = thread_node->value;
1650 regions_t *tmp;
1651 while ( region != NULL ) {
1652
1653 /* clean up read node list */
1654 extended_total_num_events = total_num_events + 2;
1655 for ( i = 0; i < extended_total_num_events; i++ ) {
1656 reads_t *read_node = region->values[i].read_values;
1657 reads_t *read_node_tmp;
1658 while ( read_node != NULL ) {
1659 read_node_tmp = read_node;
1660 read_node = read_node->next;
1661 free(read_node_tmp);
1662 }
1663 }
1664
1665 tmp = region;
1666 region = region->next;
1667
1668 free(tmp->region);
1669 free(tmp);
1670 }
1671 free(region);
1672
1673 tdelete(thread_node, &binary_tree->root, compar);
1674 free(thread_node);
1675 }
1676 }
1677
1678 /* we cannot free components here since other threads could still use them */
1679
1680 /* clean up requested event names */
1681 for ( i = 0; i < num_of_requested_events; i++ )
1682 free(requested_event_names[i]);
1684
1686}
double tmp
char ** requested_event_names
Definition: papi_hl.c:145
int compar(const void *l, const void *r)
Definition: papi_hl.c:123
binary_tree_t * binary_tree
Definition: papi_hl.c:137
int num_of_requested_events
Definition: papi_hl.c:146
static char * absolute_output_file_path
Definition: papi_hl.c:152
void * root
Definition: papi_hl.c:132
struct reads * next
Definition: papi_hl.c:95
regions_t * value
Definition: papi_hl.c:120
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_clean_up_local_data()

static void _internal_hl_clean_up_local_data ( )
static

Definition at line 1608 of file papi_hl.c.

1609{
1610 int i, retval;
1611 /* destroy all EventSets from local data */
1612 if ( _local_components != NULL ) {
1613 HLDBG("Thread-ID:%lu\n", PAPI_thread_id());
1614 for ( i = 0; i < num_of_components; i++ ) {
1616 /* only print error when event set is running */
1617 if ( retval != -9 )
1618 verbose_fprintf(stdout, "PAPI-HL Error: PAPI_stop failed: %d.\n", retval);
1620 verbose_fprintf(stdout, "PAPI-HL Error: PAPI_cleanup_eventset failed: %d.\n", retval);
1622 verbose_fprintf(stdout, "PAPI-HL Error: PAPI_destroy_eventset failed: %d.\n", retval);
1623 free(_local_components[i].values);
1624 }
1625 free(_local_components);
1626 _local_components = NULL;
1627
1628 /* count global thread variable */
1632 }
1635}
Stop counting hardware events in an event set.
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
THREAD_LOCAL_STORAGE_KEYWORD int _papi_hl_events_running
Definition: papi_internal.c:63
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_cmpfunc()

static int _internal_hl_cmpfunc ( const void *  a,
const void *  b 
)
static

Definition at line 1412 of file papi_hl.c.

1412 {
1413 return ( *(int*)a - *(int*)b );
1414}
static double a[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:38
static double b[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:39
Here is the caller graph for this function:

◆ _internal_hl_create_components()

static int _internal_hl_create_components ( )
static

Definition at line 569 of file papi_hl.c.

570{
571 int i, j, retval, event;
572 int component_id = -1;
573 int comp_index = 0;
574 bool component_exists = false;
575 short event_type = 0;
576
577 HLDBG("Create components\n");
579 if ( components == NULL )
580 return ( PAPI_ENOMEM );
581
582 for ( i = 0; i < num_of_requested_events; i++ ) {
583 /* check if requested event contains event type (instant or delta) */
584 const char sep = '=';
585 char *ret;
586 int index;
587 /* search for '=' in event name */
588 ret = strchr(requested_event_names[i], sep);
589 if (ret) {
590 if ( strcmp(ret, "=instant") == 0 )
591 event_type = 1;
592 else
593 event_type = 0;
594
595 /* get index of '=' in event name */
596 index = (int)(ret - requested_event_names[i]);
597 /* remove event type from string if '=instant' or '=delta' */
598 if ( (strcmp(ret, "=instant") == 0) || (strcmp(ret, "=delta") == 0) )
599 requested_event_names[i][index] = '\0';
600 }
601
602 /* change event type to instantaneous for specific events */
603 /* we consider all nvml events as instantaneous values */
604 if( (strstr(requested_event_names[i], "nvml:::") != NULL) ) {
605 event_type = 1;
606 verbose_fprintf(stdout, "PAPI-HL Info: The event \"%s\" will be stored as instantaneous value.\n", requested_event_names[i]);
607 }
608
609 /* check if event is supported on current machine */
611 if ( retval != PAPI_OK ) {
612 verbose_fprintf(stdout, "PAPI-HL Warning: \"%s\" does not exist or is not supported on this machine.\n", requested_event_names[i]);
613 } else {
614 /* determine event code and corresponding component id */
616 if ( retval != PAPI_OK )
617 return ( retval );
618 component_id = PAPI_COMPONENT_INDEX( event );
619
620 /* check if component_id already exists in global components structure */
621 for ( j = 0; j < num_of_components; j++ ) {
622 if ( components[j].component_id == component_id ) {
623 component_exists = true;
624 comp_index = j;
625 break;
626 }
627 else {
628 component_exists = false;
629 }
630 }
631
632 /* create new component */
633 if ( false == component_exists ) {
634 /* check if we need to reallocate memory for components */
638 if ( components == NULL )
639 return ( PAPI_ENOMEM );
640 }
641 comp_index = num_of_components;
642 retval = _internal_hl_new_component(component_id, &components[comp_index]);
643 if ( retval != PAPI_OK )
644 return ( retval );
645 }
646
647 /* add event to current component */
649 if ( retval == PAPI_ENOMEM )
650 return ( retval );
651 }
652 }
653
654 HLDBG("Number of components %d\n", num_of_components);
655 if ( num_of_components > 0 )
656 verbose_fprintf(stdout, "PAPI-HL Info: Using the following events:\n");
657
658 /* destroy all EventSets from global data */
659 for ( i = 0; i < num_of_components; i++ ) {
661 return ( retval );
663 return ( retval );
665
666 HLDBG("component_id = %d\n", components[i].component_id);
667 HLDBG("num_of_events = %d\n", components[i].num_of_events);
668 for ( j = 0; j < components[i].num_of_events; j++ ) {
669 HLDBG(" %s type=%d\n", components[i].event_names[j], components[i].event_types[j]);
671 }
672 }
673
674 if ( num_of_components == 0 )
675 return PAPI_EINVAL;
676
677 return PAPI_OK;
678}
#define PAPI_COMPONENT_INDEX(a)
Definition: papi.h:1246
static int _internal_hl_checkCounter(char *counter)
Definition: papi_hl.c:303
static int _internal_hl_add_event_to_component(char *event_name, int event, short event_type, components_t *component)
Definition: papi_hl.c:523
static int _internal_hl_new_component(int component_id, components_t *component)
Definition: papi_hl.c:470
int max_num_of_components
Definition: papi_hl.c:64
int
Definition: sde_internal.h:89
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_create_event_sets()

static int _internal_hl_create_event_sets ( )
static

Definition at line 732 of file papi_hl.c.

733{
734 int i, j, retval;
735
736 if ( state == PAPIHL_ACTIVE ) {
737 /* allocate memory for local components */
739 if ( _local_components == NULL )
740 return ( PAPI_ENOMEM );
741
742 for ( i = 0; i < num_of_components; i++ ) {
743 /* create EventSet */
746 return (retval );
747 }
748
749 /* Support multiplexing if user wants to */
750 if ( getenv("PAPI_MULTIPLEX") != NULL ) {
751
752 /* multiplex only for cpu core events */
753 if ( components[i].component_id == 0 ) {
755 if ( retval != PAPI_OK ) {
756 verbose_fprintf(stdout, "PAPI-HL Error: PAPI_assign_eventset_component failed.\n");
757 } else {
760 if ( retval != PAPI_OK ) {
761 verbose_fprintf(stdout, "PAPI-HL Error: PAPI_set_multiplex failed.\n");
762 }
763 }
764 }
765 }
766 }
767
768 /* add event to current EventSet */
769 for ( j = 0; j < components[i].num_of_events; j++ ) {
771 if ( retval != PAPI_OK ) {
772 return (retval );
773 }
774 }
775 /* allocate memory for return values */
776 _local_components[i].values = (long_long*)malloc(components[i].num_of_events * sizeof(long_long));
777 if ( _local_components[i].values == NULL )
778 return ( PAPI_ENOMEM );
779
780 }
781 return PAPI_OK;
782 }
783 return ( PAPI_EMISC );
784}
Assign a component index to an existing but empty EventSet.
Get the multiplexing status of specified event set.
Convert a standard event set to a multiplexed event set.
#define PAPI_EMISC
Definition: f90papi.h:122
Here is the caller graph for this function:

◆ _internal_hl_create_global_binary_tree()

static int _internal_hl_create_global_binary_tree ( )
static

Definition at line 1095 of file papi_hl.c.

1096{
1097 if ( ( binary_tree = (binary_tree_t*)malloc(sizeof(binary_tree_t)) ) == NULL )
1098 return ( PAPI_ENOMEM );
1099 binary_tree->root = NULL;
1100 if ( ( binary_tree->find_p = (threads_t*)malloc(sizeof(threads_t)) ) == NULL )
1101 return ( PAPI_ENOMEM );
1102 return ( PAPI_OK );
1103}
threads_t * find_p
Definition: papi_hl.c:133
Here is the caller graph for this function:

◆ _internal_hl_determine_default_events()

static int _internal_hl_determine_default_events ( )
static

Definition at line 366 of file papi_hl.c.

367{
368 int i;
369 HLDBG("Default events\n");
370 char *default_events[] = {
371 "PAPI_TOT_CYC",
372 };
373 int num_of_defaults = sizeof(default_events) / sizeof(char*);
374
375 /* allocate memory for requested events */
376 requested_event_names = (char**)malloc(num_of_defaults * sizeof(char*));
377 if ( requested_event_names == NULL )
378 return ( PAPI_ENOMEM );
379
380 /* check if default events are available on the current machine */
381 for ( i = 0; i < num_of_defaults; i++ ) {
382 if ( _internal_hl_checkCounter( default_events[i] ) == PAPI_OK ) {
383 requested_event_names[num_of_requested_events++] = strdup(default_events[i]);
385 return ( PAPI_ENOMEM );
386 }
387 else {
388 /* if PAPI_FP_OPS is not available try PAPI_SP_OPS or PAPI_DP_OPS */
389 if ( strcmp(default_events[i], "PAPI_FP_OPS") == 0 ) {
390 if ( _internal_hl_checkCounter( "PAPI_SP_OPS" ) == PAPI_OK )
391 requested_event_names[num_of_requested_events++] = strdup("PAPI_SP_OPS");
392 else if ( _internal_hl_checkCounter( "PAPI_DP_OPS" ) == PAPI_OK )
393 requested_event_names[num_of_requested_events++] = strdup("PAPI_DP_OPS");
394 }
395
396 /* if PAPI_FP_INS is not available try PAPI_VEC_SP or PAPI_VEC_DP */
397 if ( strcmp(default_events[i], "PAPI_FP_INS") == 0 ) {
398 if ( _internal_hl_checkCounter( "PAPI_VEC_SP" ) == PAPI_OK )
399 requested_event_names[num_of_requested_events++] = strdup("PAPI_VEC_SP");
400 else if ( _internal_hl_checkCounter( "PAPI_VEC_DP" ) == PAPI_OK )
401 requested_event_names[num_of_requested_events++] = strdup("PAPI_VEC_DP");
402 }
403 }
404 }
405
406 return ( PAPI_OK );
407}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_determine_output_path()

static int _internal_hl_determine_output_path ( )
static

Definition at line 1149 of file papi_hl.c.

1150{
1151 /* check if PAPI_OUTPUT_DIRECTORY is set */
1152 char *output_prefix = NULL;
1153 if ( getenv("PAPI_OUTPUT_DIRECTORY") != NULL ) {
1154 if ( ( output_prefix = strdup( getenv("PAPI_OUTPUT_DIRECTORY") ) ) == NULL )
1155 return ( PAPI_ENOMEM );
1156 } else {
1157 if ( ( output_prefix = strdup( getcwd(NULL,0) ) ) == NULL )
1158 return ( PAPI_ENOMEM );
1159 }
1160
1161 /* generate absolute path for measurement directory */
1162 if ( ( absolute_output_file_path = (char *)malloc((strlen(output_prefix) + 64) * sizeof(char)) ) == NULL ) {
1163 free(output_prefix);
1164 return ( PAPI_ENOMEM );
1165 }
1166 if ( output_counter > 0 )
1167 sprintf(absolute_output_file_path, "%s/papi_hl_output_%d", output_prefix, output_counter);
1168 else
1169 sprintf(absolute_output_file_path, "%s/papi_hl_output", output_prefix);
1170
1171 /* check if directory already exists */
1172 struct stat buf;
1173 if ( stat(absolute_output_file_path, &buf) == 0 && S_ISDIR(buf.st_mode) ) {
1174
1175 /* rename old directory by adding a timestamp */
1176 char *new_absolute_output_file_path = NULL;
1177 if ( ( new_absolute_output_file_path = (char *)malloc((strlen(absolute_output_file_path) + 64) * sizeof(char)) ) == NULL ) {
1178 free(output_prefix);
1180 return ( PAPI_ENOMEM );
1181 }
1182
1183 /* create timestamp */
1184 time_t t = time(NULL);
1185 struct tm tm = *localtime(&t);
1186 char m_time[32];
1187 sprintf(m_time, "%d%02d%02d-%02d%02d%02d", tm.tm_year+1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
1188 /* add timestamp to existing folder string */
1189 sprintf(new_absolute_output_file_path, "%s-%s", absolute_output_file_path, m_time);
1190
1191 uintmax_t current_unix_time = (uintmax_t)t;
1192 uintmax_t unix_time_from_old_directory = buf.st_mtime;
1193
1194 /* This is a workaround for MPI applications!!!
1195 * Only rename existing measurement directory when it is older than
1196 * current timestamp. If it's not, we assume that another MPI process already created a
1197 * new measurement directory. */
1198 if ( unix_time_from_old_directory < current_unix_time ) {
1199
1200 if ( rename(absolute_output_file_path, new_absolute_output_file_path) != 0 ) {
1201 verbose_fprintf(stdout, "PAPI-HL Warning: Cannot rename old measurement directory.\n");
1202 verbose_fprintf(stdout, "If you use MPI, another process may have already renamed the directory.\n");
1203 }
1204 }
1205
1206 free(new_absolute_output_file_path);
1207 }
1208 free(output_prefix);
1210
1211 return ( PAPI_OK );
1212}
volatile int buf[CACHE_FLUSH_BUFFER_SIZE_INTS]
Definition: do_loops.c:12
int rename(const char *__old, const char *__new) __attribute__((__nothrow__
static int output_counter
Definition: papi_hl.c:153
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_determine_rank()

static int _internal_hl_determine_rank ( )
static

Definition at line 332 of file papi_hl.c.

333{
334 int rank = -1;
335 /* check environment variables for rank identification */
336
337 if ( getenv("OMPI_COMM_WORLD_RANK") != NULL )
338 rank = atoi(getenv("OMPI_COMM_WORLD_RANK"));
339 else if ( getenv("ALPS_APP_PE") != NULL )
340 rank = atoi(getenv("ALPS_APP_PE"));
341 else if ( getenv("PMI_RANK") != NULL )
342 rank = atoi(getenv("PMI_RANK"));
343 else if ( getenv("SLURM_PROCID") != NULL )
344 rank = atoi(getenv("SLURM_PROCID"));
345
346 return rank;
347}
Here is the caller graph for this function:

◆ _internal_hl_find_region_node()

static regions_t * _internal_hl_find_region_node ( regions_t head_node,
const char *  region 
)
inlinestatic

Definition at line 955 of file papi_hl.c.

956{
957 regions_t* find_node = head_node;
958 while ( find_node != NULL ) {
959 if ( ((int)find_node->region_id == _internal_hl_region_id_stack_peak()) && (strcmp(find_node->region, region) == 0) ) {
960 return find_node;
961 }
962 find_node = find_node->next;
963 }
964 find_node = NULL;
965 return find_node;
966}
static int _internal_hl_region_id_stack_peak()
Definition: papi_hl.c:826
struct regions * next
Definition: papi_hl.c:112
unsigned int region_id
Definition: papi_hl.c:109
char * region
Definition: papi_hl.c:111
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_find_thread_node()

static threads_t * _internal_hl_find_thread_node ( unsigned long  tid)
inlinestatic

Definition at line 979 of file papi_hl.c.

980{
981 threads_t *find_node = binary_tree->find_p;
982 find_node->key = tid;
983 void *found = tfind(find_node, &binary_tree->root, compar);
984 if ( found != NULL ) {
985 find_node = (*(threads_t**)found);
986 return find_node;
987 }
988 return NULL;
989}
unsigned long key
Definition: papi_hl.c:119
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_insert_read_node()

static reads_t * _internal_hl_insert_read_node ( reads_t **  head_node)
inlinestatic

Definition at line 834 of file papi_hl.c.

835{
836 reads_t *new_node;
837
838 /* create new region node */
839 if ( ( new_node = malloc(sizeof(reads_t)) ) == NULL )
840 return ( NULL );
841 new_node->next = NULL;
842 new_node->prev = NULL;
843
844 /* insert node in list */
845 if ( *head_node == NULL ) {
846 *head_node = new_node;
847 return new_node;
848 }
849 (*head_node)->prev = new_node;
850 new_node->next = *head_node;
851 *head_node = new_node;
852
853 return new_node;
854}
struct reads * prev
Definition: papi_hl.c:96
Here is the caller graph for this function:

◆ _internal_hl_insert_region_node()

static regions_t * _internal_hl_insert_region_node ( regions_t **  head_node,
const char *  region 
)
inlinestatic

Definition at line 913 of file papi_hl.c.

914{
915 regions_t *new_node;
916 int i;
917 int extended_total_num_events;
918
919 /* number of all events including CPU cycles and real time */
920 extended_total_num_events = total_num_events + 2;
921
922 /* create new region node */
923 new_node = malloc(sizeof(regions_t) + extended_total_num_events * sizeof(value_t));
924 if ( new_node == NULL )
925 return ( NULL );
926 new_node->region = (char *)malloc((strlen(region) + 1) * sizeof(char));
927 if ( new_node->region == NULL ) {
928 free(new_node);
929 return ( NULL );
930 }
931
932 new_node->next = NULL;
933 new_node->prev = NULL;
934
937 strcpy(new_node->region, region);
938 for ( i = 0; i < extended_total_num_events; i++ ) {
939 new_node->values[i].read_values = NULL;
940 }
941
942 /* insert node in list */
943 if ( *head_node == NULL ) {
944 *head_node = new_node;
945 return new_node;
946 }
947 (*head_node)->prev = new_node;
948 new_node->next = *head_node;
949 *head_node = new_node;
950
951 return new_node;
952}
THREAD_LOCAL_STORAGE_KEYWORD unsigned int _local_region_begin_cnt
Definition: papi_hl.c:82
struct regions * prev
Definition: papi_hl.c:113
int parent_region_id
Definition: papi_hl.c:110
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_insert_thread_node()

static threads_t * _internal_hl_insert_thread_node ( unsigned long  tid)
inlinestatic

Definition at line 968 of file papi_hl.c.

969{
970 threads_t *new_node = (threads_t*)malloc(sizeof(threads_t));
971 if ( new_node == NULL )
972 return ( NULL );
973 new_node->key = tid;
974 new_node->value = NULL; /* head node of region list */
975 tsearch(new_node, &binary_tree->root, compar);
976 return new_node;
977}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_json_definitions()

static void _internal_hl_json_definitions ( FILE *  f,
bool  beautifier 
)
static

Definition at line 1224 of file papi_hl.c.

1225{
1226 int num_events, i, j;
1227
1229 fprintf(f, "\"event_definitions\":{");
1230
1231 /* get all events + types */
1232 num_events = 1;
1233 for ( i = 0; i < num_of_components; i++ ) {
1234 for ( j = 0; j < components[i].num_of_events; j++ ) {
1236
1237 const char *event_type = "delta";
1238 if ( components[i].event_types[j] == 1 )
1239 event_type = "instant";
1240 const PAPI_component_info_t* cmpinfo;
1241 cmpinfo = PAPI_get_component_info( components[i].component_id );
1242
1243 fprintf(f, "\"%s\":{", components[i].event_names[j]);
1245 fprintf(f, "\"component\":\"%s\",", cmpinfo->name);
1247 fprintf(f, "\"type\":\"%s\"", event_type);
1249 fprintf(f, "}");
1251 fprintf(f, ",");
1252 num_events++;
1253 }
1254 }
1255
1257 fprintf(f, "},");
1258}
double f(double a)
Definition: cpi.c:23
static int num_events
static void _internal_hl_json_line_break_and_indent(FILE *f, bool b, int width)
Definition: papi_hl.c:1214
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_json_line_break_and_indent()

static void _internal_hl_json_line_break_and_indent ( FILE *  f,
bool  b,
int  width 
)
static

Definition at line 1214 of file papi_hl.c.

1215{
1216 int i;
1217 if ( b ) {
1218 fprintf(f, "\n");
1219 for ( i = 0; i < width; ++i )
1220 fprintf(f, " ");
1221 }
1222}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_json_region_events()

static void _internal_hl_json_region_events ( FILE *  f,
bool  beautifier,
regions_t regions 
)
static

Definition at line 1260 of file papi_hl.c.

1261{
1262 char **all_event_names = NULL;
1263 int *all_event_types = NULL;
1264 int extended_total_num_events;
1265 int i, j, cmp_iter;
1266
1267 /* generate array of all events including CPU cycles and real time for output */
1268 extended_total_num_events = total_num_events + 2;
1269 all_event_names = (char**)malloc(extended_total_num_events * sizeof(char*));
1270 all_event_names[0] = "cycles";
1271 all_event_names[1] = "real_time_nsec";
1272
1273 all_event_types = (int*)malloc(extended_total_num_events * sizeof(int));
1274 all_event_types[0] = 0;
1275 all_event_types[1] = 0;
1276
1277
1278 cmp_iter = 2;
1279 for ( i = 0; i < num_of_components; i++ ) {
1280 for ( j = 0; j < components[i].num_of_events; j++ ) {
1281 all_event_names[cmp_iter] = components[i].event_names[j];
1282 if ( components[i].event_types[j] == 0 )
1283 all_event_types[cmp_iter] = 0;
1284 else
1285 all_event_types[cmp_iter] = 1;
1286 cmp_iter++;
1287 }
1288 }
1289
1290 for ( j = 0; j < extended_total_num_events; j++ ) {
1291
1293
1294 /* print read values if available */
1295 if ( regions->values[j].read_values != NULL) {
1296 reads_t* read_node = regions->values[j].read_values;
1297 /* going to last node */
1298 while ( read_node->next != NULL ) {
1299 read_node = read_node->next;
1300 }
1301 /* read values in reverse order */
1302 int read_cnt = 1;
1303 fprintf(f, "\"%s\":{", all_event_names[j]);
1304
1306 fprintf(f, "\"region_value\":\"%lld\",", regions->values[j].region_value);
1307
1308 while ( read_node != NULL ) {
1310 fprintf(f, "\"read_%d\":\"%lld\"", read_cnt,read_node->value);
1311
1312 read_node = read_node->prev;
1313
1314 if ( read_node == NULL ) {
1316 fprintf(f, "}");
1317 if ( j < extended_total_num_events - 1 )
1318 fprintf(f, ",");
1319 } else {
1320 fprintf(f, ",");
1321 }
1322
1323 read_cnt++;
1324 }
1325 } else {
1326 HLDBG(" %s:%lld\n", all_event_names[j], regions->values[j].region_value);
1327 fprintf(f, "\"%s\":\"%lld\"", all_event_names[j], regions->values[j].region_value);
1328 if ( j < ( extended_total_num_events - 1 ) )
1329 fprintf(f, ",");
1330 }
1331 }
1332
1333 free(all_event_names);
1334 free(all_event_types);
1335}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_json_regions()

static void _internal_hl_json_regions ( FILE *  f,
bool  beautifier,
threads_t thread_node 
)
static

Definition at line 1337 of file papi_hl.c.

1338{
1339 /* iterate over regions list */
1340 regions_t *regions = thread_node->value;
1341
1342 /* going to last node */
1343 while ( regions->next != NULL ) {
1344 regions = regions->next;
1345 }
1346
1347 /* read regions in reverse order */
1348 while (regions != NULL) {
1349 HLDBG(" Region:%u\n", regions->region_id);
1350
1352 fprintf(f, "\"%u\":{", regions->region_id);
1353
1355 fprintf(f, "\"name\":\"%s\",", regions->region);
1357 fprintf(f, "\"parent_region_id\":\"%d\",", regions->parent_region_id);
1358
1359 _internal_hl_json_region_events(f, beautifier, regions);
1360
1361 regions = regions->prev;
1363 if (regions == NULL ) {
1364 fprintf(f, "}");
1365 } else {
1366 fprintf(f, "},");
1367 }
1368 }
1369}
static void _internal_hl_json_region_events(FILE *f, bool beautifier, regions_t *regions)
Definition: papi_hl.c:1260
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_json_threads()

static void _internal_hl_json_threads ( FILE *  f,
bool  beautifier,
unsigned long tids,
int  threads_num 
)
static

Definition at line 1371 of file papi_hl.c.

1372{
1373 int i;
1374
1376 fprintf(f, "\"threads\":{");
1377
1378 /* get regions of all threads */
1379 for ( i = 0; i < threads_num; i++ )
1380 {
1381 HLDBG("Thread ID:%lu\n", tids[i]);
1382 /* find values of current thread in global binary tree */
1383 threads_t* thread_node = _internal_hl_find_thread_node(tids[i]);
1384 if ( thread_node != NULL ) {
1385 /* do we really need the exact thread id? */
1386 /* we only store iterator id as thread id, not tids[i] */
1388 fprintf(f, "\"%d\":{", i);
1389
1391 fprintf(f, "\"regions\":{");
1392
1393 _internal_hl_json_regions(f, beautifier, thread_node);
1394
1396 fprintf(f, "}");
1397
1399 if ( i < threads_num - 1 ) {
1400 fprintf(f, "},");
1401 } else {
1402 fprintf(f, "}");
1403 }
1404 }
1405 }
1406
1408 fprintf(f, "}");
1409
1410}
static void _internal_hl_json_regions(FILE *f, bool beautifier, threads_t *thread_node)
Definition: papi_hl.c:1337
static threads_t * _internal_hl_find_thread_node(unsigned long tid)
Definition: papi_hl.c:979
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_library_init()

static void _internal_hl_library_init ( void  )
static

Definition at line 224 of file papi_hl.c.

225{
226 /* This function is only called by one thread! */
227 int retval;
228
229 /* check VERBOSE level */
230 if ( getenv("PAPI_HL_VERBOSE") != NULL ) {
231 verbosity = 1;
232 }
233
235 verbose_fprintf(stdout, "PAPI-HL Error: PAPI_library_init failed!\n");
236
237 /* PAPI_thread_init only suceeds if PAPI_library_init has suceeded */
238 char *multi_thread = getenv("PAPI_HL_THREAD_MULTIPLE");
239 if ( NULL == multi_thread || atoi(multi_thread) == 1 ) {
241 } else {
243 }
244
245 if (retval == PAPI_OK) {
246
247 /* determine output directory and output file */
249 verbose_fprintf(stdout, "PAPI-HL Error: _internal_hl_determine_output_path failed!\n");
251 verbose_fprintf(stdout, "PAPI-HL Error: PAPI could not be initiated!\n");
252 } else {
253
254 /* register the termination function for output */
256 verbose_fprintf(stdout, "PAPI-HL Info: PAPI has been initiated!\n");
257
258 /* remember thread id */
260 HLDBG("master_thread_id=%lu\n", master_thread_id);
261 }
262
263 /* Support multiplexing if user wants to */
264 if ( getenv("PAPI_MULTIPLEX") != NULL ) {
266 if ( retval == PAPI_ENOSUPP) {
267 verbose_fprintf(stdout, "PAPI-HL Info: Multiplex is not supported!\n");
268 } else if ( retval != PAPI_OK ) {
269 verbose_fprintf(stdout, "PAPI-HL Error: PAPI_multiplex_init failed!\n");
270 } else if ( retval == PAPI_OK ) {
271 verbose_fprintf(stdout, "PAPI-HL Info: Multiplex has been initiated!\n");
272 }
273 }
274
275 } else {
276 verbose_fprintf(stdout, "PAPI-HL Error: PAPI_thread_init failed!\n");
278 verbose_fprintf(stdout, "PAPI-HL Error: PAPI could not be initiated!\n");
279 }
280
281 hl_initiated = true;
282}
initialize the PAPI library.
Initialize multiplex support in the PAPI library.
Initialize thread support in the PAPI library.
#define PAPI_VER_CURRENT
Definition: f90papi.h:54
#define PAPI_ENOSUPP
Definition: f90papi.h:244
int multi_thread(int argc, char *argv[])
bool hl_initiated
Definition: papi_hl.c:148
static int _internal_hl_determine_output_path()
Definition: papi_hl.c:1149
unsigned long master_thread_id
Definition: papi_hl.c:158
void _internal_PAPI_hl_print_output()
Definition: papi_hl.c:1836
short verbosity
Definition: papi_hl.c:154
unsigned long _papi_gettid(void)
Definition: threads.c:613
unsigned long _papi_getpid(void)
Definition: threads.c:634
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_mkdir()

static int _internal_hl_mkdir ( const char *  dir)
static

Definition at line 1106 of file papi_hl.c.

1107{
1108 int retval;
1109 int errno;
1110 char *tmp = NULL;
1111 char *p = NULL;
1112 size_t len;
1113
1114 if ( ( tmp = strdup(dir) ) == NULL )
1115 return ( PAPI_ENOMEM );
1116 len = strlen(tmp);
1117
1118 /* check if there is a file with the same name as the ouptut directory */
1119 struct stat buf;
1120 if ( stat(dir, &buf) == 0 && S_ISREG(buf.st_mode) ) {
1121 verbose_fprintf(stdout, "PAPI-HL Error: Name conflict with measurement directory and existing file.\n");
1122 return ( PAPI_ESYS );
1123 }
1124
1125 if(tmp[len - 1] == '/')
1126 tmp[len - 1] = 0;
1127 for(p = tmp + 1; *p; p++)
1128 {
1129 if(*p == '/')
1130 {
1131 *p = 0;
1132 errno = 0;
1133 retval = mkdir(tmp, S_IRWXU);
1134 *p = '/';
1135 if ( retval != 0 && errno != EEXIST ) {
1136 free(tmp);
1137 return ( PAPI_ESYS );
1138 }
1139 }
1140 }
1141 retval = mkdir(tmp, S_IRWXU);
1142 free(tmp);
1143 if ( retval != 0 && errno != EEXIST )
1144 return ( PAPI_ESYS );
1145
1146 return ( PAPI_OK );
1147}
int errno
#define PAPI_ESYS
Definition: f90papi.h:136
Here is the caller graph for this function:

◆ _internal_hl_new_component()

static int _internal_hl_new_component ( int  component_id,
components_t component 
)
static

Definition at line 470 of file papi_hl.c.

471{
472 int retval;
473
474 /* create new EventSet */
475 component->EventSet = PAPI_NULL;
476 if ( ( retval = PAPI_create_eventset( &component->EventSet ) ) != PAPI_OK ) {
477 verbose_fprintf(stdout, "PAPI-HL Error: Cannot create EventSet for component %d.\n", component_id);
478 return ( retval );
479 }
480
481 /* Support multiplexing if user wants to */
482 if ( getenv("PAPI_MULTIPLEX") != NULL ) {
483
484 /* multiplex only for cpu core events */
485 if ( component_id == 0 ) {
486 retval = PAPI_assign_eventset_component(component->EventSet, component_id);
487 if ( retval != PAPI_OK ) {
488 verbose_fprintf(stdout, "PAPI-HL Error: PAPI_assign_eventset_component failed.\n");
489 } else {
490 if ( PAPI_get_multiplex(component->EventSet) == false ) {
491 retval = PAPI_set_multiplex(component->EventSet);
492 if ( retval != PAPI_OK ) {
493 verbose_fprintf(stdout, "PAPI-HL Error: PAPI_set_multiplex failed.\n");
494 }
495 }
496 }
497 }
498 }
499
500 component->component_id = component_id;
501 component->num_of_events = 0;
503
504 component->event_names = NULL;
505 component->event_names = (char**)malloc(component->max_num_of_events * sizeof(char*));
506 if ( component->event_names == NULL )
507 return ( PAPI_ENOMEM );
508
509 component->event_codes = NULL;
510 component->event_codes = (int*)malloc(component->max_num_of_events * sizeof(int));
511 if ( component->event_codes == NULL )
512 return ( PAPI_ENOMEM );
513
514 component->event_types = NULL;
515 component->event_types = (short*)malloc(component->max_num_of_events * sizeof(short));
516 if ( component->event_types == NULL )
517 return ( PAPI_ENOMEM );
518
520 return ( PAPI_OK );
521}
#define PAPIHL_NUM_OF_EVENTS_PER_COMPONENT
Definition: papi_hl.c:42
Here is the caller graph for this function:

◆ _internal_hl_onetime_library_init()

static void _internal_hl_onetime_library_init ( void  )
static

Definition at line 284 of file papi_hl.c.

285{
286 static pthread_once_t library_is_initialized = PTHREAD_ONCE_INIT;
287 if ( pthread_once ) {
288 /* we assume that PAPI_hl_init() is called from a parallel region */
289 pthread_once(&library_is_initialized, _internal_hl_library_init);
290 /* wait until first thread has finished */
291 int i = 0;
292 /* give it 5 seconds in case PAPI_thread_init crashes */
293 while ( !hl_initiated && (i++) < 500000 )
294 usleep(10);
295 } else {
296 /* we assume that PAPI_hl_init() is called from a serial application
297 * that was not linked against libpthread */
299 }
300}
int pthread_once_t
static void _internal_hl_library_init(void)
Definition: papi_hl.c:224
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_read_and_store_counters()

static int _internal_hl_read_and_store_counters ( const char *  region,
enum region_type  reg_typ 
)
static

Definition at line 1075 of file papi_hl.c.

1076{
1077 int retval;
1078 /* read all events */
1079 if ( ( retval = _internal_hl_read_counters() ) != PAPI_OK ) {
1080 verbose_fprintf(stdout, "PAPI-HL Error: Could not read counters for thread %lu.\n", PAPI_thread_id());
1082 return ( retval );
1083 }
1084
1085 /* store all events */
1086 if ( ( retval = _internal_hl_store_counters( PAPI_thread_id(), region, reg_typ) ) != PAPI_OK ) {
1087 verbose_fprintf(stdout, "PAPI-HL Error: Could not store counters for thread %lu.\n", PAPI_thread_id());
1088 verbose_fprintf(stdout, "PAPI-HL Advice: Check if your regions are matching.\n");
1090 return ( retval );
1091 }
1092 return ( PAPI_OK );
1093}
static int _internal_hl_store_counters(unsigned long tid, const char *region, enum region_type reg_typ)
Definition: papi_hl.c:992
static int _internal_hl_read_counters()
Definition: papi_hl.c:1054
static void _internal_hl_clean_up_all(bool deactivate)
Definition: papi_hl.c:1688
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_read_counters()

static int _internal_hl_read_counters ( )
static

Definition at line 1054 of file papi_hl.c.

1055{
1056 int i, j, retval;
1057 for ( i = 0; i < num_of_components; i++ ) {
1058 if ( i < ( num_of_components - 1 ) ) {
1060 } else {
1061 /* get cycles for last component */
1063 }
1064 HLDBG("Thread-ID:%lu, Component-ID:%d\n", PAPI_thread_id(), components[i].component_id);
1065 for ( j = 0; j < components[i].num_of_events; j++ ) {
1066 HLDBG("Thread-ID:%lu, %s:%lld\n", PAPI_thread_id(), components[i].event_names[j], _local_components[i].values[j]);
1067 }
1068
1069 if ( retval != PAPI_OK )
1070 return ( retval );
1071 }
1072 return ( PAPI_OK );
1073}
Read hardware counters with a timestamp.
Read hardware counters from an event set.
Here is the caller graph for this function:

◆ _internal_hl_read_events()

static int _internal_hl_read_events ( const char *  events)
static

Definition at line 680 of file papi_hl.c.

681{
682 int i, retval;
683 HLDBG("Read events: %s\n", events);
684 if ( events != NULL ) {
687 return ( retval );
688
689 /* check if user specified events via environment variable */
690 } else if ( getenv("PAPI_EVENTS") != NULL ) {
691 char *user_events_from_env = strdup( getenv("PAPI_EVENTS") );
692 if ( user_events_from_env == NULL )
693 return ( PAPI_ENOMEM );
694 /* if string is emtpy use default events */
695 if ( strlen( user_events_from_env ) == 0 ) {
697 free(user_events_from_env);
698 return ( retval );
699 }
700 }
701 else if ( _internal_hl_read_user_events(user_events_from_env) != PAPI_OK )
703 free(user_events_from_env);
704 return ( retval );
705 }
706 free(user_events_from_env);
707 } else {
709 return ( retval );
710 }
711
712 /* create components based on requested events */
714 {
715 /* requested events do not work at all, use default events */
716 verbose_fprintf(stdout, "PAPI-HL Warning: All requested events do not work, using default.\n");
717
718 for ( i = 0; i < num_of_requested_events; i++ )
723 return ( retval );
725 return ( retval );
726 }
727
728 events_determined = true;
729 return ( PAPI_OK );
730}
char events[MAX_EVENTS][BUFSIZ]
static int _internal_hl_read_user_events()
static int _internal_hl_determine_default_events()
Definition: papi_hl.c:366
static int _internal_hl_create_components()
Definition: papi_hl.c:569
bool events_determined
Definition: papi_hl.c:150
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_read_json_file()

static void _internal_hl_read_json_file ( const char *  path)
static

Definition at line 1474 of file papi_hl.c.

1475{
1476 /* print output to stdout */
1477 printf("\n\nPAPI-HL Output:\n");
1478 FILE* output_file = fopen(path, "r");
1479 int c = fgetc(output_file);
1480 while (c != EOF)
1481 {
1482 printf("%c", c);
1483 c = fgetc(output_file);
1484 }
1485 printf("\n");
1486 fclose(output_file);
1487}
static double c[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:40
int fclose(FILE *__stream)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_read_user_events() [1/2]

static int _internal_hl_read_user_events ( )
static
Here is the caller graph for this function:

◆ _internal_hl_read_user_events() [2/2]

static int _internal_hl_read_user_events ( const char *  user_events)
static

Definition at line 409 of file papi_hl.c.

410{
411 char* user_events_copy;
412 const char *separator; //separator for events
413 int num_of_req_events = 1; //number of events in string
414 int req_event_index = 0; //index of event
415 const char *position = NULL; //current position in processed string
416 char *token;
417
418 HLDBG("User events: %s\n", user_events);
419 user_events_copy = strdup(user_events);
420 if ( user_events_copy == NULL )
421 return ( PAPI_ENOMEM );
422
423 /* check if string is not empty */
424 if ( strlen( user_events_copy ) > 0 )
425 {
426 /* count number of separator characters */
427 position = user_events_copy;
428 separator=",";
429 while ( *position ) {
430 if ( strchr( separator, *position ) ) {
431 num_of_req_events++;
432 }
433 position++;
434 }
435
436 /* allocate memory for requested events */
437 requested_event_names = (char**)malloc(num_of_req_events * sizeof(char*));
438 if ( requested_event_names == NULL ) {
439 free(user_events_copy);
440 return ( PAPI_ENOMEM );
441 }
442
443 /* parse list of event names */
444 token = strtok( user_events_copy, separator );
445 while ( token ) {
446 if ( req_event_index >= num_of_req_events ){
447 /* more entries as in the first run */
448 free(user_events_copy);
449 return PAPI_EINVAL;
450 }
451 requested_event_names[req_event_index] = strdup(_internal_hl_remove_spaces(token, 0));
452 if ( requested_event_names[req_event_index] == NULL ) {
453 free(user_events_copy);
454 return ( PAPI_ENOMEM );
455 }
456 token = strtok( NULL, separator );
457 req_event_index++;
458 }
459 }
460
461 num_of_requested_events = req_event_index;
462 free(user_events_copy);
463 if ( num_of_requested_events == 0 )
464 return PAPI_EINVAL;
465
466 HLDBG("Number of requested events: %d\n", num_of_requested_events);
467 return ( PAPI_OK );
468}
static char * _internal_hl_remove_spaces(char *str, int mode)
Definition: papi_hl.c:349
Here is the call graph for this function:

◆ _internal_hl_region_id_pop()

static int _internal_hl_region_id_pop ( )
static

Definition at line 807 of file papi_hl.c.

807 {
808 if ( _local_region_id_top == -1 ) {
809 return PAPI_ENOEVNT;
810 } else {
812 }
813 return PAPI_OK;
814}
#define PAPI_ENOEVNT
Definition: f90papi.h:139
THREAD_LOCAL_STORAGE_KEYWORD int _local_region_id_top
Definition: papi_hl.c:86
Here is the caller graph for this function:

◆ _internal_hl_region_id_push()

static int _internal_hl_region_id_push ( )
static

Definition at line 816 of file papi_hl.c.

816 {
818 return PAPI_ENOMEM;
819 } else {
822 }
823 return PAPI_OK;
824}
THREAD_LOCAL_STORAGE_KEYWORD unsigned int _local_region_id_stack[PAPIHL_MAX_STACK_SIZE]
Definition: papi_hl.c:85
#define PAPIHL_MAX_STACK_SIZE
Definition: papi_hl.c:48
Here is the caller graph for this function:

◆ _internal_hl_region_id_stack_peak()

static int _internal_hl_region_id_stack_peak ( )
static

Definition at line 826 of file papi_hl.c.

826 {
827 if ( _local_region_id_top == -1 ) {
828 return -1;
829 } else {
831 }
832}
Here is the caller graph for this function:

◆ _internal_hl_remove_spaces()

static char * _internal_hl_remove_spaces ( char *  str,
int  mode 
)
static

Definition at line 349 of file papi_hl.c.

350{
351 char *out = str, *put = str;
352 for(; *str != '\0'; ++str) {
353 if ( mode == 0 ) {
354 if(*str != ' ')
355 *put++ = *str;
356 } else {
357 while (*str == ' ' && *(str + 1) == ' ')
358 str++;
359 *put++ = *str;
360 }
361 }
362 *put = '\0';
363 return out;
364}
Here is the caller graph for this function:

◆ _internal_hl_start_counters()

static int _internal_hl_start_counters ( )
static

Definition at line 786 of file papi_hl.c.

787{
788 int i, retval;
789 long_long cycles;
790
791 if ( state == PAPIHL_ACTIVE ) {
792 for ( i = 0; i < num_of_components; i++ ) {
794 return (retval );
795
796 /* warm up PAPI code paths and data structures */
798 return (retval );
799 }
800 }
802 return PAPI_OK;
803 }
804 return ( PAPI_EMISC );
805}
Start counting hardware events in an event set.
Here is the caller graph for this function:

◆ _internal_hl_store_counters()

static int _internal_hl_store_counters ( unsigned long  tid,
const char *  region,
enum region_type  reg_typ 
)
static

Definition at line 992 of file papi_hl.c.

994{
995 int retval;
996
998 threads_t* current_thread_node;
999
1000 /* check if current thread is already stored in tree */
1001 current_thread_node = _internal_hl_find_thread_node(tid);
1002 if ( current_thread_node == NULL ) {
1003 /* insert new node for current thread in tree if type is REGION_BEGIN */
1004 if ( reg_typ == REGION_BEGIN ) {
1005 if ( ( current_thread_node = _internal_hl_insert_thread_node(tid) ) == NULL ) {
1007 return ( PAPI_ENOMEM );
1008 }
1009 } else {
1011 return ( PAPI_EINVAL );
1012 }
1013 }
1014
1015 regions_t* current_region_node;
1016 if ( reg_typ == REGION_READ || reg_typ == REGION_END ) {
1017 current_region_node = _internal_hl_find_region_node(current_thread_node->value, region);
1018 if ( current_region_node == NULL ) {
1019 if ( reg_typ == REGION_READ ) {
1020 /* ignore no matching REGION_READ */
1021 verbose_fprintf(stdout, "PAPI-HL Warning: Cannot find matching region for PAPI_hl_read(\"%s\") for thread id=%lu.\n", region, PAPI_thread_id());
1022 retval = PAPI_OK;
1023 } else {
1024 verbose_fprintf(stdout, "PAPI-HL Warning: Cannot find matching region for PAPI_hl_region_end(\"%s\") for thread id=%lu.\n", region, PAPI_thread_id());
1026 }
1028 return ( retval );
1029 }
1030 } else {
1031 /* create new node for current region in list if type is REGION_BEGIN */
1032 if ( ( current_region_node = _internal_hl_insert_region_node(&current_thread_node->value, region) ) == NULL ) {
1034 return ( PAPI_ENOMEM );
1035 }
1036 }
1037
1038
1039 /* add recorded values to current region */
1040 if ( ( retval = _internal_hl_add_values_to_region( current_region_node, reg_typ ) ) != PAPI_OK ) {
1042 return ( retval );
1043 }
1044
1045 /* count all REGION_BEGIN and REGION_END calls */
1046 if ( reg_typ == REGION_BEGIN ) region_begin_cnt++;
1047 if ( reg_typ == REGION_END ) region_end_cnt++;
1048
1050 return ( PAPI_OK );
1051}
static int _internal_hl_add_values_to_region(regions_t *node, enum region_type reg_typ)
Definition: papi_hl.c:856
static regions_t * _internal_hl_insert_region_node(regions_t **head_node, const char *region)
Definition: papi_hl.c:913
static int region_begin_cnt
Definition: papi_hl.c:156
static regions_t * _internal_hl_find_region_node(regions_t *head_node, const char *region)
Definition: papi_hl.c:955
static threads_t * _internal_hl_insert_thread_node(unsigned long tid)
Definition: papi_hl.c:968
static int region_end_cnt
Definition: papi_hl.c:157
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_write_json_file()

static void _internal_hl_write_json_file ( FILE *  f,
unsigned long tids,
int  threads_num 
)
static

Definition at line 1436 of file papi_hl.c.

1437{
1438 /* JSON beautifier (line break and indent) */
1439 bool beautifier = true;
1440
1441 /* start of JSON file */
1442 fprintf(f, "{");
1444 fprintf(f, "\"papi_version\":\"%d.%d.%d.%d\",", PAPI_VERSION_MAJOR( PAPI_VERSION ),
1448
1449 /* add some hardware info */
1450 const PAPI_hw_info_t *hwinfo;
1451 if ( ( hwinfo = PAPI_get_hardware_info( ) ) != NULL ) {
1453 char* cpu_info = _internal_hl_remove_spaces(strdup(hwinfo->model_string), 1);
1454 fprintf(f, "\"cpu_info\":\"%s\",", cpu_info);
1455 free(cpu_info);
1457 fprintf(f, "\"max_cpu_rate_mhz\":\"%d\",", hwinfo->cpu_max_mhz);
1459 fprintf(f, "\"min_cpu_rate_mhz\":\"%d\",", hwinfo->cpu_min_mhz);
1460 }
1461
1462 /* write definitions */
1463 _internal_hl_json_definitions(f, beautifier);
1464
1465 /* write all regions with events per thread */
1466 _internal_hl_json_threads(f, beautifier, tids, threads_num);
1467
1468 /* end of JSON file */
1470 fprintf(f, "}");
1471 fprintf(f, "\n");
1472}
get information about the system hardware
#define PAPI_VERSION
Definition: f90papi.h:193
#define PAPI_VERSION_REVISION(x)
Definition: papi.h:221
#define PAPI_VERSION_MAJOR(x)
Definition: papi.h:219
#define PAPI_VERSION_INCREMENT(x)
Definition: papi.h:222
#define PAPI_VERSION_MINOR(x)
Definition: papi.h:220
static void _internal_hl_json_definitions(FILE *f, bool beautifier)
Definition: papi_hl.c:1224
static void _internal_hl_json_threads(FILE *f, bool beautifier, unsigned long *tids, int threads_num)
Definition: papi_hl.c:1371
Hardware info structure.
Definition: papi.h:774
int cpu_min_mhz
Definition: papi.h:791
char model_string[PAPI_MAX_STR_LEN]
Definition: papi.h:784
int cpu_max_mhz
Definition: papi.h:790
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_hl_write_output()

static void _internal_hl_write_output ( )
static

Definition at line 1489 of file papi_hl.c.

1490{
1491 if ( output_generated == false )
1492 {
1494 if ( output_generated == false ) {
1495 /* check if events were recorded */
1496 if ( binary_tree == NULL ) {
1497 verbose_fprintf(stdout, "PAPI-HL Info: No events were recorded.\n");
1499 return;
1500 }
1501
1503 verbose_fprintf(stdout, "PAPI-HL Info: Print results...\n");
1504 } else {
1505 verbose_fprintf(stdout, "PAPI-HL Warning: Cannot generate output due to not matching regions.\n");
1506 output_generated = true;
1507 HLDBG("region_begin_cnt=%d, region_end_cnt=%d\n", region_begin_cnt, region_end_cnt);
1510 return;
1511 }
1512
1513 /* create new measurement directory */
1515 verbose_fprintf(stdout, "PAPI-HL Error: Cannot create measurement directory %s.\n", absolute_output_file_path);
1517 return;
1518 }
1519
1520 /* determine rank for output file */
1522
1523 /* if system does not provide rank id, create a random id */
1524 if ( rank < 0 ) {
1525 srandom( time(NULL) + getpid() );
1526 rank = random() % 1000000;
1527 }
1528
1529 int unique_output_file_created = 0;
1530 char *final_absolute_output_file_path = NULL;
1531 int fd;
1532 int random_cnt = 0;
1533
1534 /* allocate memory for final output file path */
1535 if ( ( final_absolute_output_file_path = (char *)malloc((strlen(absolute_output_file_path) + 20) * sizeof(char)) ) == NULL ) {
1536 verbose_fprintf(stdout, "PAPI-HL Error: Cannot create output file.\n");
1538 free(final_absolute_output_file_path);
1539 return;
1540 }
1541
1542 /* create unique output file per process based on rank variable */
1543 while ( unique_output_file_created == 0 ) {
1544 rank += random_cnt;
1545 sprintf(final_absolute_output_file_path, "%s/rank_%06d.json", absolute_output_file_path, rank);
1546
1547 fd = open(final_absolute_output_file_path, O_WRONLY|O_APPEND|O_CREAT|O_NONBLOCK, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
1548 if ( fd == -1 ) {
1549 verbose_fprintf(stdout, "PAPI-HL Error: Cannot create output file.\n");
1551 free(final_absolute_output_file_path);
1552 return;
1553 }
1554
1555 struct flock filelock;
1556 filelock.l_type = F_WRLCK; /* Test for any lock on any part of file. */
1557 filelock.l_start = 0;
1558 filelock.l_whence = SEEK_SET;
1559 filelock.l_len = 0;
1560
1561 if ( fcntl(fd, F_SETLK, &filelock) == 0 ) {
1562 unique_output_file_created = 1;
1564
1565 /* write into file */
1566 FILE *fp = fdopen(fd, "w");
1567 if ( fp != NULL ) {
1568
1569 /* list all threads */
1570 unsigned long *tids = NULL;
1571 int threads_num;
1572 if ( _internal_get_sorted_thread_list(&tids, &threads_num) != PAPI_OK ) {
1573 fclose(fp);
1574 free(final_absolute_output_file_path);
1575 return;
1576 }
1577
1578 /* start writing json output */
1579 _internal_hl_write_json_file(fp, tids, threads_num);
1580 free(tids);
1581 fclose(fp);
1582
1583 if ( getenv("PAPI_REPORT") != NULL ) {
1584 _internal_hl_read_json_file(final_absolute_output_file_path);
1585 }
1586
1587 } else {
1588 verbose_fprintf(stdout, "PAPI-HL Error: Cannot create output file: %s\n", strerror( errno ));
1589 free(final_absolute_output_file_path);
1590 fcntl(fd, F_UNLCK, &filelock);
1591 return;
1592 }
1593 fcntl(fd, F_UNLCK, &filelock);
1594 } else {
1595 /* try another file name */
1596 close(fd);
1597 random_cnt++;
1598 }
1599 }
1600
1601 output_generated = true;
1602 free(final_absolute_output_file_path);
1603 }
1605 }
1606}
int open(const char *pathname, int flags, mode_t mode)
Definition: appio.c:188
int close(int fd)
Definition: appio.c:179
static int _internal_hl_mkdir(const char *dir)
Definition: papi_hl.c:1106
static int _internal_get_sorted_thread_list(unsigned long **tids, int *threads_num)
Definition: papi_hl.c:1416
static void _internal_hl_write_json_file(FILE *f, unsigned long *tids, int threads_num)
Definition: papi_hl.c:1436
static int _internal_hl_determine_rank()
Definition: papi_hl.c:332
static void _internal_hl_read_json_file(const char *path)
Definition: papi_hl.c:1474
static FILE * fp
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_PAPI_hl_cleanup_thread()

int _internal_PAPI_hl_cleanup_thread ( )

clean local-thread event sets

Definition at line 1773 of file papi_hl.c.

1774{
1775 if ( state == PAPIHL_ACTIVE &&
1776 hl_initiated == true &&
1778 /* do not clean local data from master thread */
1781 return ( PAPI_OK );
1782 }
1783 return ( PAPI_EMISC );
1784}
Here is the call graph for this function:

◆ _internal_PAPI_hl_finalize()

int _internal_PAPI_hl_finalize ( )

shutdown event sets and clear up everything

Definition at line 1786 of file papi_hl.c.

1787{
1788 if ( state == PAPIHL_ACTIVE && hl_initiated == true ) {
1790 return ( PAPI_OK );
1791 }
1792 return ( PAPI_EMISC );
1793}
Here is the call graph for this function:

◆ _internal_PAPI_hl_init()

int _internal_PAPI_hl_init ( )

intialize high level library

Definition at line 1758 of file papi_hl.c.

1759{
1760 if ( state == PAPIHL_ACTIVE ) {
1761 if ( hl_initiated == false && hl_finalized == false ) {
1763 /* check if the library has been initialized successfully */
1764 if ( state == PAPIHL_DEACTIVATED )
1765 return ( PAPI_EMISC );
1766 return ( PAPI_OK );
1767 }
1768 return ( PAPI_ENOINIT );
1769 }
1770 return ( PAPI_EMISC );
1771}
#define PAPI_ENOINIT
Definition: f90papi.h:160
bool hl_finalized
Definition: papi_hl.c:149
static void _internal_hl_onetime_library_init(void)
Definition: papi_hl.c:284
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_PAPI_hl_print_output()

void _internal_PAPI_hl_print_output ( )

generate output

Definition at line 1836 of file papi_hl.c.

1837{
1838 if ( state == PAPIHL_ACTIVE &&
1839 hl_initiated == true &&
1840 output_generated == false ) {
1842 }
1843}
static void _internal_hl_write_output()
Definition: papi_hl.c:1489
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _internal_PAPI_hl_set_events()

int _internal_PAPI_hl_set_events ( const char *  events)

set specfic events to be recorded

Definition at line 1796 of file papi_hl.c.

1797{
1798 int retval;
1799 if ( state == PAPIHL_ACTIVE ) {
1800
1801 /* This may only be called once after the high-level API was successfully
1802 * initiated. Any second call just returns PAPI_OK without doing an
1803 * expensive lock. */
1804 if ( hl_initiated == true ) {
1805 if ( events_determined == false )
1806 {
1808 if ( events_determined == false && state == PAPIHL_ACTIVE )
1809 {
1810 HLDBG("Set events: %s\n", events);
1815 return ( retval );
1816 }
1821 return ( retval );
1822 }
1823 }
1825 }
1826 }
1827 /* in case the first locked thread ran into problems */
1828 if ( state == PAPIHL_DEACTIVATED)
1829 return ( PAPI_EMISC );
1830 return ( PAPI_OK );
1831 }
1832 return ( PAPI_EMISC );
1833}
static int _internal_hl_read_events(const char *events)
Definition: papi_hl.c:680
static int _internal_hl_create_global_binary_tree()
Definition: papi_hl.c:1095
Here is the call graph for this function:
Here is the caller graph for this function:

◆ compar()

int compar ( const void *  l,
const void *  r 
)

Definition at line 123 of file papi_hl.c.

124{
125 const threads_t *lm = l;
126 const threads_t *lr = r;
127 return lm->key - lr->key;
128}
Here is the caller graph for this function:

Variable Documentation

◆ _local_components

Definition at line 79 of file papi_hl.c.

◆ _local_cycles

Definition at line 80 of file papi_hl.c.

◆ _local_region_begin_cnt

THREAD_LOCAL_STORAGE_KEYWORD unsigned int _local_region_begin_cnt = 0

Count each PAPI_hl_region_begin call

Definition at line 82 of file papi_hl.c.

◆ _local_region_end_cnt

THREAD_LOCAL_STORAGE_KEYWORD unsigned int _local_region_end_cnt = 0

Count each PAPI_hl_region_end call

Definition at line 83 of file papi_hl.c.

◆ _local_region_id_stack

THREAD_LOCAL_STORAGE_KEYWORD unsigned int _local_region_id_stack[PAPIHL_MAX_STACK_SIZE]

Definition at line 85 of file papi_hl.c.

◆ _local_region_id_top

THREAD_LOCAL_STORAGE_KEYWORD int _local_region_id_top = -1

Definition at line 86 of file papi_hl.c.

◆ _local_state

THREAD_LOCAL_STORAGE_KEYWORD volatile bool _local_state = PAPIHL_ACTIVE

Definition at line 81 of file papi_hl.c.

◆ absolute_output_file_path

char* absolute_output_file_path = NULL
static

Definition at line 152 of file papi_hl.c.

◆ binary_tree

binary_tree_t* binary_tree = NULL

Definition at line 137 of file papi_hl.c.

◆ components

components_t* components = NULL

Definition at line 62 of file papi_hl.c.

◆ events_determined

bool events_determined = false

Check if events are determined

Definition at line 150 of file papi_hl.c.

◆ hl_finalized

bool hl_finalized = false

Check PAPI-HL has been fininalized

Definition at line 149 of file papi_hl.c.

◆ hl_initiated

bool hl_initiated = false

Check PAPI-HL has been initiated

Definition at line 148 of file papi_hl.c.

◆ master_thread_id

unsigned long master_thread_id = -1

Remember id of master thread

Definition at line 158 of file papi_hl.c.

◆ max_num_of_components

int max_num_of_components = PAPIHL_NUM_OF_COMPONENTS

Definition at line 64 of file papi_hl.c.

◆ num_of_cleaned_threads

int num_of_cleaned_threads = 0

Definition at line 66 of file papi_hl.c.

◆ num_of_components

int num_of_components = 0

Definition at line 63 of file papi_hl.c.

◆ num_of_requested_events

int num_of_requested_events = 0

Definition at line 146 of file papi_hl.c.

◆ output_counter

int output_counter = 0
static

Count each output generation. Not used yet

Definition at line 153 of file papi_hl.c.

◆ output_generated

bool output_generated = false

Check if output has been already generated

Definition at line 151 of file papi_hl.c.

◆ region_begin_cnt

int region_begin_cnt = 0
static

Count each PAPI_hl_region_begin call

Definition at line 156 of file papi_hl.c.

◆ region_end_cnt

int region_end_cnt = 0
static

Count each PAPI_hl_region_end call

Definition at line 157 of file papi_hl.c.

◆ requested_event_names

char** requested_event_names = NULL

Events from user or default

Definition at line 145 of file papi_hl.c.

◆ state

bool state = PAPIHL_ACTIVE

PAPIHL is active until first error or finalization

Definition at line 155 of file papi_hl.c.

◆ total_num_events

int total_num_events = 0

Definition at line 65 of file papi_hl.c.

◆ verbosity

short verbosity = 0

Verbose output is off by default

Definition at line 154 of file papi_hl.c.