Commit 6d395a51 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

libperf: Add a test case for read formats

It checks a various combination of the read format settings and verify
it return the value in a proper position.  The test uses task-clock
software events to guarantee it's always active and sets enabled/running
time.
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220819003644.508916-4-namhyung@kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 89e3106f
// SPDX-License-Identifier: GPL-2.0
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <linux/perf_event.h>
#include <linux/kernel.h>
#include <perf/cpumap.h>
#include <perf/threadmap.h>
#include <perf/evsel.h>
#include <internal/evsel.h>
#include <internal/tests.h>
#include "tests.h"
......@@ -189,6 +192,163 @@ static int test_stat_user_read(int event)
return 0;
}
static int test_stat_read_format_single(struct perf_event_attr *attr, struct perf_thread_map *threads)
{
struct perf_evsel *evsel;
struct perf_counts_values counts;
volatile int count = 0x100000;
int err;
evsel = perf_evsel__new(attr);
__T("failed to create evsel", evsel);
/* skip old kernels that don't support the format */
err = perf_evsel__open(evsel, NULL, threads);
if (err < 0)
return 0;
while (count--) ;
memset(&counts, -1, sizeof(counts));
perf_evsel__read(evsel, 0, 0, &counts);
__T("failed to read value", counts.val);
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
__T("failed to read TOTAL_TIME_ENABLED", counts.ena);
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
__T("failed to read TOTAL_TIME_RUNNING", counts.run);
if (attr->read_format & PERF_FORMAT_ID)
__T("failed to read ID", counts.id);
if (attr->read_format & PERF_FORMAT_LOST)
__T("failed to read LOST", counts.lost == 0);
perf_evsel__close(evsel);
perf_evsel__delete(evsel);
return 0;
}
static int test_stat_read_format_group(struct perf_event_attr *attr, struct perf_thread_map *threads)
{
struct perf_evsel *leader, *member;
struct perf_counts_values counts;
volatile int count = 0x100000;
int err;
attr->read_format |= PERF_FORMAT_GROUP;
leader = perf_evsel__new(attr);
__T("failed to create leader", leader);
attr->read_format &= ~PERF_FORMAT_GROUP;
member = perf_evsel__new(attr);
__T("failed to create member", member);
member->leader = leader;
leader->nr_members = 2;
/* skip old kernels that don't support the format */
err = perf_evsel__open(leader, NULL, threads);
if (err < 0)
return 0;
err = perf_evsel__open(member, NULL, threads);
if (err < 0)
return 0;
while (count--) ;
memset(&counts, -1, sizeof(counts));
perf_evsel__read(leader, 0, 0, &counts);
__T("failed to read leader value", counts.val);
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
__T("failed to read leader TOTAL_TIME_ENABLED", counts.ena);
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
__T("failed to read leader TOTAL_TIME_RUNNING", counts.run);
if (attr->read_format & PERF_FORMAT_ID)
__T("failed to read leader ID", counts.id);
if (attr->read_format & PERF_FORMAT_LOST)
__T("failed to read leader LOST", counts.lost == 0);
memset(&counts, -1, sizeof(counts));
perf_evsel__read(member, 0, 0, &counts);
__T("failed to read member value", counts.val);
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
__T("failed to read member TOTAL_TIME_ENABLED", counts.ena);
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
__T("failed to read member TOTAL_TIME_RUNNING", counts.run);
if (attr->read_format & PERF_FORMAT_ID)
__T("failed to read member ID", counts.id);
if (attr->read_format & PERF_FORMAT_LOST)
__T("failed to read member LOST", counts.lost == 0);
perf_evsel__close(member);
perf_evsel__close(leader);
perf_evsel__delete(member);
perf_evsel__delete(leader);
return 0;
}
static int test_stat_read_format(void)
{
struct perf_thread_map *threads;
struct perf_event_attr attr = {
.type = PERF_TYPE_SOFTWARE,
.config = PERF_COUNT_SW_TASK_CLOCK,
};
int err, i;
#define FMT(_fmt) PERF_FORMAT_ ## _fmt
#define FMT_TIME (FMT(TOTAL_TIME_ENABLED) | FMT(TOTAL_TIME_RUNNING))
uint64_t test_formats [] = {
0,
FMT_TIME,
FMT(ID),
FMT(LOST),
FMT_TIME | FMT(ID),
FMT_TIME | FMT(LOST),
FMT_TIME | FMT(ID) | FMT(LOST),
FMT(ID) | FMT(LOST),
};
#undef FMT
#undef FMT_TIME
threads = perf_thread_map__new_dummy();
__T("failed to create threads", threads);
perf_thread_map__set_pid(threads, 0, 0);
for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) {
attr.read_format = test_formats[i];
__T_VERBOSE("testing single read with read_format: %lx\n",
(unsigned long)test_formats[i]);
err = test_stat_read_format_single(&attr, threads);
__T("failed to read single format", err == 0);
}
perf_thread_map__put(threads);
threads = perf_thread_map__new_array(2, NULL);
__T("failed to create threads", threads);
perf_thread_map__set_pid(threads, 0, 0);
perf_thread_map__set_pid(threads, 1, 0);
for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) {
attr.read_format = test_formats[i];
__T_VERBOSE("testing group read with read_format: %lx\n",
(unsigned long)test_formats[i]);
err = test_stat_read_format_group(&attr, threads);
__T("failed to read group format", err == 0);
}
perf_thread_map__put(threads);
return 0;
}
int test_evsel(int argc, char **argv)
{
__T_START;
......@@ -200,6 +360,7 @@ int test_evsel(int argc, char **argv)
test_stat_thread_enable();
test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS);
test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES);
test_stat_read_format();
__T_END;
return tests_failed == 0 ? 0 : -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment