PAPI 7.1.0.0
Loading...
Searching...
No Matches
syst_smp.c
Go to the documentation of this file.
1/*
2 * syst_smp.c - system-wide monitoring for SMP machine using libpfms helper
3 * library
4 *
5 * Copyright (c) 2006 Hewlett-Packard Development Company, L.P.
6 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 * of the Software, and to permit persons to whom the Software is furnished to do so,
13 * subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in all
16 * copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
19 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
22 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
23 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25#include <sys/types.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <unistd.h>
29#include <string.h>
30#include <pthread.h>
31#include <inttypes.h>
32#include <errno.h>
33#include <stdarg.h>
34
35#include <perfmon/perfmon.h>
36#include <perfmon/pfmlib.h>
37
38#include <libpfms.h>
39
40
41#define NUM_PMCS PFMLIB_MAX_PMCS
42#define NUM_PMDS PFMLIB_MAX_PMDS
43
44static void fatal_error(char *fmt,...) __attribute__((noreturn));
45
46static void
47fatal_error(char *fmt, ...)
48{
49 va_list ap;
50
51 va_start(ap, fmt);
52 vfprintf(stderr, fmt, ap);
53 va_end(ap);
54
55 exit(1);
56}
57
58static uint32_t
59popcount(uint64_t c)
60{
61 uint32_t count = 0;
62
63 for(; c; c>>=1) {
64 if (c & 0x1)
65 count++;
66 }
67 return count;
68}
69
70int
71main(int argc, char **argv)
72{
73 pfarg_ctx_t ctx;
75 pfarg_pmd_t *pd;
78 uint64_t cpu_list;
79 void *desc;
80 unsigned int num_counters;
81 uint32_t i, j, l, k, ncpus, npmds;
82 size_t len;
83 int ret;
84 char *name;
85
87 fatal_error("cannot initialize libpfm\n");
88
89 if (pfms_initialize())
90 fatal_error("cannot initialize libpfms\n");
91
92 memset(&ctx, 0, sizeof(ctx));
93 memset(pc, 0, sizeof(pc));
94
95 ncpus = (uint32_t)sysconf(_SC_NPROCESSORS_ONLN);
96 if (ncpus == -1)
97 fatal_error("cannot retrieve number of online processors\n");
98
99 if (argc > 1) {
100 cpu_list = strtoul(argv[1],NULL,0);
101 if (popcount(cpu_list) > ncpus)
102 fatal_error("too many processors specified\n");
103 } else {
104 cpu_list = ((1<<ncpus)-1);
105 }
106
107 /*
108 * use libpfm to prepare some decent PMC/PMD setup
109 */
110 memset(&inp,0, sizeof(inp));
111 memset(&outp,0, sizeof(outp));
112
113 pfm_get_num_counters(&num_counters);
115
116 name = malloc(len+1);
117 if (name == NULL)
118 fatal_error("cannot allocate memory for event name\n");
119
120
122 fatal_error("cannot find cycle event\n");
123
125 fatal_error("cannot find inst retired event\n");
126
127 i = 2;
128
130
131 if (i > num_counters) {
132 i = num_counters;
133 printf("too many events provided (max=%d events), using first %d event(s)\n", num_counters, i);
134 }
135 /*
136 * how many counters we use
137 */
138 inp.pfp_event_count = i;
139
140 /*
141 * indicate we are using the monitors for a system-wide session.
142 * This may impact the way the library sets up the PMC values.
143 */
145
146 /*
147 * let the library figure out the values for the PMCS
148 */
149 if ((ret=pfm_dispatch_events(&inp, NULL, &outp, NULL)) != PFMLIB_SUCCESS)
150 fatal_error("cannot configure events: %s\n", pfm_strerror(ret));
151
152
153 npmds = ncpus * inp.pfp_event_count;
154
155 printf("ncpus=%u npmds=%u\n", ncpus, npmds);
156
157 pd = calloc(npmds, sizeof(pfarg_pmd_t));
158 if (pd == NULL)
159 fatal_error("cannot allocate pd array\n");
160
161 for (i=0; i < outp.pfp_pmc_count; i++) {
162 pc[i].reg_num = outp.pfp_pmcs[i].reg_num;
163 pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
164 }
165
166 /*
167 * We use inp.pfp_event_count PMD registers for our events per-CPU.
168 * We need to setup the PMDs we use. They are determined based on the
169 * PMC registers used. The following loop prepares the pd[] array
170 * for pfm_write_pmds(). With libpfms, on PMD write we need to pass
171 * only pfp_event_count PMD registers. But on PMD read, we need
172 * to pass pfp_event_count PMD registers per-CPU because libpfms
173 * does not aggregate counts. To prepapre for PMD read, we therefore
174 * propagate the PMD setup beyond just the first pfp_event_count
175 * elements of pd[].
176 */
177 for(l=0, k= 0; l < ncpus; l++) {
178 for (i=0; i < outp.pfp_pmd_count; i++, k++)
179 pd[k].reg_num = outp.pfp_pmds[i].reg_num;
180 }
181
182 /*
183 * create a context on all CPUs we asked for
184 *
185 * libpfms only works for system-wide, so we set the flag in
186 * the master context. the context argument is not modified by
187 * call.
188 *
189 * desc is an opaque descriptor used to identify session.
190 */
192
193 ret = pfms_create(&cpu_list, 1, &ctx, NULL, &desc);
194 if (ret == -1)
195 fatal_error("create error %d\n", ret);
196
197 /*
198 * program the PMC registers on all CPUs of interest
199 */
200 ret = pfms_write_pmcs(desc, pc, outp.pfp_pmc_count);
201 if (ret == -1)
202 fatal_error("write_pmcs error %d\n", ret);
203
204 /*
205 * program the PMD registers on all CPUs of interest
206 */
207 ret = pfms_write_pmds(desc, pd, outp.pfp_pmd_count);
208 if (ret == -1)
209 fatal_error("write_pmds error %d\n", ret);
210
211 /*
212 * load context on all CPUs of interest
213 */
214 ret = pfms_load(desc);
215 if (ret == -1)
216 fatal_error("load error %d\n", ret);
217
218 printf("monitoring for 10s on all CPUs\n");
219
220 /*
221 * start monitoring on all CPUs of interest
222 */
223 ret = pfms_start(desc);
224 if (ret == -1)
225 fatal_error("start error %d\n", ret);
226
227 /*
228 * stop and listen to activity for 10s
229 */
230 sleep(10);
231
232 /*
233 * stop monitoring on all CPUs of interest
234 */
235 ret = pfms_stop(desc);
236 if (ret == -1)
237 fatal_error("stop error %d\n", ret);
238
239 /*
240 * read the PMD registers on all CPUs of interest.
241 * The pd[] array must be organized such that to
242 * read 2 PMDs on each CPU you need:
243 * - 2 * number of CPUs of interest
244 * - the first 2 elements of pd[] read on CPU0
245 * - the next 2 elements of pd[] read on CPU1
246 * - and so on
247 */
248 ret = pfms_read_pmds(desc, pd, npmds);
249 if (ret == -1)
250 fatal_error("read_pmds error %d\n", ret);
251
252 /*
253 * print per-CPU results
254 */
255 for(j=0, k= 0; j < ncpus; j++) {
256 for (i=0; i < inp.pfp_event_count; i++, k++) {
258 printf("CPU%-3d PMD%u %20"PRIu64" %s\n",
259 j,
260 pd[k].reg_num,
261 pd[k].reg_value,
262 name);
263 }
264 }
265
266 /*
267 * destroy context on all CPUs of interest.
268 * After this call desc is invalid
269 */
270 ret = pfms_close(desc);
271 if (ret == -1)
272 fatal_error("close error %d\n", ret);
273
274 free(name);
275
276 return 0;
277}
int i
static long count
static double c[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:40
#define PFM_FL_SYSTEM_WIDE
static uint32_t ncpus
Definition: libpfms.c:63
int pfms_write_pmcs(void *desc, pfarg_pmc_t *pmcs, uint32_t n)
Definition: libpfms.c:596
int pfms_write_pmds(void *desc, pfarg_pmd_t *pmds, uint32_t n)
Definition: libpfms.c:602
int pfms_create(uint64_t *cpu_list, size_t n, pfarg_ctx_t *ctx, pfms_ovfl_t *ovfl, void **desc)
Definition: libpfms.c:327
int pfms_stop(void *desc)
Definition: libpfms.c:590
int pfms_load(void *desc)
Definition: libpfms.c:468
int pfms_close(void *desc)
Definition: libpfms.c:608
int pfms_initialize(void)
Definition: libpfms.c:300
int pfms_read_pmds(void *desc, pfarg_pmd_t *pmds, uint32_t n)
Definition: libpfms.c:660
int pfms_start(void *desc)
Definition: libpfms.c:584
unsigned long AO_t __attribute__((__aligned__(4)))
Definition: m68k.h:21
__gnuc_va_list va_list
FILE * stderr
int main()
Definition: pernode.c:20
pfm_err_t pfm_get_inst_retired_event(pfmlib_event_t *e)
char * pfm_strerror(int code)
pfm_err_t pfm_dispatch_events(pfmlib_input_param_t *p, void *model_in, pfmlib_output_param_t *q, void *model_out)
#define PFMLIB_SUCCESS
Definition: pfmlib.h:283
#define PFM_PLM3
Definition: pfmlib.h:53
pfm_err_t pfm_get_full_event_name(pfmlib_event_t *e, char *name, size_t maxlen)
pfm_err_t pfm_get_cycle_event(pfmlib_event_t *e)
#define PFM_PLM0
Definition: pfmlib.h:50
pfm_err_t pfm_initialize(void)
pfm_err_t pfm_get_max_event_name_len(size_t *len)
#define PFMLIB_PFP_SYSTEMWIDE
Definition: pfmlib.h:121
pfm_err_t pfm_get_num_counters(unsigned int *num)
const char * fmt
Definition: pscanf.h:10
va_end(arg_list)
va_start(arg_list, fmt)
const char * name
Definition: rocs.c:225
uint32_t ctx_flags
Definition: perfmon_v2.h:19
uint16_t reg_num
Definition: perfmon_v2.h:28
uint64_t reg_value
Definition: perfmon_v2.h:31
unsigned int pfp_dfl_plm
Definition: pfmlib.h:110
unsigned int pfp_flags
Definition: pfmlib.h:111
pfmlib_event_t pfp_events[PFMLIB_MAX_PMCS]
Definition: pfmlib.h:113
unsigned int pfp_event_count
Definition: pfmlib.h:109
pfmlib_reg_t pfp_pmds[PFMLIB_MAX_PMDS]
Definition: pfmlib.h:130
pfmlib_reg_t pfp_pmcs[PFMLIB_MAX_PMCS]
Definition: pfmlib.h:129
unsigned int pfp_pmc_count
Definition: pfmlib.h:127
unsigned int pfp_pmd_count
Definition: pfmlib.h:128
unsigned long long reg_value
Definition: pfmlib.h:98
unsigned int reg_num
Definition: pfmlib.h:100
static void fatal_error(char *fmt,...) __attribute__((noreturn))
Definition: syst_smp.c:47
#define NUM_PMCS
Definition: syst_smp.c:41
static uint32_t popcount(uint64_t c)
Definition: syst_smp.c:59