File: perfctr.ch

package info (click to toggle)
ucl 1.03%2Brepack-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 4,308 kB
  • ctags: 10,088
  • sloc: sh: 11,733; asm: 10,461; ansic: 5,067; makefile: 112
file content (157 lines) | stat: -rw-r--r-- 4,109 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* ACC -- Automatic Compiler Configuration

   Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer
   All Rights Reserved.

   This software is a copyrighted work licensed under the terms of
   the GNU General Public License. Please consult the file "ACC_LICENSE"
   for details.

   Markus F.X.J. Oberhumer
   <markus@oberhumer.com>
   http://www.oberhumer.com/
 */


#define __ACCLIB_PERFCTR_CH_INCLUDED 1
#if !defined(ACCLIB_PUBLIC)
#  define ACCLIB_PUBLIC(r,f)    r __ACCLIB_FUNCNAME(f)
#endif


#if (ACC_OS_POSIX_LINUX)
/* see http://user.it.uu.se/~mikpe/linux/perfctr/ */
#if defined(__cplusplus)
extern "C" {
#include <libperfctr.h>
}
#else
#include <libperfctr.h>
#endif
#endif


/*************************************************************************
//
**************************************************************************/

ACCLIB_PUBLIC(int, acc_perfctr_open) (acc_perfctr_handle_p h)
{
    memset(h, 0, sizeof(*h));
#if (ACC_OS_POSIX_LINUX)
    {
    struct vperfctr* handle;
    struct perfctr_info info;
    struct vperfctr_control control;
    struct perfctr_cpu_control* const cc = &control.cpu_control;
    /* open */
    handle = vperfctr_open();
    if (!handle) goto error;
    /* get info */
    if (vperfctr_info(handle, &info) < 0) goto error;
    h->cpu_type = info.cpu_type;
    h->cpu_features = info.cpu_features;
    h->cpu_khz = info.cpu_khz;
    h->cpu_nrctrs = perfctr_info_nrctrs(&info);
    h->cpu_name = perfctr_info_cpu_name(&info);
    /* setup control */
    memset(&control, 0, sizeof(control));
    switch (h->cpu_type) {
#if (ACC_ARCH_IA32)
    case PERFCTR_X86_WINCHIP_C6:
    case PERFCTR_X86_WINCHIP_2:
        break;      /* no working TSC available */
    case PERFCTR_X86_AMD_K7:
#endif
#if (ACC_ARCH_AMD64 || ACC_ARCH_IA32)
    case PERFCTR_X86_AMD_K8:
    case PERFCTR_X86_AMD_K8C:
        cc->tsc_on = 1; cc->nractrs = 2;
        /* event 0xC0 (RETIRED_INSNS), count at CPL > 0, Enable */
        cc->pmc_map[0] = 0;
        cc->evntsel[0] = 0xC0 | (1 << 16) | (1 << 22);
        /* event 0xC1 (RETIRED_OPS), count at CPL > 0, Enable */
        cc->pmc_map[1] = 1;
        cc->evntsel[1] = 0xC1 | (1 << 16) | (1 << 22);
        break;
#endif
    default:
        cc->tsc_on = 1;
        break;
    }
    if (cc->nractrs > h->cpu_nrctrs) cc->nractrs = h->cpu_nrctrs;
    if (vperfctr_control(handle, &control) < 0) goto error;
    /* success */
    h->h = (void*) handle;
    return 0;
error:
    if (handle) {
        vperfctr_stop(handle);
        vperfctr_close(handle);
    }
    }
#endif
    return -1;
}


ACCLIB_PUBLIC(int, acc_perfctr_close) (acc_perfctr_handle_p h)
{
    if (h->h) {
#if (ACC_OS_POSIX_LINUX)
        struct vperfctr* handle = (struct vperfctr*) h->h;
        vperfctr_stop(handle);
        vperfctr_close(handle);
#endif
        h->h = 0;
    }
    return 0;
}


/*************************************************************************
//
**************************************************************************/

ACCLIB_PUBLIC(void, acc_perfctr_read) (acc_perfctr_handle_p h, acc_perfctr_clock_p c)
{
    if (h->h) {
#if (ACC_OS_POSIX_LINUX)
        struct vperfctr* handle = (struct vperfctr*) h->h;
        vperfctr_read_ctrs(handle, (struct perfctr_sum_ctrs*) c);
#else
        memset(c, 0, sizeof(*c));
#endif
    } else
        memset(c, 0, sizeof(*c));
}


/*************************************************************************
//
**************************************************************************/

ACCLIB_PUBLIC(double, acc_perfctr_get_elapsed) (acc_perfctr_handle_p h, const acc_perfctr_clock_p start, const acc_perfctr_clock_p stop)
{
#if (ACC_OS_POSIX_LINUX)
    acc_uint64l_t tsc = stop->tsc - start->tsc;
    return ((double)tsc / h->cpu_khz) / 1000.0;
#else
    ACC_UNUSED(h); ACC_UNUSED(start); ACC_UNUSED(stop); return 0;
#endif
}


ACCLIB_PUBLIC(double, acc_perfctr_get_elapsed_tsc) (acc_perfctr_handle_p h, acc_uint64l_t tsc)
{
#if (ACC_OS_POSIX_LINUX)
    return ((double)tsc / h->cpu_khz) / 1000.0;
#else
    ACC_UNUSED(h); ACC_UNUSED(tsc); return 0;
#endif
}


/*
vi:ts=4:et
*/