Linux Perf
sw-clock.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0
2 #include <errno.h>
3 #include <inttypes.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <signal.h>
7 #include <sys/mman.h>
8 
9 #include "tests.h"
10 #include "util/evsel.h"
11 #include "util/evlist.h"
12 #include "util/cpumap.h"
13 #include "util/thread_map.h"
14 
15 #define NR_LOOPS 10000000
16 
17 /*
18  * This test will open software clock events (cpu-clock, task-clock)
19  * then check their frequency -> period conversion has no artifact of
20  * setting period to 1 forcefully.
21  */
22 static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
23 {
24  int i, err = -1;
25  volatile int tmp = 0;
26  u64 total_periods = 0;
27  int nr_samples = 0;
28  char sbuf[STRERR_BUFSIZE];
29  union perf_event *event;
30  struct perf_evsel *evsel;
31  struct perf_evlist *evlist;
32  struct perf_event_attr attr = {
33  .type = PERF_TYPE_SOFTWARE,
34  .config = clock_id,
35  .sample_type = PERF_SAMPLE_PERIOD,
36  .exclude_kernel = 1,
37  .disabled = 1,
38  .freq = 1,
39  };
40  struct cpu_map *cpus;
41  struct thread_map *threads;
42  struct perf_mmap *md;
43 
44  attr.sample_freq = 500;
45 
46  evlist = perf_evlist__new();
47  if (evlist == NULL) {
48  pr_debug("perf_evlist__new\n");
49  return -1;
50  }
51 
52  evsel = perf_evsel__new(&attr);
53  if (evsel == NULL) {
54  pr_debug("perf_evsel__new\n");
55  goto out_delete_evlist;
56  }
57  perf_evlist__add(evlist, evsel);
58 
59  cpus = cpu_map__dummy_new();
60  threads = thread_map__new_by_tid(getpid());
61  if (!cpus || !threads) {
62  err = -ENOMEM;
63  pr_debug("Not enough memory to create thread/cpu maps\n");
64  goto out_free_maps;
65  }
66 
67  perf_evlist__set_maps(evlist, cpus, threads);
68 
69  cpus = NULL;
70  threads = NULL;
71 
72  if (perf_evlist__open(evlist)) {
73  const char *knob = "/proc/sys/kernel/perf_event_max_sample_rate";
74 
75  err = -errno;
76  pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n",
77  str_error_r(errno, sbuf, sizeof(sbuf)),
78  knob, (u64)attr.sample_freq);
79  goto out_delete_evlist;
80  }
81 
82  err = perf_evlist__mmap(evlist, 128);
83  if (err < 0) {
84  pr_debug("failed to mmap event: %d (%s)\n", errno,
85  str_error_r(errno, sbuf, sizeof(sbuf)));
86  goto out_delete_evlist;
87  }
88 
89  perf_evlist__enable(evlist);
90 
91  /* collect samples */
92  for (i = 0; i < NR_LOOPS; i++)
93  tmp++;
94 
95  perf_evlist__disable(evlist);
96 
97  md = &evlist->mmap[0];
98  if (perf_mmap__read_init(md) < 0)
99  goto out_init;
100 
101  while ((event = perf_mmap__read_event(md)) != NULL) {
102  struct perf_sample sample;
103 
104  if (event->header.type != PERF_RECORD_SAMPLE)
105  goto next_event;
106 
107  err = perf_evlist__parse_sample(evlist, event, &sample);
108  if (err < 0) {
109  pr_debug("Error during parse sample\n");
110  goto out_delete_evlist;
111  }
112 
113  total_periods += sample.period;
114  nr_samples++;
115 next_event:
116  perf_mmap__consume(md);
117  }
119 
120 out_init:
121  if ((u64) nr_samples == total_periods) {
122  pr_debug("All (%d) samples have period value of 1!\n",
123  nr_samples);
124  err = -1;
125  }
126 
127 out_free_maps:
128  cpu_map__put(cpus);
129  thread_map__put(threads);
130 out_delete_evlist:
131  perf_evlist__delete(evlist);
132  return err;
133 }
134 
135 int test__sw_clock_freq(struct test *test __maybe_unused, int subtest __maybe_unused)
136 {
137  int ret;
138 
139  ret = __test__sw_clock_freq(PERF_COUNT_SW_CPU_CLOCK);
140  if (!ret)
141  ret = __test__sw_clock_freq(PERF_COUNT_SW_TASK_CLOCK);
142 
143  return ret;
144 }
void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus, struct thread_map *threads)
Definition: evlist.c:1115
void perf_mmap__consume(struct perf_mmap *map)
Definition: mmap.c:118
struct perf_mmap * mmap
Definition: evlist.h:45
struct cpu_map * cpu_map__dummy_new(void)
Definition: cpumap.c:252
void perf_evlist__enable(struct perf_evlist *evlist)
Definition: evlist.c:369
int int err
Definition: 5sec.c:44
void perf_evlist__delete(struct perf_evlist *evlist)
Definition: evlist.c:133
Definition: cpumap.h:12
Definition: mmap.h:17
struct thread_map * thread_map__new_by_tid(pid_t tid)
Definition: thread_map.c:83
int test__sw_clock_freq(struct test *test __maybe_unused, int subtest __maybe_unused)
Definition: sw-clock.c:135
void cpu_map__put(struct cpu_map *map)
Definition: cpumap.c:298
int perf_mmap__read_init(struct perf_mmap *map)
Definition: mmap.c:271
#define pr_debug(fmt,...)
Definition: json.h:27
int perf_evlist__open(struct perf_evlist *evlist)
Definition: evlist.c:1398
int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, struct perf_sample *sample)
Definition: evlist.c:1561
u64 period
Definition: event.h:198
list cpus
Definition: stat-cpi.py:7
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
Definition: evlist.c:176
#define event
int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages)
Definition: evlist.c:1061
static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
Definition: sw-clock.c:22
static struct thread_data threads[THREADS]
static struct perf_evsel * perf_evsel__new(struct perf_event_attr *attr)
Definition: evsel.h:197
void perf_mmap__read_done(struct perf_mmap *map)
Definition: mmap.c:329
struct perf_event_header header
Definition: event.h:624
union perf_event * perf_mmap__read_event(struct perf_mmap *map)
Definition: mmap.c:78
void perf_evlist__disable(struct perf_evlist *evlist)
Definition: evlist.c:356
Definition: tests.h:30
#define STRERR_BUFSIZE
Definition: debug.h:43
void thread_map__put(struct thread_map *map)
Definition: thread_map.c:361
struct perf_evlist * perf_evlist__new(void)
Definition: evlist.c:54
#define NR_LOOPS
Definition: sw-clock.c:15