PAPI 7.1.0.0
Loading...
Searching...
No Matches
papi_hl.c
Go to the documentation of this file.
1/****************************/
2/* THIS IS OPEN SOURCE CODE */
3/****************************/
4
14#include <string.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <stdbool.h>
18#include <pthread.h>
19#include <search.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <sys/file.h>
23#include <fcntl.h>
24#include <errno.h>
25#include <time.h>
26#include <stdint.h>
27#include <unistd.h>
28#include "papi.h"
29#include "papi_internal.h"
30
31
32/* For dynamic linking to libpapi */
33/* Weak symbol for pthread_once to avoid additional linking
34 * against libpthread when not used. */
35#pragma weak pthread_once
36
37#define verbose_fprintf \
38 if (verbosity == 1) fprintf
39
40/* defaults for number of components and events */
41#define PAPIHL_NUM_OF_COMPONENTS 10
42#define PAPIHL_NUM_OF_EVENTS_PER_COMPONENT 10
43
44#define PAPIHL_ACTIVE 1
45#define PAPIHL_DEACTIVATED 0
46
47/* number of nested regions */
48#define PAPIHL_MAX_STACK_SIZE 10
49
50/* global components data begin *****************************************/
51typedef struct components
52{
59 int EventSet; //only for testing at initialization phase
61
67
68/* global components data end *******************************************/
69
70
71/* thread local components data begin ***********************************/
72typedef struct local_components
73{
78
87
88
89/* thread local components data end *************************************/
90
91
92/* global event storage data begin **************************************/
93typedef struct reads
94{
95 struct reads *next;
96 struct reads *prev;
98} reads_t;
99
100typedef struct
101{
105} value_t;
106
107typedef struct regions
108{
109 unsigned int region_id;
111 char *region;
112 struct regions *next;
113 struct regions *prev;
115} regions_t;
116
117typedef struct
118{
119 unsigned long key;
121} threads_t;
122
123int compar(const void *l, const void *r)
124{
125 const threads_t *lm = l;
126 const threads_t *lr = r;
127 return lm->key - lr->key;
128}
129
130typedef struct
131{
132 void *root;
135
138
139/* global event storage data end ****************************************/
140
141
142/* global auxiliary variables begin *************************************/
144
147
148bool hl_initiated = false;
149bool hl_finalized = false;
150bool events_determined = false;
151bool output_generated = false;
152static char *absolute_output_file_path = NULL;
153static int output_counter = 0;
154short verbosity = 0;
156static int region_begin_cnt = 0;
157static int region_end_cnt = 0;
158unsigned long master_thread_id = -1;
160/* global auxiliary variables end ***************************************/
161
162static void _internal_hl_library_init(void);
163static void _internal_hl_onetime_library_init(void);
164
165/* functions for creating eventsets for different components */
166static int _internal_hl_checkCounter ( char* counter );
167static int _internal_hl_determine_rank();
168static char *_internal_hl_remove_spaces( char *str, int mode );
171static int _internal_hl_new_component(int component_id, components_t *component);
172static int _internal_hl_add_event_to_component(char *event_name, int event,
173 short event_type, components_t *component);
175static int _internal_hl_read_events(const char* events);
177static int _internal_hl_start_counters();
178
179/* functions for storing events */
180static int _internal_hl_region_id_pop();
181static int _internal_hl_region_id_push();
183
184static inline reads_t* _internal_hl_insert_read_node( reads_t** head_node );
185static inline int _internal_hl_add_values_to_region( regions_t *node, enum region_type reg_typ );
186static inline regions_t* _internal_hl_insert_region_node( regions_t** head_node, const char *region );
187static inline regions_t* _internal_hl_find_region_node( regions_t* head_node, const char *region );
188static inline threads_t* _internal_hl_insert_thread_node( unsigned long tid );
189static inline threads_t* _internal_hl_find_thread_node( unsigned long tid );
190static int _internal_hl_store_counters( unsigned long tid, const char *region,
191 enum region_type reg_typ );
192static int _internal_hl_read_counters();
193static int _internal_hl_read_and_store_counters( const char *region, enum region_type reg_typ );
195
196/* functions for output generation */
197static int _internal_hl_mkdir(const char *dir);
199static void _internal_hl_json_line_break_and_indent(FILE* f, bool b, int width);
200static void _internal_hl_json_definitions(FILE* f, bool beautifier);
201static void _internal_hl_json_region_events(FILE* f, bool beautifier, regions_t *regions);
202static void _internal_hl_json_regions(FILE* f, bool beautifier, threads_t* thread_node);
203static void _internal_hl_json_threads(FILE* f, bool beautifier, unsigned long* tids, int threads_num);
204static int _internal_hl_cmpfunc(const void * a, const void * b);
205static int _internal_get_sorted_thread_list(unsigned long** tids, int* threads_num);
206static void _internal_hl_write_json_file(FILE* f, unsigned long* tids, int threads_num);
207static void _internal_hl_read_json_file(const char* path);
208static void _internal_hl_write_output();
209
210/* functions for cleaning up heap memory */
213static void _internal_hl_clean_up_all(bool deactivate);
215
216/* internal advanced functions */
220int _internal_PAPI_hl_set_events(const char* events);
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}
283
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}
301
302static int
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}
331
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}
348
349static char *_internal_hl_remove_spaces( char *str, int mode )
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}
365
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}
408
409static int _internal_hl_read_user_events(const char *user_events)
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}
469
470static int _internal_hl_new_component(int component_id, components_t *component)
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}
522
524 short event_type, components_t *component)
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}
568
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}
679
680static int _internal_hl_read_events(const char* events)
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}
731
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}
785
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}
806
808 if ( _local_region_id_top == -1 ) {
809 return PAPI_ENOEVNT;
810 } else {
812 }
813 return PAPI_OK;
814}
815
818 return PAPI_ENOMEM;
819 } else {
822 }
823 return PAPI_OK;
824}
825
827 if ( _local_region_id_top == -1 ) {
828 return -1;
829 } else {
831 }
832}
833
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}
855
856static inline int _internal_hl_add_values_to_region( regions_t *node, enum region_type reg_typ )
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}
911
912
913static inline regions_t* _internal_hl_insert_region_node(regions_t** head_node, const char *region )
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}
953
954
955static inline regions_t* _internal_hl_find_region_node(regions_t* head_node, const char *region )
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}
967
968static inline threads_t* _internal_hl_insert_thread_node(unsigned long tid)
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}
978
979static inline threads_t* _internal_hl_find_thread_node(unsigned long tid)
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}
990
991
992static int _internal_hl_store_counters( unsigned long tid, const char *region,
993 enum region_type reg_typ )
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}
1052
1053
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}
1074
1075static int _internal_hl_read_and_store_counters( const char *region, enum region_type reg_typ )
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}
1094
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}
1104
1105
1106static int _internal_hl_mkdir(const char *dir)
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}
1148
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}
1213
1214static void _internal_hl_json_line_break_and_indent( FILE* f, bool b, int width )
1215{
1216 int i;
1217 if ( b ) {
1218 fprintf(f, "\n");
1219 for ( i = 0; i < width; ++i )
1220 fprintf(f, " ");
1221 }
1222}
1223
1224static void _internal_hl_json_definitions(FILE* f, bool beautifier)
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}
1259
1260static void _internal_hl_json_region_events(FILE* f, bool beautifier, regions_t *regions)
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}
1336
1337static void _internal_hl_json_regions(FILE* f, bool beautifier, threads_t* thread_node)
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}
1370
1371static void _internal_hl_json_threads(FILE* f, bool beautifier, unsigned long* tids, int threads_num)
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}
1411
1412static int _internal_hl_cmpfunc(const void * a, const void * b) {
1413 return ( *(int*)a - *(int*)b );
1414}
1415
1416static int _internal_get_sorted_thread_list(unsigned long** tids, int* threads_num)
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}
1435
1436static void _internal_hl_write_json_file(FILE* f, unsigned long* tids, int threads_num)
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}
1473
1474static void _internal_hl_read_json_file(const char* path)
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}
1488
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}
1607
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}
1636
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}
1687
1688static void _internal_hl_clean_up_all(bool deactivate)
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}
1740
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}
1756
1757int
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}
1772
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}
1785
1787{
1788 if ( state == PAPIHL_ACTIVE && hl_initiated == true ) {
1790 return ( PAPI_OK );
1791 }
1792 return ( PAPI_EMISC );
1793}
1794
1795int
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}
1834
1835void
1837{
1838 if ( state == PAPIHL_ACTIVE &&
1839 hl_initiated == true &&
1840 output_generated == false ) {
1842 }
1843}
1844
1899int
1900PAPI_hl_region_begin( const char* region )
1901{
1902 int retval;
1903 /* if a rate event set is running stop it */
1904 if ( _papi_rate_events_running == 1 ) {
1905 if ( ( retval = PAPI_rate_stop() ) != PAPI_OK )
1906 return ( retval );
1907 }
1908
1909 if ( state == PAPIHL_DEACTIVATED ) {
1910 /* check if we have to clean up local stuff */
1911 if ( _local_state == PAPIHL_ACTIVE )
1913 return ( PAPI_EMISC );
1914 }
1915
1916 if ( hl_finalized == true )
1917 return ( PAPI_ENOTRUN );
1918
1919 if ( hl_initiated == false ) {
1920 if ( ( retval = _internal_PAPI_hl_init() ) != PAPI_OK )
1921 return ( retval );
1922 }
1923
1924 if ( events_determined == false ) {
1925 if ( ( retval = _internal_PAPI_hl_set_events(NULL) ) != PAPI_OK )
1926 return ( retval );
1927 }
1928
1929 if ( _local_components == NULL ) {
1931 HLDBG("Could not create local events sets for thread %lu.\n", PAPI_thread_id());
1933 return ( retval );
1934 }
1935 }
1936
1937 if ( _papi_hl_events_running == 0 ) {
1938 if ( ( retval = _internal_hl_start_counters() ) != PAPI_OK ) {
1939 HLDBG("Could not start counters for thread %lu.\n", PAPI_thread_id());
1941 return ( retval );
1942 }
1943 }
1944
1945 /* read and store all events */
1946 HLDBG("Thread ID:%lu, Region:%s\n", PAPI_thread_id(), region);
1948 return ( retval );
1949
1950 if ( ( retval = _internal_hl_region_id_push() ) != PAPI_OK ) {
1951 verbose_fprintf(stdout, "PAPI-HL Warning: Number of nested regions exceeded for thread %lu.\n", PAPI_thread_id());
1953 return ( retval );
1954 }
1956 return ( PAPI_OK );
1957}
1958
2012int
2013PAPI_hl_read(const char* region)
2014{
2015 int retval;
2016
2017 if ( state == PAPIHL_DEACTIVATED ) {
2018 /* check if we have to clean up local stuff */
2019 if ( _local_state == PAPIHL_ACTIVE )
2021 return ( PAPI_EMISC );
2022 }
2023
2024 if ( _local_region_begin_cnt == 0 ) {
2025 verbose_fprintf(stdout, "PAPI-HL Warning: Cannot find matching region for PAPI_hl_read(\"%s\") for thread %lu.\n", region, PAPI_thread_id());
2026 return ( PAPI_EMISC );
2027 }
2028
2029 if ( _local_components == NULL )
2030 return ( PAPI_ENOTRUN );
2031
2032 /* read and store all events */
2033 HLDBG("Thread ID:%lu, Region:%s\n", PAPI_thread_id(), region);
2035 return ( retval );
2036
2037 return ( PAPI_OK );
2038}
2039
2130int
2131PAPI_hl_region_end( const char* region )
2132{
2133 int retval;
2134
2135 if ( state == PAPIHL_DEACTIVATED ) {
2136 /* check if we have to clean up local stuff */
2137 if ( _local_state == PAPIHL_ACTIVE )
2139 return ( PAPI_EMISC );
2140 }
2141
2142 if ( _local_region_begin_cnt == 0 ) {
2143 verbose_fprintf(stdout, "PAPI-HL Warning: Cannot find matching region for PAPI_hl_region_end(\"%s\") for thread %lu.\n", region, PAPI_thread_id());
2144 return ( PAPI_EMISC );
2145 }
2146
2147 if ( _local_components == NULL )
2148 return ( PAPI_ENOTRUN );
2149
2150 /* read and store all events */
2151 HLDBG("Thread ID:%lu, Region:%s\n", PAPI_thread_id(), region);
2153 return ( retval );
2154
2157 return ( PAPI_OK );
2158}
2159
2183int
2185{
2186 int retval, i;
2187
2188 if ( _papi_hl_events_running == 1 ) {
2189 if ( _local_components != NULL ) {
2190 for ( i = 0; i < num_of_components; i++ ) {
2192 return ( retval );
2193 }
2194 }
2196 return ( PAPI_OK );
2197 }
2198 return ( PAPI_ENOEVNT );
2199}
2200
static const char * event_names[2]
Definition: Gamum.c:27
double tmp
int i
int open(const char *pathname, int flags, mode_t mode)
Definition: appio.c:188
int close(int fd)
Definition: appio.c:179
int errno
add PAPI preset or native hardware event to an event set
Assign a component index to an existing but empty EventSet.
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.
get information about a specific software component
get information about the system hardware
Get the multiplexing status of specified event set.
Get real time counter value in nanoseconds.
Read performance events inside of a region and store the difference to the corresponding beginning of...
Read performance events at the beginning of a region.
Read performance events at the end of a region and store the difference to the corresponding beginnin...
initialize the PAPI library.
List the registered thread ids.
Initialize multiplex support in the PAPI library.
Stop a running event set of a rate function.
Read hardware counters with a timestamp.
Read hardware counters from an event set.
Convert a standard event set to a multiplexed event set.
Finish using PAPI and free all related resources.
Start counting hardware events in an event set.
Stop counting hardware events in an event set.
Get the thread identifier of the current thread.
Initialize thread support in the PAPI library.
double f(double a)
Definition: cpi.c:23
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:29
volatile int buf[CACHE_FLUSH_BUFFER_SIZE_INTS]
Definition: do_loops.c:12
#define PAPI_VER_CURRENT
Definition: f90papi.h:54
#define PAPI_VERSION
Definition: f90papi.h:193
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_NULL
Definition: f90papi.h:78
#define PAPI_ENOEVNT
Definition: f90papi.h:139
#define PAPI_EINVAL
Definition: f90papi.h:115
#define PAPI_ENOSUPP
Definition: f90papi.h:244
#define PAPI_RUNNING
Definition: f90papi.h:165
#define PAPI_EMISC
Definition: f90papi.h:122
#define PAPI_ESYS
Definition: f90papi.h:136
#define PAPI_EISRUN
Definition: f90papi.h:277
#define PAPI_ENOMEM
Definition: f90papi.h:16
#define PAPI_ENOINIT
Definition: f90papi.h:160
#define PAPI_ENOTRUN
Definition: f90papi.h:146
int PAPI_hl_stop()
Definition: papi_hl.c:2184
char events[MAX_EVENTS][BUFSIZ]
static int EventSet
Definition: init_fini.c:8
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
static double a[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:38
static double b[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:39
static double c[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:40
static int num_events
int multi_thread(int argc, char *argv[])
Return codes and api definitions.
#define PAPI_VERSION_REVISION(x)
Definition: papi.h:221
#define PAPI_VERSION_MAJOR(x)
Definition: papi.h:219
#define long_long
Definition: papi.h:559
#define PAPI_COMPONENT_INDEX(a)
Definition: papi.h:1246
#define PAPI_VERSION_INCREMENT(x)
Definition: papi.h:222
#define PAPI_VERSION_MINOR(x)
Definition: papi.h:220
#define HLDBG(format, args...)
Definition: papi_debug.h:73
int rename(const char *__old, const char *__new) __attribute__((__nothrow__
int pthread_once_t
FILE * stdout
int fclose(FILE *__stream)
#define PAPIHL_ACTIVE
Definition: papi_hl.c:44
static void _internal_hl_clean_up_global_data()
Definition: papi_hl.c:1637
static int _internal_hl_mkdir(const char *dir)
Definition: papi_hl.c:1106
static int _internal_hl_checkCounter(char *counter)
Definition: papi_hl.c:303
static int _internal_hl_read_events(const char *events)
Definition: papi_hl.c:680
int _internal_PAPI_hl_set_events(const char *events)
Definition: papi_hl.c:1796
static int _internal_hl_region_id_push()
Definition: papi_hl.c:816
THREAD_LOCAL_STORAGE_KEYWORD unsigned int _local_region_id_stack[PAPIHL_MAX_STACK_SIZE]
Definition: papi_hl.c:85
static void _internal_hl_json_definitions(FILE *f, bool beautifier)
Definition: papi_hl.c:1224
static int _internal_hl_read_user_events()
static int _internal_hl_add_values_to_region(regions_t *node, enum region_type reg_typ)
Definition: papi_hl.c:856
char ** requested_event_names
Definition: papi_hl.c:145
bool hl_initiated
Definition: papi_hl.c:148
bool hl_finalized
Definition: papi_hl.c:149
#define PAPIHL_DEACTIVATED
Definition: papi_hl.c:45
static int _internal_hl_store_counters(unsigned long tid, const char *region, enum region_type reg_typ)
Definition: papi_hl.c:992
static void _internal_hl_json_region_events(FILE *f, bool beautifier, regions_t *regions)
Definition: papi_hl.c:1260
static int output_counter
Definition: papi_hl.c:153
static int _internal_get_sorted_thread_list(unsigned long **tids, int *threads_num)
Definition: papi_hl.c:1416
#define PAPIHL_MAX_STACK_SIZE
Definition: papi_hl.c:48
static int _internal_hl_create_global_binary_tree()
Definition: papi_hl.c:1095
static int _internal_hl_determine_default_events()
Definition: papi_hl.c:366
static void _internal_hl_json_regions(FILE *f, bool beautifier, threads_t *thread_node)
Definition: papi_hl.c:1337
static regions_t * _internal_hl_insert_region_node(regions_t **head_node, const char *region)
Definition: papi_hl.c:913
THREAD_LOCAL_STORAGE_KEYWORD unsigned int _local_region_begin_cnt
Definition: papi_hl.c:82
#define PAPIHL_NUM_OF_COMPONENTS
Definition: papi_hl.c:41
THREAD_LOCAL_STORAGE_KEYWORD unsigned int _local_region_end_cnt
Definition: papi_hl.c:83
region_type
Definition: papi_hl.c:143
@ REGION_END
Definition: papi_hl.c:143
@ REGION_READ
Definition: papi_hl.c:143
@ REGION_BEGIN
Definition: papi_hl.c:143
static int _internal_hl_create_event_sets()
Definition: papi_hl.c:732
static int _internal_hl_read_counters()
Definition: papi_hl.c:1054
int _internal_PAPI_hl_init()
Definition: papi_hl.c:1758
static int region_begin_cnt
Definition: papi_hl.c:156
static threads_t * _internal_hl_find_thread_node(unsigned long tid)
Definition: papi_hl.c:979
static void _internal_hl_json_line_break_and_indent(FILE *f, bool b, int width)
Definition: papi_hl.c:1214
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_region_id_stack_peak()
Definition: papi_hl.c:826
int compar(const void *l, const void *r)
Definition: papi_hl.c:123
static int _internal_hl_read_and_store_counters(const char *region, enum region_type reg_typ)
Definition: papi_hl.c:1075
static int _internal_hl_new_component(int component_id, components_t *component)
Definition: papi_hl.c:470
THREAD_LOCAL_STORAGE_KEYWORD int _local_region_id_top
Definition: papi_hl.c:86
components_t * components
Definition: papi_hl.c:62
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_output_path()
Definition: papi_hl.c:1149
#define PAPIHL_NUM_OF_EVENTS_PER_COMPONENT
Definition: papi_hl.c:42
static char * _internal_hl_remove_spaces(char *str, int mode)
Definition: papi_hl.c:349
static regions_t * _internal_hl_find_region_node(regions_t *head_node, const char *region)
Definition: papi_hl.c:955
int _internal_PAPI_hl_finalize()
Definition: papi_hl.c:1786
static void _internal_hl_write_output()
Definition: papi_hl.c:1489
binary_tree_t * binary_tree
Definition: papi_hl.c:137
static int _internal_hl_create_components()
Definition: papi_hl.c:569
static int _internal_hl_start_counters()
Definition: papi_hl.c:786
bool state
Definition: papi_hl.c:155
static int _internal_hl_check_for_clean_thread_states()
Definition: papi_hl.c:1741
unsigned long master_thread_id
Definition: papi_hl.c:158
bool events_determined
Definition: papi_hl.c:150
static void _internal_hl_library_init(void)
Definition: papi_hl.c:224
int num_of_requested_events
Definition: papi_hl.c:146
int total_num_events
Definition: papi_hl.c:65
THREAD_LOCAL_STORAGE_KEYWORD local_components_t * _local_components
Definition: papi_hl.c:79
static void _internal_hl_clean_up_all(bool deactivate)
Definition: papi_hl.c:1688
static int _internal_hl_cmpfunc(const void *a, const void *b)
Definition: papi_hl.c:1412
static int _internal_hl_determine_rank()
Definition: papi_hl.c:332
static void _internal_hl_clean_up_local_data()
Definition: papi_hl.c:1608
#define verbose_fprintf
Definition: papi_hl.c:37
static void _internal_hl_json_threads(FILE *f, bool beautifier, unsigned long *tids, int threads_num)
Definition: papi_hl.c:1371
static threads_t * _internal_hl_insert_thread_node(unsigned long tid)
Definition: papi_hl.c:968
THREAD_LOCAL_STORAGE_KEYWORD volatile bool _local_state
Definition: papi_hl.c:81
static reads_t * _internal_hl_insert_read_node(reads_t **head_node)
Definition: papi_hl.c:834
static char * absolute_output_file_path
Definition: papi_hl.c:152
int max_num_of_components
Definition: papi_hl.c:64
int num_of_components
Definition: papi_hl.c:63
static int region_end_cnt
Definition: papi_hl.c:157
void _internal_PAPI_hl_print_output()
Definition: papi_hl.c:1836
bool output_generated
Definition: papi_hl.c:151
static int _internal_hl_region_id_pop()
Definition: papi_hl.c:807
static void _internal_hl_onetime_library_init(void)
Definition: papi_hl.c:284
int num_of_cleaned_threads
Definition: papi_hl.c:66
short verbosity
Definition: papi_hl.c:154
THREAD_LOCAL_STORAGE_KEYWORD long_long _local_cycles
Definition: papi_hl.c:80
static void _internal_hl_read_json_file(const char *path)
Definition: papi_hl.c:1474
int _internal_PAPI_hl_cleanup_thread()
Definition: papi_hl.c:1773
THREAD_LOCAL_STORAGE_KEYWORD int _papi_hl_events_running
Definition: papi_internal.c:63
THREAD_LOCAL_STORAGE_KEYWORD int _papi_rate_events_running
Definition: papi_internal.c:62
#define HIGHLEVEL_LOCK
Definition: papi_internal.h:88
static FILE * fp
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:56
int
Definition: sde_internal.h:89
EventSetInfo_t ** dataSlotArray
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:627
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
threads_t * find_p
Definition: papi_hl.c:133
void * root
Definition: papi_hl.c:132
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
long_long * values
Definition: papi_hl.c:76
DynamicArray_t global_eventset_map
long_long value
Definition: papi_hl.c:97
struct reads * prev
Definition: papi_hl.c:96
struct reads * next
Definition: papi_hl.c:95
struct regions * prev
Definition: papi_hl.c:113
value_t values[]
Definition: papi_hl.c:114
struct regions * next
Definition: papi_hl.c:112
unsigned int region_id
Definition: papi_hl.c:109
char * region
Definition: papi_hl.c:111
int parent_region_id
Definition: papi_hl.c:110
regions_t * value
Definition: papi_hl.c:120
unsigned long key
Definition: papi_hl.c:119
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
unsigned long _papi_gettid(void)
Definition: threads.c:613
unsigned long _papi_getpid(void)
Definition: threads.c:634
inline_static int _papi_hwi_lock(int lck)
Definition: threads.h:69
#define THREAD_LOCAL_STORAGE_KEYWORD
Definition: threads.h:16
inline_static int _papi_hwi_unlock(int lck)
Definition: threads.h:83
int retval
Definition: zero_fork.c:53