Skip to content

Commit

Permalink
libperf: Add a test case for read formats
Browse files Browse the repository at this point in the history
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: Namhyung Kim <[email protected]>
Acked-by: Jiri Olsa <[email protected]>
Cc: Ian Rogers <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
  • Loading branch information
namhyung authored and acmel committed Aug 19, 2022
1 parent 89e3106 commit 6d395a5
Showing 1 changed file with 161 additions and 0 deletions.
161 changes: 161 additions & 0 deletions tools/lib/perf/tests/test-evsel.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// 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"

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit 6d395a5

Please sign in to comment.