Created
July 19, 2013 16:47
-
-
Save pyrovski/6040623 to your computer and use it in GitHub Desktop.
Testcase for PAPI deadlock in _papi_hwi_lookup_or_create_cpu()
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// compile with -lpapi -fopenmp | |
#define _GNU_SOURCE | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <papi.h> | |
#include <assert.h> | |
#include <omp.h> | |
#include <sched.h> | |
#define errorExit(status, expected) if(status != expected){fprintf(stderr, "error: %s:%d:%s: %d/%d\n", __FILE__, __LINE__, __FUNCTION__, status, expected); exit(1);} | |
#define PAPI_errorExit(status, expected) if(status != expected){fprintf(stderr, "error: %s:%d:%s: %s\n", __FILE__, __LINE__, __FUNCTION__, PAPI_strerror(status)); exit(1);} | |
int eventSet = PAPI_NULL; | |
void add_events(){ | |
char *eventNames = getenv((const char*)"PAPI_EVENTS"); | |
char *eventNamesCopy = (char*)calloc(1, strlen(eventNames)+1); | |
strcpy(eventNamesCopy, eventNames); | |
printf("eventNames: %s\n", eventNames); | |
char *result = 0; | |
char delim[] = ","; | |
int papi_error; | |
result = strtok(eventNamesCopy, delim); | |
while(result){ | |
int event; | |
papi_error = PAPI_event_name_to_code(result, &event); | |
PAPI_errorExit(papi_error, PAPI_OK); | |
papi_error = PAPI_add_event(eventSet, event); | |
PAPI_errorExit(papi_error, PAPI_OK); | |
result = strtok(0, delim); | |
} | |
int numEvents = PAPI_num_events(eventSet); | |
if(numEvents <= 0){ | |
fprintf(stderr, "error: expected one or more events\n"); | |
exit(1); | |
} | |
printf("added %d events\n", numEvents); | |
papi_error = PAPI_reset(eventSet); | |
PAPI_errorExit(papi_error, PAPI_OK); | |
} | |
void func(){ | |
uint64_t iterations = 2e9; | |
volatile uint64_t i; | |
printf("iterations: %lu\n", iterations); | |
for(i = 0; i < iterations; i++); | |
} | |
void init_counters(){ | |
int papi_error; | |
papi_error = PAPI_create_eventset(&eventSet); | |
PAPI_errorExit(papi_error, PAPI_OK); | |
papi_error = PAPI_assign_eventset_component(eventSet, 0); | |
PAPI_errorExit(papi_error, PAPI_OK); | |
//! apparently need root for this | |
PAPI_cpu_option_t cpu_opt; | |
cpu_opt.eventset = eventSet; | |
cpu_opt.cpu_num=0; | |
//! @todo PAPI deadlock here | |
papi_error = PAPI_set_opt(PAPI_CPU_ATTACH, (PAPI_option_t*)&cpu_opt); | |
PAPI_errorExit(papi_error, PAPI_OK); | |
/*! sched_setaffinity() works on perf_event_system_wide.c only | |
because it also uses CPU attachment through PAPI | |
*/ | |
#if 0 | |
cpu_set_t mask; | |
CPU_ZERO(&mask); | |
CPU_SET(0, &mask); | |
if(sched_setaffinity(0, sizeof(mask), &mask) < 0){ | |
fprintf(stderr, "set affinity failed\n"); | |
exit(1); | |
} | |
#endif | |
add_events(eventSet); | |
} | |
void start_counters(){ | |
int papi_error; | |
papi_error = PAPI_start(eventSet); | |
PAPI_errorExit(papi_error, PAPI_OK); | |
} | |
void stop_counters(){ | |
int numEvents = PAPI_num_events(eventSet); | |
if(numEvents <= 0){ | |
fprintf(stderr, "error: expected one or more events\n"); | |
exit(1); | |
} | |
long_long *values = (long_long*)calloc(numEvents, sizeof(long_long)); | |
int papi_error; | |
papi_error = PAPI_stop(eventSet, values); | |
PAPI_errorExit(papi_error, PAPI_OK); | |
int *events = (int*)calloc(numEvents, sizeof(int)); | |
papi_error = PAPI_list_events(eventSet, events, &numEvents); | |
PAPI_errorExit(papi_error, PAPI_OK); | |
int i; | |
char name[1024]; | |
for(i = 0; i < numEvents; i++){ | |
papi_error = PAPI_event_code_to_name(events[i], name); | |
PAPI_errorExit(papi_error, PAPI_OK); | |
printf("%s\t", name); | |
} | |
printf("\n"); | |
for(i = 0; i < numEvents; i++) | |
printf("%lld\t", values[i]); | |
printf("\n"); | |
} | |
int main(int argc, char ** argv){ | |
int papi_error = PAPI_library_init(PAPI_VER_CURRENT); | |
PAPI_errorExit(papi_error, PAPI_VER_CURRENT); | |
papi_error = PAPI_thread_init(&omp_get_thread_num); | |
papi_error = PAPI_set_granularity(PAPI_GRN_SYS); | |
PAPI_errorExit(papi_error, PAPI_OK); | |
papi_error = PAPI_set_domain(PAPI_DOM_USER); | |
PAPI_errorExit(papi_error, PAPI_OK); | |
init_counters(); | |
start_counters(); | |
func(); | |
stop_counters(); | |
PAPI_shutdown(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment