PAPI 7.1.0.0
Loading...
Searching...
No Matches
perfctr.c
Go to the documentation of this file.
1/*
2* File: perfctr.c
3* Author: Philip Mucci
4* mucci at cs.utk.edu
5* Mods: Kevin London
6* london at cs.utk.edu
7* Mods: Maynard Johnson
8* maynardj at us.ibm.com
9* Mods: Brian Sheely
10* bsheely at eecs.utk.edu
11*/
12
13#include <string.h>
14#include <linux/unistd.h>
15#include <errno.h>
16#include <sys/time.h>
17
18#include "papi.h"
19#include "papi_internal.h"
20
21#ifdef PPC64
22#include "perfctr-ppc64.h"
23#else
24#include "perfctr-x86.h"
25#include "papi_libpfm_events.h"
26#endif
27
28#include "papi_vector.h"
29
30#include "papi_memory.h"
31#include "extras.h"
32
33#include "linux-common.h"
34#include "linux-context.h"
35
37
38#ifdef PPC64
39extern int setup_ppc64_presets( int cputype, int cidx );
40#endif
41
42/* This should be in a linux.h header file maybe. */
43#define FOPEN_ERROR "fopen(%s) returned NULL"
44
45#if defined(PERFCTR26)
46#define PERFCTR_CPU_NAME(pi) perfctr_info_cpu_name(pi)
47#define PERFCTR_CPU_NRCTRS(pi) perfctr_info_nrctrs(pi)
48#else
49#define PERFCTR_CPU_NAME perfctr_cpu_name
50#define PERFCTR_CPU_NRCTRS perfctr_cpu_nrctrs
51#endif
52
53#if !defined(PPC64)
54static inline int
55xlate_cpu_type_to_vendor( unsigned perfctr_cpu_type )
56{
57 switch ( perfctr_cpu_type ) {
58 case PERFCTR_X86_INTEL_P5:
59 case PERFCTR_X86_INTEL_P5MMX:
60 case PERFCTR_X86_INTEL_P6:
61 case PERFCTR_X86_INTEL_PII:
62 case PERFCTR_X86_INTEL_PIII:
63 case PERFCTR_X86_INTEL_P4:
64 case PERFCTR_X86_INTEL_P4M2:
65#ifdef PERFCTR_X86_INTEL_P4M3
66 case PERFCTR_X86_INTEL_P4M3:
67#endif
68#ifdef PERFCTR_X86_INTEL_PENTM
69 case PERFCTR_X86_INTEL_PENTM:
70#endif
71#ifdef PERFCTR_X86_INTEL_CORE
72 case PERFCTR_X86_INTEL_CORE:
73#endif
74#ifdef PERFCTR_X86_INTEL_CORE2
75 case PERFCTR_X86_INTEL_CORE2:
76#endif
77#ifdef PERFCTR_X86_INTEL_ATOM /* family 6 model 28 */
78 case PERFCTR_X86_INTEL_ATOM:
79#endif
80#ifdef PERFCTR_X86_INTEL_NHLM /* family 6 model 26 */
81 case PERFCTR_X86_INTEL_NHLM:
82#endif
83#ifdef PERFCTR_X86_INTEL_WSTMR
84 case PERFCTR_X86_INTEL_WSTMR:
85#endif
86 return ( PAPI_VENDOR_INTEL );
87#ifdef PERFCTR_X86_AMD_K8
88 case PERFCTR_X86_AMD_K8:
89#endif
90#ifdef PERFCTR_X86_AMD_K8C
91 case PERFCTR_X86_AMD_K8C:
92#endif
93#ifdef PERFCTR_X86_AMD_FAM10 /* this is defined in perfctr 2.6.29 */
94 case PERFCTR_X86_AMD_FAM10:
95#endif
96 case PERFCTR_X86_AMD_K7:
97 return ( PAPI_VENDOR_AMD );
98 default:
99 return ( PAPI_VENDOR_UNKNOWN );
100 }
101}
102#endif
103
104long long tb_scale_factor = ( long long ) 1; /* needed to scale get_cycles on PPC series */
105
106int
108{
109 int retval;
110 struct perfctr_info info;
111 char abiv[PAPI_MIN_STR_LEN];
112
113#if defined(PERFCTR26)
114 int fd;
115#else
116 struct vperfctr *dev;
117#endif
118
119#if defined(PERFCTR26)
120 /* Get info from the kernel */
121 /* Use lower level calls per Mikael to get the perfctr info
122 without actually creating a new kernel-side state.
123 Also, close the fd immediately after retrieving the info.
124 This is much lighter weight and doesn't reserve the counter
125 resources. Also compatible with perfctr 2.6.14.
126 */
127 fd = _vperfctr_open( 0 );
128 if ( fd < 0 ) {
132 goto fn_fail;
133 }
134 retval = perfctr_info( fd, &info );
135 close( fd );
136 if ( retval < 0 ) {
140 goto fn_fail;
141 }
142
143 /* copy tsc multiplier to local variable */
144 /* this field appears in perfctr 2.6 and higher */
145 tb_scale_factor = ( long long ) info.tsc_to_cpu_mult;
146#else
147 /* Opened once for all threads. */
148 if ( ( dev = vperfctr_open( ) ) == NULL ) {
152 goto fn_fail;
153 }
154 SUBDBG( "_perfctr_init_component vperfctr_open = %p\n", dev );
155
156 /* Get info from the kernel */
157 retval = vperfctr_info( dev, &info );
158 if ( retval < 0 ) {
162 goto fn_fail;
163 }
164 vperfctr_close( dev );
165#endif
166
167 /* Fill in what we can of the papi_system_info. */
169 if ( retval != PAPI_OK )
170 goto fn_fail;
171
172 /* Setup memory info */
174 ( int ) info.cpu_type );
175 if ( retval )
176 goto fn_fail;
177
178 strcpy( _perfctr_vector.cmp_info.name,"perfctr.c" );
179 strcpy( _perfctr_vector.cmp_info.version, "$Revision$" );
180 sprintf( abiv, "0x%08X", info.abi_version );
182 strcpy( _perfctr_vector.cmp_info.kernel_version, info.driver_version );
186 if ( info.cpu_features & PERFCTR_FEATURE_RDPMC )
188 else
195#if !defined(PPC64)
196 /* AMD and Intel ia386 processors all support unit mask bits */
198#endif
199#if defined(PPC64)
202#else
204#endif
207 if ( info.cpu_features & PERFCTR_FEATURE_PCINT )
209 else
211 SUBDBG( "Hardware/OS %s support counter generated interrupts\n",
212 _perfctr_vector.cmp_info.hardware_intr ? "does" : "does not" );
213
215 PERFCTR_CPU_NAME( &info ) );
216 _papi_hwi_system_info.hw_info.model = ( int ) info.cpu_type;
217#if defined(PPC64)
219 if ( strlen( _papi_hwi_system_info.hw_info.vendor_string ) == 0 )
221#else
223 xlate_cpu_type_to_vendor( info.cpu_type );
224#endif
225
226 /* Setup presets last. Some platforms depend on earlier info */
227#if !defined(PPC64)
228// retval = setup_p3_vector_table(vtable);
229 if ( !retval )
231#else
232 /* Setup native and preset events */
233// retval = ppc64_setup_vector_table(vtable);
234 if ( !retval )
236 if ( !retval )
237 retval = setup_ppc64_presets( info.cpu_type, cidx );
238#endif
239
240 fn_exit:
241 _papi_hwd[cidx]->cmp_info.disabled = retval;
242 return retval;
243 fn_fail:
244 goto fn_exit;
245}
246
247static int
248attach( hwd_control_state_t * ctl, unsigned long tid )
249{
250 struct vperfctr_control tmp;
251
252#ifdef VPERFCTR_CONTROL_CLOEXEC
253 tmp.flags = VPERFCTR_CONTROL_CLOEXEC;
254#endif
255
256 ctl->rvperfctr = rvperfctr_open( ( int ) tid );
257 if ( ctl->rvperfctr == NULL ) {
259 return ( PAPI_ESYS );
260 }
261 SUBDBG( "_papi_hwd_ctl rvperfctr_open() = %p\n", ctl->rvperfctr );
262
263 /* Initialize the per thread/process virtualized TSC */
264 memset( &tmp, 0x0, sizeof ( tmp ) );
265 tmp.cpu_control.tsc_on = 1;
266
267 /* Start the per thread/process virtualized TSC */
268 if ( rvperfctr_control( ctl->rvperfctr, &tmp ) < 0 ) {
270 return ( PAPI_ESYS );
271 }
272
273 return ( PAPI_OK );
274} /* end attach() */
275
276static int
278{
279 rvperfctr_close( ctl->rvperfctr );
280 return ( PAPI_OK );
281} /* end detach() */
282
283static inline int
285{
286 if ( ns < _papi_os_info.itimer_res_ns ) {
288 } else {
289 int leftover_ns = ns % _papi_os_info.itimer_res_ns;
290 return ns + leftover_ns;
291 }
292}
293
294int
296{
297 ( void ) ctx; /*unused */
298 switch ( code ) {
299 case PAPI_DOMAIN:
300 case PAPI_DEFDOM:
301#if defined(PPC64)
302 return ( _perfctr_vector.
303 set_domain( option->domain.ESI, option->domain.domain ) );
304#else
305 return ( _perfctr_vector.
306 set_domain( option->domain.ESI->ctl_state,
307 option->domain.domain ) );
308#endif
309 case PAPI_GRANUL:
310 case PAPI_DEFGRN:
311 return PAPI_ECMP;
312 case PAPI_ATTACH:
313 return ( attach( option->attach.ESI->ctl_state, option->attach.tid ) );
314 case PAPI_DETACH:
315 return ( detach( option->attach.ESI->ctl_state ) );
316 case PAPI_DEF_ITIMER:
317 {
318 /* flags are currently ignored, eventually the flags will be able
319 to specify whether or not we use POSIX itimers (clock_gettimer) */
320 if ( ( option->itimer.itimer_num == ITIMER_REAL ) &&
321 ( option->itimer.itimer_sig != SIGALRM ) )
322 return PAPI_EINVAL;
323 if ( ( option->itimer.itimer_num == ITIMER_VIRTUAL ) &&
324 ( option->itimer.itimer_sig != SIGVTALRM ) )
325 return PAPI_EINVAL;
326 if ( ( option->itimer.itimer_num == ITIMER_PROF ) &&
327 ( option->itimer.itimer_sig != SIGPROF ) )
328 return PAPI_EINVAL;
329 if ( option->itimer.ns > 0 )
330 option->itimer.ns = round_requested_ns( option->itimer.ns );
331 /* At this point, we assume the user knows what he or
332 she is doing, they maybe doing something arch specific */
333 return PAPI_OK;
334 }
335 case PAPI_DEF_MPX_NS:
336 {
337 option->multiplex.ns =
338 ( unsigned long ) round_requested_ns( ( int ) option->multiplex.
339 ns );
340 return ( PAPI_OK );
341 }
343 {
344 option->itimer.ns = round_requested_ns( option->itimer.ns );
345 return ( PAPI_OK );
346 }
347 default:
348 return ( PAPI_ENOSUPP );
349 }
350}
351
352void
353_perfctr_dispatch_timer( int signal, siginfo_t * si, void *context )
354{
355 ( void ) signal; /*unused */
357 ThreadInfo_t *master = NULL;
358 int isHardware = 0;
359 vptr_t address;
361 hwd_context_t *our_context;
362
363 ctx.si = si;
364 ctx.ucontext = ( ucontext_t * ) context;
365
366#define OVERFLOW_MASK si->si_pmc_ovf_mask
367#define GEN_OVERFLOW 0
368
369 address = ( vptr_t ) GET_OVERFLOW_ADDRESS( ( ctx ) );
370 _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address, &isHardware,
371 OVERFLOW_MASK, GEN_OVERFLOW, &master,
373
374 /* We are done, resume interrupting counters */
375 if ( isHardware ) {
376 our_context=(hwd_context_t *) master->context[cidx];
377 errno = vperfctr_iresume( our_context->perfctr );
378 if ( errno < 0 ) {
379 PAPIERROR( "vperfctr_iresume errno %d", errno );
380 }
381 }
382}
383
384
385int
387{
388 struct vperfctr_control tmp;
389 int error;
390
391 /* Initialize our thread/process pointer. */
392 if ( ( ctx->perfctr = vperfctr_open( ) ) == NULL ) {
393#ifdef VPERFCTR_OPEN_CREAT_EXCL
394 /* New versions of perfctr have this, which allows us to
395 get a previously created context, i.e. one created after
396 a fork and now we're inside a new process that has been exec'd */
397 if ( errno ) {
398 if ( ( ctx->perfctr = vperfctr_open_mode( 0 ) ) == NULL ) {
399 return PAPI_ESYS;
400 }
401 } else {
402 return PAPI_ESYS;
403 }
404#else
405 return PAPI_ESYS;
406#endif
407 }
408 SUBDBG( "_papi_hwd_init vperfctr_open() = %p\n", ctx->perfctr );
409
410 /* Initialize the per thread/process virtualized TSC */
411 memset( &tmp, 0x0, sizeof ( tmp ) );
412 tmp.cpu_control.tsc_on = 1;
413
414#ifdef VPERFCTR_CONTROL_CLOEXEC
415 tmp.flags = VPERFCTR_CONTROL_CLOEXEC;
416 SUBDBG( "close on exec\t\t\t%u\n", tmp.flags );
417#endif
418
419 /* Start the per thread/process virtualized TSC */
420 error = vperfctr_control( ctx->perfctr, &tmp );
421 if ( error < 0 ) {
422 SUBDBG( "starting virtualized TSC; vperfctr_control returns %d\n",
423 error );
424 return PAPI_ESYS;
425 }
426
427 return PAPI_OK;
428}
429
430/* This routine is for shutting down threads, including the
431 master thread. */
432
433int
435{
436#ifdef DEBUG
437 int retval = vperfctr_unlink( ctx->perfctr );
438 SUBDBG( "_papi_hwd_shutdown vperfctr_unlink(%p) = %d\n", ctx->perfctr,
439 retval );
440#else
441 vperfctr_unlink( ctx->perfctr );
442#endif
443 vperfctr_close( ctx->perfctr );
444 SUBDBG( "_perfctr_shutdown vperfctr_close(%p)\n", ctx->perfctr );
445 memset( ctx, 0x0, sizeof ( hwd_context_t ) );
446 return ( PAPI_OK );
447}
double tmp
#define GET_OVERFLOW_ADDRESS(ctx)
Definition: aix-context.h:12
PAPI_os_info_t _papi_os_info
Definition: aix.c:1210
papi_os_vector_t _papi_os_vector
Definition: aix.c:1288
int close(int fd)
Definition: appio.c:179
int errno
struct papi_vectors * _papi_hwd[]
int _papi_hwi_dispatch_overflow_signal(void *papiContext, vptr_t address, int *isHardware, long long overflow_bit, int genOverflowBit, ThreadInfo_t **t, int cidx)
Definition: extras.c:216
#define PAPI_DOM_USER
Definition: f90papi.h:174
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_MIN_STR_LEN
Definition: f90papi.h:208
#define PAPI_VENDOR_IBM
Definition: f90papi.h:61
#define PAPI_VENDOR_UNKNOWN
Definition: f90papi.h:104
#define PAPI_DEFGRN
Definition: f90papi.h:26
#define PAPI_GRANUL
Definition: f90papi.h:179
#define PAPI_DOM_KERNEL
Definition: f90papi.h:254
#define PAPI_DETACH
Definition: f90papi.h:64
#define PAPI_DOM_SUPERVISOR
Definition: f90papi.h:109
#define PAPI_VENDOR_INTEL
Definition: f90papi.h:275
#define PAPI_VENDOR_AMD
Definition: f90papi.h:230
#define PAPI_ATTACH
Definition: f90papi.h:70
#define PAPI_EINVAL
Definition: f90papi.h:115
#define PAPI_ENOSUPP
Definition: f90papi.h:244
#define PAPI_MAX_STR_LEN
Definition: f90papi.h:77
#define PAPI_DOMAIN
Definition: f90papi.h:159
#define PAPI_DEF_MPX_NS
Definition: f90papi.h:235
#define PAPI_ESYS
Definition: f90papi.h:136
#define PAPI_ECMP
Definition: f90papi.h:214
#define PAPI_DEFDOM
Definition: f90papi.h:188
#define PAPI_GRN_THR
Definition: f90papi.h:265
#define PAPI_DEF_ITIMER
Definition: papi.h:462
#define PAPI_DEF_ITIMER_NS
Definition: papi.h:463
Return codes and api definitions.
void * vptr_t
Definition: papi.h:576
#define SUBDBG(format, args...)
Definition: papi_debug.h:64
__sighandler_t signal(int __sig, __sighandler_t __handler) __attribute__((__nothrow__
void PAPIERROR(char *format,...)
int _papi_libpfm_init(papi_vector_t *my_vector, int cidx)
static int cidx
int setup_ppc64_presets(int cputype)
static int set_domain(hwd_control_state_t *cntrl, unsigned int domain)
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:56
#define VOPEN_ERROR
Definition: perfctr-x86.h:62
#define VINFO_ERROR
Definition: perfctr-x86.h:64
#define RCNTRL_ERROR
Definition: perfctr-x86.h:66
papi_vector_t _perfctr_vector
Definition: perfctr-x86.c:1163
static int xlate_cpu_type_to_vendor(unsigned perfctr_cpu_type)
Definition: perfctr.c:55
static int attach(hwd_control_state_t *ctl, unsigned long tid)
Definition: perfctr.c:248
int _perfctr_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
Definition: perfctr.c:295
int _perfctr_init_thread(hwd_context_t *ctx)
Definition: perfctr.c:386
static int detach(hwd_control_state_t *ctl)
Definition: perfctr.c:277
#define GEN_OVERFLOW
#define PERFCTR_CPU_NAME
Definition: perfctr.c:49
#define PERFCTR_CPU_NRCTRS
Definition: perfctr.c:50
void _perfctr_dispatch_timer(int signal, siginfo_t *si, void *context)
Definition: perfctr.c:353
static int round_requested_ns(int ns)
Definition: perfctr.c:284
int _perfctr_init_component(int cidx)
Definition: perfctr.c:107
long long tb_scale_factor
Definition: perfctr.c:104
#define OVERFLOW_MASK
int _perfctr_shutdown_thread(hwd_context_t *ctx)
Definition: perfctr.c:434
int perfctr_ppc64_setup_native_table()
Definition: ppc64_events.c:73
if(file==NULL) goto out
int
Definition: sde_internal.h:89
long long int long long
Definition: sde_internal.h:85
hwd_control_state_t * ctl_state
unsigned int fast_virtual_timer
Definition: papi.h:657
int default_granularity
Definition: papi.h:644
unsigned int cntr_umasks
Definition: papi.h:660
unsigned int fast_counter_read
Definition: papi.h:655
int available_granularities
Definition: papi.h:645
char support_version[PAPI_MIN_STR_LEN]
Definition: papi.h:632
char kernel_version[PAPI_MIN_STR_LEN]
Definition: papi.h:633
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:627
unsigned int attach
Definition: papi.h:658
unsigned int attach_must_ptrace
Definition: papi.h:659
char disabled_reason[PAPI_HUGE_STR_LEN]
Definition: papi.h:634
char version[PAPI_MIN_STR_LEN]
Definition: papi.h:631
unsigned int fast_real_timer
Definition: papi.h:656
unsigned int hardware_intr
Definition: papi.h:650
char vendor_string[PAPI_MAX_STR_LEN]
Definition: papi.h:782
int model
Definition: papi.h:783
int vendor
Definition: papi.h:781
char model_string[PAPI_MAX_STR_LEN]
Definition: papi.h:784
hwd_context_t ** context
Definition: threads.h:28
hwd_siginfo_t * si
hwd_ucontext_t * ucontext
EventSetInfo_t * ESI
unsigned long tid
EventSetInfo_t * ESI
PAPI_hw_info_t hw_info
int(* get_system_info)(papi_mdi_t *mdi)
Definition: papi_vector.h:68
int(* get_memory_info)(PAPI_hw_info_t *, int)
Definition: papi_vector.h:69
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
_papi_int_domain_t domain
_papi_int_multiplex_t multiplex
_papi_int_attach_t attach
_papi_int_itimer_t itimer
int retval
Definition: zero_fork.c:53