hi,
the perf test patch below is not to be merged. It's
just to show how to hit issue fixed by patch 1/1.

thanks,
jirka


Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
---
 tools/perf/Makefile.perf          |   1 +
 tools/perf/tests/builtin-test.c   |   4 +
 tools/perf/tests/group-read-bug.c | 169 ++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/tests.h          |   1 +
 4 files changed, 175 insertions(+)
 create mode 100644 tools/perf/tests/group-read-bug.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 9670a16..909084f 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -419,6 +419,7 @@ endif
 endif
 LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
 LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
+LIB_OBJS += $(OUTPUT)tests/group-read-bug.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 6f8b01b..2b2d544 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -154,6 +154,10 @@ static struct test {
                .func = test__hists_cumulate,
        },
        {
+               .desc = "Test group read bug",
+               .func = test__group_read_bug,
+       },
+       {
                .func = NULL,
        },
 };
diff --git a/tools/perf/tests/group-read-bug.c 
b/tools/perf/tests/group-read-bug.c
new file mode 100644
index 0000000..d69fabf
--- /dev/null
+++ b/tools/perf/tests/group-read-bug.c
@@ -0,0 +1,169 @@
+#include <unistd.h>
+#include <sys/syscall.h>   /* For SYS_xxx definitions */
+#include <linux/perf_event.h>
+#include <linux/hw_breakpoint.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <pthread.h>
+#include "tests.h"
+#include "perf.h"
+#include "debug.h"
+#include "trace-event.h"
+
+static int fd_leader;
+static bool done;
+static int pid;
+
+static int create_event(int group_fd)
+{
+       struct perf_event_attr pe;
+       struct event_format* format;
+       int fd;
+
+       memset(&pe, 0, sizeof(struct perf_event_attr));
+       pe.type = PERF_TYPE_TRACEPOINT;
+       pe.size = sizeof(struct perf_event_attr);
+
+       format = trace_event__tp_format("syscalls", "sys_enter_read");
+       if (!format)
+               return TEST_FAIL;
+
+       pe.config = format->id;
+       pe.sample_period = 1;
+       pe.sample_type = PERF_SAMPLE_ID|PERF_SAMPLE_READ;
+       pe.read_format = PERF_FORMAT_ID|PERF_FORMAT_GROUP;
+
+       if (group_fd == -1)
+               pe.disabled = 1;
+
+       fd = sys_perf_event_open(&pe, pid, -1, group_fd, 0);
+       if (fd < 0) {
+               pr_debug("failed opening event %llx, errno %d\n",
+                        pe.config, errno);
+               return TEST_FAIL;
+       }
+
+       return fd;
+}
+
+static __u64 read_head(struct perf_event_mmap_page *pc)
+{
+       __u64 head = ACCESS_ONCE(pc->data_head);
+       rmb();
+       return head;
+}
+
+static void write_tail(struct perf_event_mmap_page *pc, __u64 tail)
+{
+       mb();
+       pc->data_tail = tail;
+}
+
+static void mmap_read(struct perf_event_mmap_page *pc, int mask)
+{
+       __u64 old = 0;
+       __u64 empty = 0;
+
+       while (!done) {
+               __u64 size, head;
+
+               head = read_head(pc);
+
+               if (old == head) {
+                       empty++;
+                       continue;
+               }
+
+               size = head - old;
+
+               pr_debug("empty %llu, head = %llu, size %llu\n", empty, head, 
size);
+               empty = 0;
+
+               if ((old & mask) + size != (head & mask)) {
+                       size = mask + 1 - (old & mask);
+                       old += size;
+               }
+
+               size = head - old;
+               old += size;
+               write_tail(pc, old);
+       }
+}
+
+static void *worker_thread(void *data __maybe_unused)
+{
+#define CNT 1000
+       int fds[CNT];
+
+       while (!done) {
+               int i;
+
+               for (i = 0; i < CNT; i++)
+                       fds[i] = create_event(fd_leader);
+
+               for (i = 0; i < CNT; i++)
+                       close(fds[i]);
+       }
+
+       return NULL;
+}
+
+static void *gen_thread(void *data __maybe_unused)
+{
+       pid = syscall(SYS_gettid);
+
+       while (!done) {
+               int i;
+
+               i = read(300, &i, sizeof(i));
+       }
+
+       return NULL;
+}
+
+static void signal_fn(int signo __maybe_unused)
+{
+       done = 1;
+}
+
+int test__group_read_bug(void)
+{
+       pthread_t pthread, pthread_gen;
+       int mmap_len  = page_size + (page_size  << 5);
+       int mmap_mask = mmap_len - page_size - 1;
+       void *buf;
+       int err;
+
+       signal(SIGINT,  signal_fn);
+
+       err = pthread_create(&pthread, NULL, gen_thread, NULL);
+       TEST_ASSERT_VAL("create gen", !err);
+
+       while(!pid) {
+               pr_debug("waiting for pid\n");
+               sleep(1);
+       }
+
+       fd_leader = create_event(-1);
+       TEST_ASSERT_VAL("create a leader", fd_leader >= 0);
+
+       buf = mmap(NULL, mmap_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd_leader, 
0);
+       TEST_ASSERT_VAL("mmap leader", buf != MAP_FAILED);
+
+       err = ioctl(fd_leader, PERF_EVENT_IOC_ENABLE, 0);
+       TEST_ASSERT_VAL("enable leader", !err);
+
+       err = pthread_create(&pthread_gen, NULL, worker_thread, NULL);
+       TEST_ASSERT_VAL("create worker", !err);
+
+       mmap_read(buf, mmap_mask);
+
+       munmap(buf, mmap_len);
+       close(fd_leader);
+
+       pthread_join(pthread, NULL);
+       pthread_join(pthread_gen, NULL);
+       return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index ed64790..af43c47 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -48,6 +48,7 @@ int test__mmap_thread_lookup(void);
 int test__thread_mg_share(void);
 int test__hists_output(void);
 int test__hists_cumulate(void);
+int test__group_read_bug(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to