Skip to content

Instantly share code, notes, and snippets.

@pyrovski
Created July 19, 2013 16:47
Show Gist options
  • Save pyrovski/6040623 to your computer and use it in GitHub Desktop.
Save pyrovski/6040623 to your computer and use it in GitHub Desktop.
Testcase for PAPI deadlock in _papi_hwi_lookup_or_create_cpu()
// 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