Skip to content

Commit

Permalink
perf tests: Add 'keep tracking' test
Browse files Browse the repository at this point in the history
Add a test for the newly added PERF_COUNT_SW_DUMMY event.  The test
checks that tracking events continue when an event is disabled but a
dummy software event is not disabled.

Signed-off-by: Adrian Hunter <[email protected]>
Acked-by: Jiri Olsa <[email protected]>
Tested-by: Jiri Olsa <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
  • Loading branch information
ahunter6 authored and acmel committed Sep 2, 2013
1 parent d22d1a2 commit 395c307
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 2 deletions.
1 change: 1 addition & 0 deletions tools/perf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ endif # NO_LIBELF
ifndef NO_LIBUNWIND
LIB_OBJS += $(OUTPUT)util/unwind.o
endif
LIB_OBJS += $(OUTPUT)tests/keep-tracking.o

ifndef NO_LIBAUDIT
BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
Expand Down
4 changes: 4 additions & 0 deletions tools/perf/tests/builtin-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ static struct test {
.desc = "Test sample parsing",
.func = test__sample_parsing,
},
{
.desc = "Test using a dummy software event to keep tracking",
.func = test__keep_tracking,
},
{
.func = NULL,
},
Expand Down
154 changes: 154 additions & 0 deletions tools/perf/tests/keep-tracking.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#include <sys/types.h>
#include <unistd.h>
#include <sys/prctl.h>

#include "parse-events.h"
#include "evlist.h"
#include "evsel.h"
#include "thread_map.h"
#include "cpumap.h"
#include "tests.h"

#define CHECK__(x) { \
while ((x) < 0) { \
pr_debug(#x " failed!\n"); \
goto out_err; \
} \
}

#define CHECK_NOT_NULL__(x) { \
while ((x) == NULL) { \
pr_debug(#x " failed!\n"); \
goto out_err; \
} \
}

static int find_comm(struct perf_evlist *evlist, const char *comm)
{
union perf_event *event;
int i, found;

found = 0;
for (i = 0; i < evlist->nr_mmaps; i++) {
while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
if (event->header.type == PERF_RECORD_COMM &&
(pid_t)event->comm.pid == getpid() &&
(pid_t)event->comm.tid == getpid() &&
strcmp(event->comm.comm, comm) == 0)
found += 1;
}
}
return found;
}

/**
* test__keep_tracking - test using a dummy software event to keep tracking.
*
* This function implements a test that checks that tracking events continue
* when an event is disabled but a dummy software event is not disabled. If the
* test passes %0 is returned, otherwise %-1 is returned.
*/
int test__keep_tracking(void)
{
struct perf_record_opts opts = {
.mmap_pages = UINT_MAX,
.user_freq = UINT_MAX,
.user_interval = ULLONG_MAX,
.freq = 4000,
.target = {
.uses_mmap = true,
},
};
struct thread_map *threads = NULL;
struct cpu_map *cpus = NULL;
struct perf_evlist *evlist = NULL;
struct perf_evsel *evsel = NULL;
int found, err = -1;
const char *comm;

threads = thread_map__new(-1, getpid(), UINT_MAX);
CHECK_NOT_NULL__(threads);

cpus = cpu_map__new(NULL);
CHECK_NOT_NULL__(cpus);

evlist = perf_evlist__new();
CHECK_NOT_NULL__(evlist);

perf_evlist__set_maps(evlist, cpus, threads);

CHECK__(parse_events(evlist, "dummy:u"));
CHECK__(parse_events(evlist, "cycles:u"));

perf_evlist__config(evlist, &opts);

evsel = perf_evlist__first(evlist);

evsel->attr.comm = 1;
evsel->attr.disabled = 1;
evsel->attr.enable_on_exec = 0;

if (perf_evlist__open(evlist) < 0) {
fprintf(stderr, " (not supported)");
err = 0;
goto out_err;
}

CHECK__(perf_evlist__mmap(evlist, UINT_MAX, false));

/*
* First, test that a 'comm' event can be found when the event is
* enabled.
*/

perf_evlist__enable(evlist);

comm = "Test COMM 1";
CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0));

