/* * PAPI PMDA * * Copyright (c) 2014 Red Hat. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include "domain.h" #include #include #if defined(HAVE_GRP_H) #include #endif #include enum { CLUSTER_PAPI = 0, // hardware event counters CLUSTER_CONTROL, // control variables CLUSTER_AVAILABLE, // available hardware }; typedef struct { unsigned int papi_event_code; //the PAPI_ eventcode char papi_string_code[8]; int position; int pmns_position; } papi_m_user_tuple; static papi_m_user_tuple *papi_info; static char *enable_string; static char *disable_string; static char isDSO = 1; /* == 0 if I am a daemon */ static int EventSet = PAPI_NULL; static long_long *values; struct uid_gid_tuple { char uid_p; char gid_p; /* uid/gid received flags. */ int uid; int gid; /* uid/gid received from PCP_ATTR_* */ }; static struct uid_gid_tuple *ctxtab; static int ctxtab_size; static int number_of_counters; static unsigned int number_of_active_counters; static unsigned int size_of_active_counters; static unsigned int number_of_events; static void set_pmns_position(unsigned int i) { switch (papi_info[i].papi_event_code) { case PAPI_TOT_INS: papi_info[i].pmns_position = 0; break; case PAPI_TOT_CYC: papi_info[i].pmns_position = 1; break; case PAPI_L1_DCM: papi_info[i].pmns_position = 2; break; case PAPI_L1_ICM: papi_info[i].pmns_position = 3; break; case PAPI_L2_DCM: papi_info[i].pmns_position = 4; break; case PAPI_L2_ICM: papi_info[i].pmns_position = 5; break; case PAPI_L3_DCM: papi_info[i].pmns_position = 6; break; case PAPI_L3_ICM: papi_info[i].pmns_position = 7; break; case PAPI_L1_TCM: papi_info[i].pmns_position = 8; break; case PAPI_L2_TCM: papi_info[i].pmns_position = 9; break; case PAPI_L3_TCM: papi_info[i].pmns_position = 10; break; case PAPI_TLB_DM: papi_info[i].pmns_position = 11; break; case PAPI_TLB_IM: papi_info[i].pmns_position = 12; break; case PAPI_TLB_TL: papi_info[i].pmns_position = 13; break; case PAPI_L1_LDM: papi_info[i].pmns_position = 14; break; case PAPI_L1_STM: papi_info[i].pmns_position = 15; break; case PAPI_L2_LDM: papi_info[i].pmns_position = 16; break; case PAPI_L2_STM: papi_info[i].pmns_position = 17; break; case PAPI_CA_SNP: papi_info[i].pmns_position = 18; break; case PAPI_CA_SHR: papi_info[i].pmns_position = 19; break; case PAPI_CA_CLN: papi_info[i].pmns_position = 20; break; case PAPI_CA_INV: papi_info[i].pmns_position = 21; break; case PAPI_CA_ITV: papi_info[i].pmns_position = 22; break; case PAPI_L3_LDM: papi_info[i].pmns_position = 23; break; case PAPI_L3_STM: papi_info[i].pmns_position = 24; break; case PAPI_BRU_IDL: papi_info[i].pmns_position = 25; break; case PAPI_FXU_IDL: papi_info[i].pmns_position = 26; break; case PAPI_FPU_IDL: papi_info[i].pmns_position = 27; break; case PAPI_LSU_IDL: papi_info[i].pmns_position = 28; break; case PAPI_BTAC_M: papi_info[i].pmns_position = 29; break; case PAPI_PRF_DM: papi_info[i].pmns_position = 30; break; case PAPI_L3_DCH: papi_info[i].pmns_position = 31; break; case PAPI_TLB_SD: papi_info[i].pmns_position = 32; break; case PAPI_CSR_FAL: papi_info[i].pmns_position = 33; break; case PAPI_CSR_SUC: papi_info[i].pmns_position = 34; break; case PAPI_CSR_TOT: papi_info[i].pmns_position = 35; break; case PAPI_MEM_SCY: papi_info[i].pmns_position = 36; break; case PAPI_MEM_RCY: papi_info[i].pmns_position = 37; break; case PAPI_MEM_WCY: papi_info[i].pmns_position = 38; break; case PAPI_STL_ICY: papi_info[i].pmns_position = 39; break; case PAPI_FUL_ICY: papi_info[i].pmns_position = 40; break; case PAPI_STL_CCY: papi_info[i].pmns_position = 41; break; case PAPI_FUL_CCY: papi_info[i].pmns_position = 42; break; case PAPI_HW_INT: papi_info[i].pmns_position = 43; break; case PAPI_BR_UCN: papi_info[i].pmns_position = 44; break; case PAPI_BR_CN: papi_info[i].pmns_position = 45; break; case PAPI_BR_TKN: papi_info[i].pmns_position = 46; break; case PAPI_BR_NTK: papi_info[i].pmns_position = 47; break; case PAPI_BR_MSP: papi_info[i].pmns_position = 48; break; case PAPI_BR_PRC: papi_info[i].pmns_position = 49; break; case PAPI_FMA_INS: papi_info[i].pmns_position = 50; break; case PAPI_TOT_IIS: papi_info[i].pmns_position = 51; break; case PAPI_INT_INS: papi_info[i].pmns_position = 52; break; case PAPI_FP_INS: papi_info[i].pmns_position = 53; break; case PAPI_LD_INS: papi_info[i].pmns_position = 54; break; case PAPI_SR_INS: papi_info[i].pmns_position = 55; break; case PAPI_BR_INS: papi_info[i].pmns_position = 56; break; case PAPI_VEC_INS: papi_info[i].pmns_position = 57; break; case PAPI_RES_STL: papi_info[i].pmns_position = 58; break; case PAPI_FP_STAL: papi_info[i].pmns_position = 59; break; case PAPI_LST_INS: papi_info[i].pmns_position = 60; break; case PAPI_SYC_INS: papi_info[i].pmns_position = 61; break; case PAPI_L1_DCH: papi_info[i].pmns_position = 62; break; case PAPI_L2_DCH: papi_info[i].pmns_position = 63; break; case PAPI_L1_DCA: papi_info[i].pmns_position = 64; break; case PAPI_L2_DCA: papi_info[i].pmns_position = 65; break; case PAPI_L3_DCA: papi_info[i].pmns_position = 66; break; case PAPI_L1_DCR: papi_info[i].pmns_position = 67; break; case PAPI_L2_DCR: papi_info[i].pmns_position = 68; break; case PAPI_L3_DCR: papi_info[i].pmns_position = 69; break; case PAPI_L1_DCW: papi_info[i].pmns_position = 70; break; case PAPI_L2_DCW: papi_info[i].pmns_position = 71; break; case PAPI_L3_DCW: papi_info[i].pmns_position = 72; break; case PAPI_L1_ICH: papi_info[i].pmns_position = 73; break; case PAPI_L2_ICH: papi_info[i].pmns_position = 74; break; case PAPI_L3_ICH: papi_info[i].pmns_position = 75; break; case PAPI_L1_ICA: papi_info[i].pmns_position = 76; break; case PAPI_L2_ICA: papi_info[i].pmns_position = 77; break; case PAPI_L3_ICA: papi_info[i].pmns_position = 78; break; case PAPI_L1_ICR: papi_info[i].pmns_position = 79; break; case PAPI_L2_ICR: papi_info[i].pmns_position = 80; break; case PAPI_L3_ICR: papi_info[i].pmns_position = 81; break; case PAPI_L1_ICW: papi_info[i].pmns_position = 82; break; case PAPI_L2_ICW: papi_info[i].pmns_position = 83; break; case PAPI_L3_ICW: papi_info[i].pmns_position = 84; break; case PAPI_L1_TCH: papi_info[i].pmns_position = 85; break; case PAPI_L2_TCH: papi_info[i].pmns_position = 86; break; case PAPI_L3_TCH: papi_info[i].pmns_position = 87; break; case PAPI_L1_TCA: papi_info[i].pmns_position = 88; break; case PAPI_L2_TCA: papi_info[i].pmns_position = 89; break; case PAPI_L3_TCA: papi_info[i].pmns_position = 90; break; case PAPI_L1_TCR: papi_info[i].pmns_position = 91; break; case PAPI_L2_TCR: papi_info[i].pmns_position = 92; break; case PAPI_L3_TCR: papi_info[i].pmns_position = 93; break; case PAPI_L1_TCW: papi_info[i].pmns_position = 94; break; case PAPI_L2_TCW: papi_info[i].pmns_position = 95; break; case PAPI_L3_TCW: papi_info[i].pmns_position = 96; break; case PAPI_FML_INS: papi_info[i].pmns_position = 97; break; case PAPI_FAD_INS: papi_info[i].pmns_position = 98; break; case PAPI_FDV_INS: papi_info[i].pmns_position = 99; break; case PAPI_FSQ_INS: papi_info[i].pmns_position = 100; break; case PAPI_FNV_INS: papi_info[i].pmns_position = 101; break; case PAPI_FP_OPS: papi_info[i].pmns_position = 102; break; case PAPI_SP_OPS: papi_info[i].pmns_position = 103; break; case PAPI_DP_OPS: papi_info[i].pmns_position = 104; break; case PAPI_VEC_SP: papi_info[i].pmns_position = 105; break; case PAPI_VEC_DP: papi_info[i].pmns_position = 106; break; #ifdef PAPI_REF_CYC case PAPI_REF_CYC: papi_info[i].pmns_position = 107; break; #endif default: papi_info[i].pmns_position = -1; break; } } static int permission_check(int context) { if ((ctxtab[context].uid_p && ctxtab[context].uid == 0) || (ctxtab[context].gid_p && ctxtab[context].gid == 0)) return 1; return 0; } static void expand_papi_info(int size) { if (number_of_events <= size) { size_t new_size = (size + 1) * sizeof(papi_m_user_tuple); papi_info = realloc(papi_info, new_size); if (papi_info == NULL) __pmNoMem("papi_info tuple", new_size, PM_FATAL_ERR); while (number_of_events <= size) memset(&papi_info[number_of_events++], 0, sizeof(papi_m_user_tuple)); } } static void expand_values(int size) { if (size_of_active_counters <= size) { size_t new_size = (size + 1) * sizeof(long_long); values = realloc(values, new_size); if (values == NULL) __pmNoMem("values", new_size, PM_FATAL_ERR); while (size_of_active_counters <= size) { memset(&values[size_of_active_counters++], 0, sizeof(long_long)); if (pmDebug & DBG_TRACE_APPL0) { __pmNotifyErr(LOG_DEBUG, "memsetting to zero, %d counters\n", size_of_active_counters); } } } } static void enlarge_ctxtab(int context) { /* Grow the context table if necessary. */ if (ctxtab_size /* cardinal */ <= context /* ordinal */) { size_t need = (context + 1) * sizeof(struct uid_gid_tuple); ctxtab = realloc(ctxtab, need); if (ctxtab == NULL) __pmNoMem("papi ctx table", need, PM_FATAL_ERR); /* Blank out new entries. */ while (ctxtab_size <= context) memset(&ctxtab[ctxtab_size++], 0, sizeof(struct uid_gid_tuple)); } } static int check_papi_state(int state) { int retval; retval = PAPI_state(EventSet, &state); if (retval != PAPI_OK) return PM_ERR_NODATA; return state; } static char * papi_string_status(void) { int state, retval; retval = PAPI_state(EventSet, &state); if (retval != PAPI_OK) return "PAPI_state error."; switch (state) { case PAPI_STOPPED: return "Papi is stopped."; case PAPI_RUNNING: return "Papi is running."; case PAPI_PAUSED: return "Papi is paused"; case PAPI_NOT_INIT: return "Papi eventset is defined but not initialized."; case PAPI_OVERFLOWING: return "Papi eventset has overflowing enabled"; case PAPI_PROFILING: return "Papi eventset has profiling enabled"; case PAPI_MULTIPLEXING: return "Papi eventset has multiplexing enabled"; case PAPI_ATTACHED: return "Papi is attached to another process/thread"; case PAPI_CPU_ATTACHED: return "Papi is attached to a specific CPU."; default: return "PAPI_state error."; } } /* * A list of all the papi metrics we support - */ static pmdaMetric metrictab[] = { { NULL, { PMDA_PMID(CLUSTER_PAPI,0), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.TOT_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,1), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.TOT_CYC */ { NULL, { PMDA_PMID(CLUSTER_PAPI,2), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_DCM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,3), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_ICM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,4), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_DCM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,5), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_ICM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,6), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_DCM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,7), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_ICM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,8), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_TCM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,9), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_TCM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,10), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_TCM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,11), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.TLB_DM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,12), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.TLB_IM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,13), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.TLB_TL */ { NULL, { PMDA_PMID(CLUSTER_PAPI,14), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_LDM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,15), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_STM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,16), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_LDM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,17), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_STM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,18), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.CA_SNP */ { NULL, { PMDA_PMID(CLUSTER_PAPI,19), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.CA_SHR */ { NULL, { PMDA_PMID(CLUSTER_PAPI,20), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.CA_CLN */ { NULL, { PMDA_PMID(CLUSTER_PAPI,21), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.CA_INV */ { NULL, { PMDA_PMID(CLUSTER_PAPI,22), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.CA_ITV */ { NULL, { PMDA_PMID(CLUSTER_PAPI,23), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_LDM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,24), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_STM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,25), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.BRU_IDL */ { NULL, { PMDA_PMID(CLUSTER_PAPI,26), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FXU_IDL */ { NULL, { PMDA_PMID(CLUSTER_PAPI,27), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FPU_IDL */ { NULL, { PMDA_PMID(CLUSTER_PAPI,28), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.LSU_IDL */ { NULL, { PMDA_PMID(CLUSTER_PAPI,29), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.BTAC_M */ { NULL, { PMDA_PMID(CLUSTER_PAPI,30), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.PRF_DM */ { NULL, { PMDA_PMID(CLUSTER_PAPI,31), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_DCH */ { NULL, { PMDA_PMID(CLUSTER_PAPI,32), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.TLB_SD */ { NULL, { PMDA_PMID(CLUSTER_PAPI,33), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.CSR_FAL */ { NULL, { PMDA_PMID(CLUSTER_PAPI,34), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.CSR_SUC */ { NULL, { PMDA_PMID(CLUSTER_PAPI,35), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.CSR_TOT */ { NULL, { PMDA_PMID(CLUSTER_PAPI,36), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.MEM_SCY */ { NULL, { PMDA_PMID(CLUSTER_PAPI,37), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.MEM_RCY */ { NULL, { PMDA_PMID(CLUSTER_PAPI,38), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.MEM_WCY */ { NULL, { PMDA_PMID(CLUSTER_PAPI,39), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.STL_ICY */ { NULL, { PMDA_PMID(CLUSTER_PAPI,40), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FUL_ICY */ { NULL, { PMDA_PMID(CLUSTER_PAPI,41), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.STL_CCY */ { NULL, { PMDA_PMID(CLUSTER_PAPI,42), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FUL_CCY */ { NULL, { PMDA_PMID(CLUSTER_PAPI,43), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.HW_INT */ { NULL, { PMDA_PMID(CLUSTER_PAPI,44), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.BR_UCN */ { NULL, { PMDA_PMID(CLUSTER_PAPI,45), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.BR_CN */ { NULL, { PMDA_PMID(CLUSTER_PAPI,46), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.BR_TKN */ { NULL, { PMDA_PMID(CLUSTER_PAPI,47), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.BR_NTK */ { NULL, { PMDA_PMID(CLUSTER_PAPI,48), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.BR_MSP */ { NULL, { PMDA_PMID(CLUSTER_PAPI,49), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.BR_PRC */ { NULL, { PMDA_PMID(CLUSTER_PAPI,50), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FMA_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,51), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.TOT_IIS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,52), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.INT_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,53), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FP_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,54), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.LD_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,55), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.SR_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,56), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.BR_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,57), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.VEC_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,58), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.RES_STL */ { NULL, { PMDA_PMID(CLUSTER_PAPI,59), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FP_STAL */ { NULL, { PMDA_PMID(CLUSTER_PAPI,60), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.LST_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,61), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.SYC_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,62), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_DCH */ { NULL, { PMDA_PMID(CLUSTER_PAPI,63), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_DCH */ { NULL, { PMDA_PMID(CLUSTER_PAPI,64), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_DCA */ { NULL, { PMDA_PMID(CLUSTER_PAPI,65), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_DCA */ { NULL, { PMDA_PMID(CLUSTER_PAPI,66), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_DCA */ { NULL, { PMDA_PMID(CLUSTER_PAPI,67), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_DCR */ { NULL, { PMDA_PMID(CLUSTER_PAPI,68), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_DCR */ { NULL, { PMDA_PMID(CLUSTER_PAPI,69), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_DCR */ { NULL, { PMDA_PMID(CLUSTER_PAPI,70), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_DCW */ { NULL, { PMDA_PMID(CLUSTER_PAPI,71), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_DCW */ { NULL, { PMDA_PMID(CLUSTER_PAPI,72), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_DCW */ { NULL, { PMDA_PMID(CLUSTER_PAPI,73), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_ICH */ { NULL, { PMDA_PMID(CLUSTER_PAPI,74), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_ICH */ { NULL, { PMDA_PMID(CLUSTER_PAPI,75), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_ICH */ { NULL, { PMDA_PMID(CLUSTER_PAPI,76), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_ICA */ { NULL, { PMDA_PMID(CLUSTER_PAPI,77), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_ICA */ { NULL, { PMDA_PMID(CLUSTER_PAPI,78), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_ICA */ { NULL, { PMDA_PMID(CLUSTER_PAPI,79), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_ICR */ { NULL, { PMDA_PMID(CLUSTER_PAPI,80), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_ICR */ { NULL, { PMDA_PMID(CLUSTER_PAPI,81), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_ICR */ { NULL, { PMDA_PMID(CLUSTER_PAPI,82), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_ICW */ { NULL, { PMDA_PMID(CLUSTER_PAPI,83), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_ICW */ { NULL, { PMDA_PMID(CLUSTER_PAPI,84), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_ICW */ { NULL, { PMDA_PMID(CLUSTER_PAPI,85), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_TCH */ { NULL, { PMDA_PMID(CLUSTER_PAPI,86), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_TCH */ { NULL, { PMDA_PMID(CLUSTER_PAPI,87), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_TCH */ { NULL, { PMDA_PMID(CLUSTER_PAPI,88), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_TCA */ { NULL, { PMDA_PMID(CLUSTER_PAPI,89), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_TCA */ { NULL, { PMDA_PMID(CLUSTER_PAPI,90), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_TCA */ { NULL, { PMDA_PMID(CLUSTER_PAPI,91), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_TCR */ { NULL, { PMDA_PMID(CLUSTER_PAPI,92), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_TCR */ { NULL, { PMDA_PMID(CLUSTER_PAPI,93), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_TCR */ { NULL, { PMDA_PMID(CLUSTER_PAPI,94), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L1_TCW */ { NULL, { PMDA_PMID(CLUSTER_PAPI,95), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L2_TCW */ { NULL, { PMDA_PMID(CLUSTER_PAPI,96), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.L3_TCW */ { NULL, { PMDA_PMID(CLUSTER_PAPI,97), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FML_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,98), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FAD_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,99), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FDV_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,100), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FSQ_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,101), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FNV_INS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,102), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.FP_OPS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,103), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.SP_OPS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,104), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.DP_OPS */ { NULL, { PMDA_PMID(CLUSTER_PAPI,105), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.VEC_SP */ { NULL, { PMDA_PMID(CLUSTER_PAPI,106), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.VEC_DP */ { NULL, { PMDA_PMID(CLUSTER_PAPI,107), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.REF_CYC */ { NULL, { PMDA_PMID(CLUSTER_CONTROL,0), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.control.enable */ { NULL, { PMDA_PMID(CLUSTER_CONTROL,1), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.control.reset */ { NULL, { PMDA_PMID(CLUSTER_CONTROL,2), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.control.disable */ { NULL, { PMDA_PMID(CLUSTER_CONTROL,3), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.control.status */ { NULL, { PMDA_PMID(CLUSTER_AVAILABLE,0), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(0, 0, 0, 0, 0, 0) } }, /* papi.available.num_counters */ }; static void papi_endContextCallBack(int context) { if (pmDebug & DBG_TRACE_APPL0) __pmNotifyErr(LOG_DEBUG, "end context %d received\n", context); /* ensure clients re-using this slot re-authenticate */ if (context >= 0 && context < ctxtab_size) { ctxtab[context].uid_p = 0; ctxtab[context].gid_p = 0; } } static int papi_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom) { __pmID_int *idp = (__pmID_int *)&(mdesc->m_desc.pmid); int running = 0; int sts = 0; int i; sts = check_papi_state(sts); if (sts == PAPI_RUNNING && idp->cluster == CLUSTER_PAPI) { sts = PAPI_read(EventSet, values); if (sts != PAPI_OK) { __pmNotifyErr(LOG_ERR, "PAPI_read: %s\n", PAPI_strerror(sts)); return PM_ERR_VALUE; } running = 1; } switch (idp->cluster) { case CLUSTER_PAPI: if (!running) return PMDA_FETCH_NOVALUES; if (idp->item >= 0 && idp->item <= 107) { // the 'case' && 'idp->item' value we get is the pmns_position for (i = 0; i < number_of_events; i++) { if (papi_info[i].pmns_position == idp->item) { if(papi_info[i].position >= 0 && papi_info[i].papi_event_code){ atom->ull = values[papi_info[i].position]; return PMDA_FETCH_STATIC; } else return PMDA_FETCH_NOVALUES; } } } return PM_ERR_PMID; case CLUSTER_CONTROL: switch (idp->item) { case 0: atom->cp = enable_string; /* papi.control.enable */ return PMDA_FETCH_STATIC; case 1: // break; /* papi.control.reset */ // atom->cp = reset_string; return PM_ERR_NYI; case 2: if ((sts = check_papi_state(sts)) == PAPI_RUNNING) { atom->cp = disable_string; /* papi.control.disable */ return PMDA_FETCH_STATIC; } return 0; case 3: atom->cp = papi_string_status(); /* papi.control.status */ return PMDA_FETCH_STATIC; default: return PM_ERR_PMID; } break; case CLUSTER_AVAILABLE: if (idp->item == 0) { atom->ul = number_of_counters; /* papi.available.num_counters */ return PMDA_FETCH_STATIC; } return PM_ERR_PMID; default: return PM_ERR_PMID; } return PMDA_FETCH_NOVALUES; } static int papi_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda) { if (permission_check(pmda->e_context)) return pmdaFetch(numpmid, pmidlist, resp, pmda); return PM_ERR_PERMISSION; } static int remove_metric(unsigned int event, int position) { int retval = 0; int state = 0; int restart = 0; // bool to restart running values at the end int i; long_long new_values[size_of_active_counters]; retval = PAPI_query_event(event); if (retval != PAPI_OK){ if (pmDebug & DBG_TRACE_APPL0) __pmNotifyErr(LOG_DEBUG, "event not found on this hardware, skipping\n"); return retval; } /* check to make sure papi is running, otherwise do nothing */ state = check_papi_state(state); if (state == PAPI_RUNNING) { restart = 1; retval = PAPI_stop(EventSet, values); if(retval != PAPI_OK) return retval; } state = check_papi_state(state); if (state == PAPI_STOPPED) { /* first, copy the values over to new array */ for (i = 0; i < number_of_events; i++) new_values[papi_info[i].position] = values[papi_info[i].position]; /* workaround a papi bug: fully destroy the eventset and restart it */ memset(values, 0, sizeof(values[0])*size_of_active_counters); retval = PAPI_cleanup_eventset(EventSet); if (retval != PAPI_OK) return retval; retval = PAPI_destroy_eventset(&EventSet); if (retval != PAPI_OK) return retval; number_of_active_counters--; retval = PAPI_create_eventset(&EventSet); if (retval != PAPI_OK) return retval; // run through all metrics and adjust position variable as needed for (i = 0; i < number_of_events; i++) { // set event we're removing position to -1 if (papi_info[i].position == position) { new_values[papi_info[i].position] = 0; papi_info[i].position = -1; } } for (i = 0; i < number_of_events; i++) { if (papi_info[i].position < position) values[papi_info[i].position] = new_values[papi_info[i].position]; if (papi_info[i].position > position) { papi_info[i].position--; values[papi_info[i].position] = new_values[papi_info[i].position+1]; } if (papi_info[i].position >= 0 && papi_info[i].papi_event_code) { retval = PAPI_add_event(EventSet, papi_info[i].papi_event_code); if (retval != PAPI_OK) return retval; } } if (restart && (number_of_active_counters > 0)) { retval = PAPI_start(EventSet); if (retval != PAPI_OK) return retval; } return retval; } return PM_ERR_VALUE; } static int add_metric(unsigned int event) { int retval = 0; int state = 0; long_long new_values[size_of_active_counters]; int i; retval = PAPI_query_event(event); if (retval != PAPI_OK){ if (pmDebug & DBG_TRACE_APPL0) __pmNotifyErr(LOG_DEBUG, "event not found on this hardware, skipping\n"); return retval; } /* check status of papi */ state = check_papi_state(state); /* add check with number_of_counters */ /* stop papi if running? */ if (state == PAPI_RUNNING) { for (i = 0; i < size_of_active_counters; i++){ if(papi_info[i].position >= 0 && papi_info[i].papi_event_code) new_values[papi_info[i].position] = values[papi_info[i].position]; } retval = PAPI_stop(EventSet, values); if (retval != PAPI_OK) return retval; } state = check_papi_state(state); if (state == PAPI_STOPPED) { /* add metric */ retval = PAPI_add_event(EventSet, event); //XXX possibly switch this to add_events if (retval != PAPI_OK) return retval; for (i = 0; i < size_of_active_counters; i++){ if(papi_info[i].position >= 0 && papi_info[i].papi_event_code) values[papi_info[i].position] = new_values[papi_info[i].position]; } number_of_active_counters++; retval = PAPI_start(EventSet); return retval; } return PM_ERR_VALUE; } static int papi_store(pmResult *result, pmdaExt *pmda) { int sts; int i, j, len; const char *delim = " ,"; char *substring; if (!permission_check(pmda->e_context)) return PM_ERR_PERMISSION; for (i = 0; i < result->numpmid; i++) { pmValueSet *vsp = result->vset[i]; __pmID_int *idp = (__pmID_int *)&(vsp->pmid); pmAtomValue av; if (idp->cluster != CLUSTER_CONTROL) return PM_ERR_PERMISSION; switch (idp->item) { case 0: //papi.enable if ((sts = pmExtractValue(vsp->valfmt, &vsp->vlist[0], PM_TYPE_STRING, &av, PM_TYPE_STRING)) < 0) return sts; free(enable_string); enable_string = av.cp; len = strlen(enable_string); substring = strtok(enable_string, delim); while (substring != NULL) { for (j = 0; j < number_of_events; j++) { if (!strcmp(substring, papi_info[j].papi_string_code) && papi_info[j].position < 0) { // add the metric to the set if it's not already there sts = add_metric(papi_info[j].papi_event_code); if (sts == PAPI_OK) papi_info[j].position = number_of_active_counters-1; } } substring = strtok(NULL, delim); } for (j = 0; j < len-1; j++) { // recover from tokenisation if (enable_string[j] == '\0') enable_string[j] = delim[0]; } break; case 1: //papi.reset #if 0 /* not yet implemented */ sts = check_papi_state(sts); if (sts == PAPI_RUNNING) { if ((sts = pmExtractValue(vsp->valfmt, &vsp->vlist[0], PM_TYPE_STRING, &av, PM_TYPE_STRING)) < 0) return sts; } sts = PAPI_reset(EventSet); if (pmDebug & DBG_TRACE_APPL0) __pmNotifyErr(LOG_DEBUG, "reset: %d\n", sts); if (sts != PAPI_OK) return PM_ERR_VALUE; break; #else return PM_ERR_NYI; #endif case 2: //papi.disable if ((sts = pmExtractValue(vsp->valfmt, &vsp->vlist[0], PM_TYPE_STRING, &av, PM_TYPE_STRING)) < 0) return sts; free(disable_string); disable_string = av.cp; len = strlen(disable_string); substring = strtok(disable_string, delim); while (substring != NULL) { for (j = 0; j < size_of_active_counters; j++) { if (!strcmp(substring, papi_info[j].papi_string_code)) { // remove the metric from the set sts = remove_metric(papi_info[j].papi_event_code, papi_info[j].position); if (sts == PAPI_OK) papi_info[j].position = -1; break; //we've found the correct metric, break; } } if (j == size_of_active_counters) { if (pmDebug & DBG_TRACE_APPL0) __pmNotifyErr(LOG_DEBUG, "metric name %s does not match any known metrics\n", substring); sts = 1; } substring = strtok(NULL, delim); } for (j = 0; j < len-1; j++) { // recover from tokenisation if (disable_string[j] == '\0') disable_string[j] = delim[0]; } if (sts) return PM_ERR_CONV; break; default: return PM_ERR_PMID; } } return 0; } static int papi_text(int ident, int type, char **buffer, pmdaExt *ep) { int ec; int i; int position = -1; PAPI_event_info_t info; __pmID_int *pmidp = (__pmID_int*)&ident; /* no indoms - we only deal with metric help text */ if ((type & PM_TEXT_PMID) != PM_TEXT_PMID) return PM_ERR_TEXT; ec = 0 | PAPI_PRESET_MASK; PAPI_enum_event(&ec, PAPI_ENUM_FIRST); for (i = 0; i < number_of_events; i++) { if (pmidp->item == papi_info[i].pmns_position) { position = i; break; } } do { if (PAPI_get_event_info(ec, &info) == PAPI_OK) { if (info.event_code == papi_info[position].papi_event_code) { if (type & PM_TEXT_ONELINE) *buffer = info.short_descr; else *buffer = info.long_descr; return 0; } } } while (PAPI_enum_event(&ec, 0) == PAPI_OK); return pmdaText(ident, type, buffer, ep); } static int papi_internal_init(void) { int ec; int sts; int addunderscore; PAPI_event_info_t info; char *substr; char concatstr[10] = {}; unsigned int i = 0; number_of_counters = PAPI_num_counters(); if (number_of_counters < 0){ __pmNotifyErr(LOG_ERR, "hardware does not support hardware counters\n"); return 1; } ec = 0 | PAPI_PRESET_MASK; sts = PAPI_library_init(PAPI_VER_CURRENT); if (sts != PAPI_VER_CURRENT) { __pmNotifyErr(LOG_DEBUG, "PAPI_library_init error!\n"); return PM_ERR_GENERIC; } sts = PAPI_set_domain(PAPI_DOM_ALL); if (sts != PAPI_OK) { __pmNotifyErr(LOG_DEBUG, "Cannot set the domain to PAPI_DOM_ALL.\n"); return PM_ERR_GENERIC; } enable_string = (char *)calloc(1, 1); disable_string = (char *)calloc(1, 1); PAPI_enum_event(&ec, PAPI_ENUM_FIRST); do { if (PAPI_get_event_info(ec, &info) == PAPI_OK) { i++; expand_papi_info(i); papi_info[i-1].papi_event_code = info.event_code; substr = strtok(info.symbol, "_"); while (substr != NULL) { addunderscore = 0; if (strcmp("PAPI",substr)) { addunderscore = 1; strcat(concatstr, substr); } substr = strtok(NULL, "_"); if (substr != NULL && addunderscore) { strcat(concatstr, "_"); } } strcpy(papi_info[i-1].papi_string_code, concatstr); memset(&concatstr[0], 0, sizeof(concatstr)); papi_info[i-1].position = -1; set_pmns_position(i-1); } } while(PAPI_enum_event(&ec, 0) == PAPI_OK); expand_values(i); if (PAPI_create_eventset(&EventSet) != PAPI_OK) { __pmNotifyErr(LOG_ERR, "PAPI_create_eventset error!\n"); return PM_ERR_GENERIC; } return 0; } /* use documented in pmdaAttribute(3) */ static int papi_contextAttributeCallBack(int context, int attr, const char *value, int length, pmdaExt *pmda) { int id = -1; enlarge_ctxtab(context); assert(ctxtab != NULL && context < ctxtab_size); switch (attr) { case PCP_ATTR_USERID: ctxtab[context].uid_p = 1; id = atoi(value); ctxtab[context].uid = id; break; case PCP_ATTR_GROUPID: ctxtab[context].gid_p = 1; id = atoi(value); ctxtab[context].gid = id; break; default: return 0; } if (id != 0) { if (pmDebug & DBG_TRACE_AUTH) __pmNotifyErr(LOG_DEBUG, "access denied attr=%d id=%d\n", attr, id); return PM_ERR_PERMISSION; } else if (pmDebug & DBG_TRACE_AUTH) __pmNotifyErr(LOG_DEBUG, "access granted attr=%d id=%d\n", attr, id); return 0; } void __PMDA_INIT_CALL papi_init(pmdaInterface *dp) { int nummetrics = sizeof(metrictab)/sizeof(metrictab[0]); int sts; if (isDSO) { char mypath[MAXPATHLEN]; int sep = __pmPathSeparator(); snprintf(mypath, sizeof(mypath), "%s%c" "papi" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDSO(dp, PMDA_INTERFACE_6, "papi DSO", mypath); } if (dp->status != 0) return; dp->comm.flags |= PDU_FLAG_AUTH; if ((sts = papi_internal_init()) != 0) { __pmNotifyErr(LOG_ERR, "papi_internal_init returned %d\n", sts); dp->status = PM_ERR_GENERIC; return; } dp->version.six.fetch = papi_fetch; dp->version.six.store = papi_store; dp->version.six.attribute = papi_contextAttributeCallBack; dp->version.any.text = papi_text; pmdaSetFetchCallBack(dp, papi_fetchCallBack); pmdaSetEndContextCallBack(dp, papi_endContextCallBack); pmdaInit(dp, NULL, 0, metrictab, nummetrics); } static pmLongOptions longopts[] = { PMDA_OPTIONS_HEADER("Options"), PMOPT_DEBUG, PMDAOPT_DOMAIN, PMDAOPT_LOGFILE, PMOPT_HELP, PMDA_OPTIONS_END }; static pmdaOptions opts = { .short_options = "D:d:l:?", .long_options = longopts, }; /* * Set up agent if running as daemon. */ int main(int argc, char **argv) { int sep = __pmPathSeparator(); pmdaInterface dispatch; char helppath[MAXPATHLEN]; isDSO = 0; __pmSetProgname(argv[0]); snprintf(helppath, sizeof(helppath), "%s%c" "papi" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDaemon(&dispatch, PMDA_INTERFACE_6, pmProgname, PAPI, "papi.log", helppath); pmdaGetOptions(argc, argv, &opts, &dispatch); if (opts.errors) { pmdaUsageMessage(&opts); exit(1); } pmdaOpenLog(&dispatch); papi_init(&dispatch); pmdaConnect(&dispatch); pmdaMain(&dispatch); free(ctxtab); free(papi_info); free(values); exit(0); }