Diff of /libperf_events/operf_utils.cpp [3795ee] .. [ebde58] Maximize Restore

  Switch to unified view

a/libperf_events/operf_utils.cpp b/libperf_events/operf_utils.cpp
...
...
62
size_t pg_sz;
62
size_t pg_sz;
63
63
64
static list<event_t *> unresolved_events;
64
static list<event_t *> unresolved_events;
65
static struct operf_transient trans;
65
static struct operf_transient trans;
66
static bool sfile_init_done;
66
static bool sfile_init_done;
67
68
/* Some architectures (e.g., ppc64) do not use the same event value (code) for oprofile
69
 * and for perf_events.  The operf-record process requires event values that perf_events
70
 * understands, but the operf-read process requires oprofile event values.  The purpose of
71
 * the following method is to map the operf-record event value to a value that
72
 * opreport can understand.
73
 */
74
#if PPC64_ARCH
75
extern op_cpu cpu_type;
76
#define NIL_CODE ~0U
77
78
#if HAVE_LIBPFM3
79
static bool _get_codes_for_match(unsigned int pfm_idx, const char name[],
80
                                 vector<operf_event_t> * evt_vec)
81
{
82
  unsigned int num_events = evt_vec->size();
83
  int tmp_code, ret;
84
  char evt_name[OP_MAX_EVT_NAME_LEN];
85
  unsigned int events_converted = 0;
86
  for (unsigned int i = 0; i < num_events; i++) {
87
      operf_event_t event = (*evt_vec)[i];
88
      if (event.evt_code != NIL_CODE) {
89
          events_converted++;
90
          continue;
91
      }
92
      memset(evt_name, 0, OP_MAX_EVT_NAME_LEN);
93
      if (!strcmp(event.name, "CYCLES")) {
94
          strcpy(evt_name ,"PM_CYC") ;
95
      } else if (strstr(event.name, "_GRP")) {
96
          string str = event.name;
97
          strncpy(evt_name, event.name, str.rfind("_GRP"));
98
      } else {
99
          strncpy(evt_name, event.name, strlen(event.name));
100
      }
101
      if (strncmp(name, evt_name, OP_MAX_EVT_NAME_LEN))
102
          continue;
103
      ret = pfm_get_event_code(pfm_idx, &tmp_code);
104
      if (ret != PFMLIB_SUCCESS) {
105
          string evt_name_str = event.name;
106
          string msg = "libpfm cannot find event code for " + evt_name_str +
107
                  "; cannot continue";
108
          throw runtime_error(msg);
109
      }
110
      event.evt_code = tmp_code;
111
      (*evt_vec)[i] = event;
112
      events_converted++;
113
      cverb << vrecord << "Successfully converted " << event.name << " to perf_event code "
114
            << hex << tmp_code << endl;
115
  }
116
  return (events_converted == num_events);
117
}
118
#else
119
static bool _op_get_event_codes(vector<operf_event_t> * evt_vec)
120
{
121
  int ret, i;
122
  unsigned int num_events = evt_vec->size();
123
  char evt_name[OP_MAX_EVT_NAME_LEN];
124
  unsigned int events_converted = 0;
125
  uint64_t code[1];
126
127
  typedef struct {
128
      uint64_t    *codes;
129
      char        **fstr;
130
      size_t      size;
131
      int         count;
132
      int         idx;
133
  } pfm_raw_pmu_encode_t;
134
135
  pfm_raw_pmu_encode_t raw;
136
  raw.codes = code;
137
  raw.count = 1;
138
  raw.fstr = NULL;
139
140
  if (pfm_initialize() != PFM_SUCCESS)
141
      throw runtime_error("Unable to initialize libpfm; cannot continue");
142
143
  for (unsigned int i = 0; i < num_events; i++) {
144
      operf_event_t event = (*evt_vec)[i];
145
      if (event.evt_code != NIL_CODE) {
146
          events_converted++;
147
          continue;
148
      }
149
      memset(evt_name, 0, OP_MAX_EVT_NAME_LEN);
150
      if (!strcmp(event.name, "CYCLES")) {
151
          strcpy(evt_name ,"PM_CYC") ;
152
      } else if (strstr(event.name, "_GRP")) {
153
          string str = event.name;
154
          strncpy(evt_name, event.name, str.rfind("_GRP"));
155
      } else {
156
          strncpy(evt_name, event.name, strlen(event.name));
157
      }
158
159
      memset(&raw, 0, sizeof(raw));
160
      ret = pfm_get_os_event_encoding(evt_name, PFM_PLM3, PFM_OS_NONE, &raw);
161
      if (ret != PFM_SUCCESS) {
162
          string evt_name_str = event.name;
163
          string msg = "libpfm cannot find event code for " + evt_name_str +
164
                  "; cannot continue";
165
          throw runtime_error(msg);
166
      }
167
168
      event.evt_code = raw.codes[0];
169
      (*evt_vec)[i] = event;
170
      events_converted++;
171
      cverb << vrecord << "Successfully converted " << event.name << " to perf_event code "
172
            << hex << event.evt_code << endl;
173
  }
174
  return (events_converted == num_events);
175
}
176
#endif
177
178
bool OP_perf_utils::op_convert_event_vals(vector<operf_event_t> * evt_vec)
179
{
180
  unsigned int i, count;
181
  char name[256];
182
  int ret;
183
  for (unsigned int i = 0; i < evt_vec->size(); i++) {
184
      operf_event_t event = (*evt_vec)[i];
185
      if (cpu_type == CPU_PPC64_POWER7) {
186
          if (!strncmp(event.name, "PM_RUN_CYC", strlen("PM_RUN_CYC"))) {
187
              event.evt_code = 0x600f4;
188
          } else if (!strncmp(event.name, "PM_RUN_INST_CMPL", strlen("PM_RUN_INST_CMPL"))) {
189
              event.evt_code = 0x500fa;
190
          } else {
191
              event.evt_code = NIL_CODE;
192
          }
193
      } else {
194
          event.evt_code = NIL_CODE;
195
      }
196
      (*evt_vec)[i] = event;
197
  }
198
199
#if HAVE_LIBPFM3
200
  if (pfm_initialize() != PFMLIB_SUCCESS)
201
      throw runtime_error("Unable to initialize libpfm; cannot continue");
202
203
  ret = pfm_get_num_events(&count);
204
  if (ret != PFMLIB_SUCCESS)
205
      throw runtime_error("Unable to use libpfm to obtain event code; cannot continue");
206
  for(i =0 ; i < count; i++)
207
  {
208
      ret = pfm_get_event_name(i, name, 256);
209
      if (ret != PFMLIB_SUCCESS)
210
          continue;
211
      if (_get_codes_for_match(i, name, evt_vec))
212
          break;
213
  }
214
  return (i != count);
215
#else
216
  return _op_get_event_codes(evt_vec);
217
#endif
218
}
219
220
#endif // PPC64_ARCH
221
222
67
223
static inline void update_trans_last(struct operf_transient * trans)
68
static inline void update_trans_last(struct operf_transient * trans)
224
{
69
{
225
    trans->last = trans->current;
70
    trans->last = trans->current;
226
    trans->last_pc = trans->pc;
71
    trans->last_pc = trans->pc;
...
...
1463
    old += size;
1308
    old += size;
1464
    pr->add_to_total(op_write_output(out_fd, buf, size));
1309
    pr->add_to_total(op_write_output(out_fd, buf, size));
1465
    md->prev = old;
1310
    md->prev = old;
1466
    pc->data_tail = old;
1311
    pc->data_tail = old;
1467
}
1312
}
1468
1469
1470
int OP_perf_utils::op_get_next_online_cpu(DIR * dir, struct dirent *entry)
1471
{
1472
#define OFFLINE 0x30
1473
  unsigned int cpu_num;
1474
  char cpu_online_pathname[40];
1475
  int res;
1476
  FILE * online;
1477
  again:
1478
  do {
1479
      entry = readdir(dir);
1480
      if (!entry)
1481
          return -1;
1482
  } while (entry->d_type != DT_DIR);
1483
1484
  res = sscanf(entry->d_name, "cpu%u", &cpu_num);
1485
  if (res <= 0)
1486
      goto again;
1487
1488
  errno = 0;
1489
  snprintf(cpu_online_pathname, 40, "/sys/devices/system/cpu/cpu%u/online", cpu_num);
1490
  if ((online = fopen(cpu_online_pathname, "r")) == NULL) {
1491
      cerr << "Unable to open " << cpu_online_pathname << endl;
1492
      if (errno)
1493
          cerr << strerror(errno) << endl;
1494
      return -1;
1495
  }
1496
  res = fgetc(online);
1497
  fclose(online);
1498
  if (res == OFFLINE)
1499
      goto again;
1500
  else
1501
      return cpu_num;
1502
}