perf_evlist__disable(evlist);

found = find_comm(evlist, comm);
if (found != 1) {
pr_debug("First time, failed to find tracking event.\n");
goto out_err;
}

/*
* Secondly, test that a 'comm' event can be found when the event is
* disabled with the dummy event still enabled.
*/

perf_evlist__enable(evlist);

evsel = perf_evlist__last(evlist);

CHECK__(perf_evlist__disable_event(evlist, evsel));

comm = "Test COMM 2";
CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0));

perf_evlist__disable(evlist);

found = find_comm(evlist, comm);
if (found != 1) {
pr_debug("Seconf time, failed to find tracking event.\n");
goto out_err;
}

err = 0;

out_err:
if (evlist) {
perf_evlist__disable(evlist);
perf_evlist__munmap(evlist);
perf_evlist__close(evlist);
perf_evlist__delete(evlist);
}
if (cpus)
cpu_map__delete(cpus);
if (threads)
thread_map__delete(threads);

return err;
}
1 change: 1 addition & 0 deletions tools/perf/tests/tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@ int test__sw_clock_freq(void);
int test__perf_time_to_tsc(void);
int test__code_reading(void);
int test__sample_parsing(void);
int test__keep_tracking(void);

#endif /* TESTS_H */
42 changes: 40 additions & 2 deletions tools/perf/util/evlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)

for (cpu = 0; cpu < nr_cpus; cpu++) {
list_for_each_entry(pos, &evlist->entries, node) {
if (!perf_evsel__is_group_leader(pos))
if (!perf_evsel__is_group_leader(pos) || !pos->fd)
continue;
for (thread = 0; thread < nr_threads; thread++)
ioctl(FD(pos, cpu, thread),
Expand All @@ -264,7 +264,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)

for (cpu = 0; cpu < nr_cpus; cpu++) {
list_for_each_entry(pos, &evlist->entries, node) {
if (!perf_evsel__is_group_leader(pos))
if (!perf_evsel__is_group_leader(pos) || !pos->fd)
continue;
for (thread = 0; thread < nr_threads; thread++)
ioctl(FD(pos, cpu, thread),
Expand All @@ -273,6 +273,44 @@ void perf_evlist__enable(struct perf_evlist *evlist)
}
}

int perf_evlist__disable_event(struct perf_evlist *evlist,
struct perf_evsel *evsel)
{
int cpu, thread, err;

if (!evsel->fd)
return 0;

for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
for (thread = 0; thread < evlist->threads->nr; thread++) {
err = ioctl(FD(evsel, cpu, thread),
PERF_EVENT_IOC_DISABLE, 0);
if (err)
return err;
}
}
return 0;
}

int perf_evlist__enable_event(struct perf_evlist *evlist,
struct perf_evsel *evsel)
{
int cpu, thread, err;

if (!evsel->fd)
return -EINVAL;

for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
for (thread = 0; thread < evlist->threads->nr; thread++) {
err = ioctl(FD(evsel, cpu, thread),
PERF_EVENT_IOC_ENABLE, 0);
if (err)
return err;
}
}
return 0;
}

static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
{
int nr_cpus = cpu_map__nr(evlist->cpus);
Expand Down
5 changes: 5 additions & 0 deletions tools/perf/util/evlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ void perf_evlist__munmap(struct perf_evlist *evlist);
void perf_evlist__disable(struct perf_evlist *evlist);
void perf_evlist__enable(struct perf_evlist *evlist);

int perf_evlist__disable_event(struct perf_evlist *evlist,
struct perf_evsel *evsel);
int perf_evlist__enable_event(struct perf_evlist *evlist,
struct perf_evsel *evsel);

void perf_evlist__set_selected(struct perf_evlist *evlist,
struct perf_evsel *evsel);

Expand Down

0 comments on commit 395c307

Please sign in to comment.