Create ltp-perf_event_open.m4 to determine whether struct perf_event_attr is
defined in <linux/perf_event.h>.

And according to perf_event_open()'s manpage, the official way of knowing
if perf_event_open() support is enabled is checking for the existence
of the file /proc/sys/kernel/perf_event_paranoid, so add this check.

According to this perf_event_open API description, rewrite this test
case to test hardware CPU events.
int perf_event_open(struct perf_event_attr *attr,
        pid_t pid, int cpu, int group_fd,
        unsigned long flags);

Some cleanup.

Signed-off-by: Xiaoguang Wang <[email protected]>
---
 configure.ac                                       |   1 +
 m4/ltp-perf_event_open.m4                          |  47 ++++++
 runtest/syscalls                                   |   2 +
 .../syscalls/perf_event_open/perf_event_open01.c   | 185 +++++++++++++++------
 4 files changed, 187 insertions(+), 48 deletions(-)
 create mode 100644 m4/ltp-perf_event_open.m4

diff --git a/configure.ac b/configure.ac
index 44016e7..161f41c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -175,5 +175,6 @@ LTP_CHECK_FCHOWNAT
 LTP_CHECK_MKNODAT
 LTP_CHECK_FALLOCATE
 LTP_CHECK_SYSCALL_FCNTL
+LTP_CHECK_SYSCALL_PERF_EVENT_OPEN
 
 AC_OUTPUT
diff --git a/m4/ltp-perf_event_open.m4 b/m4/ltp-perf_event_open.m4
new file mode 100644
index 0000000..a1084cf
--- /dev/null
+++ b/m4/ltp-perf_event_open.m4
@@ -0,0 +1,47 @@
+dnl
+dnl Copyright (c) 2014 Fujitsu Ltd.
+dnl Author: Xiaoguang Wang <[email protected]>
+dnl
+dnl This program is free software;  you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY;  without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+dnl the GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program;  if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
USA
+dnl
+
+dnl
+dnl LTP_CHECK_SYSCALL_PERF_EVENT_OPEN
+dnl ----------------------------
+dnl
+AC_DEFUN([LTP_CHECK_SYSCALL_PERF_EVENT_OPEN],[dnl
+       AC_MSG_CHECKING([for perf_event_open struct perf_event_attr])
+       save_CPPFLAGS=$CPPFLAGS
+       CPPFLAGS="$CPPFLAGS -I$srcdir/testcases/kernel/include 
-I$srcdir/include"
+       AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <linux/perf_event.h>
+#include "linux_syscall_numbers.h"
+int main(void) {
+       struct perf_event_attr pe;
+       syscall(__NR_perf_event_open, &pe, 0, -1, -1, 0);
+       return 0;
+}])],[has_perf_event_attr="yes"])
+
+
+if test "x$has_perf_event_attr" = xyes; then
+       AC_DEFINE(HAVE_PERF_EVENT_ATTR,1,[Define to 1 if you have struct 
perf_event_attr])
+       AC_MSG_RESULT(yes)
+else
+       AC_MSG_RESULT(no)
+fi
+CPPFLAGS=$save_CPPFLAGS
+])
diff --git a/runtest/syscalls b/runtest/syscalls
index fb3e59f..afbded3 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1352,3 +1352,5 @@ writev03 writev03
 writev04 writev04
 writev05 writev05
 writev06 writev06
+
+perf_event_open01 perf_event_open01
diff --git a/testcases/kernel/syscalls/perf_event_open/perf_event_open01.c 
b/testcases/kernel/syscalls/perf_event_open/perf_event_open01.c
index 6d7cbc9..5c870f6 100644
--- a/testcases/kernel/syscalls/perf_event_open/perf_event_open01.c
+++ b/testcases/kernel/syscalls/perf_event_open/perf_event_open01.c
@@ -22,13 +22,13 @@
  * Very simple performance counter testcase.
  * Picked up from: http://lkml.org/lkml/2008/12/5/17
  */
+
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/uio.h>
 #include <linux/unistd.h>
-
 #include <assert.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -36,73 +36,162 @@
 #include <string.h>
 #include <stdio.h>
 #include <fcntl.h>
+#include "config.h"
+#if HAVE_PERF_EVENT_ATTR
+#include <linux/perf_event.h>
+#endif
 
-/* Harness Specific Include Files. */
 #include "test.h"
 #include "usctest.h"
 #include "linux_syscall_numbers.h"
-
-/* Extern Global Variables */
-extern int tst_count;
-extern char *TESTDIR;          /* temporary dir created by tst_tmpdir() */
-/* Global Variables */
-char *TCID = "performance_counter01";  /* test program identifier.          */
-int TST_TOTAL = 1;
-
-enum hw_event_types {
-       PERF_COUNT_CYCLES,
-       PERF_COUNT_INSTRUCTIONS,
-       PERF_COUNT_CACHE_REFERENCES,
-       PERF_COUNT_CACHE_MISSES,
-       PERF_COUNT_BRANCH_INSTRUCTIONS,
-       PERF_COUNT_BRANCH_MISSES,
+#include "safe_macros.h"
+
+char *TCID = "performance_counter01";
+int TST_TOTAL = 6;
+
+#if HAVE_PERF_EVENT_ATTR
+static void setup(void);
+static void cleanup(void);
+
+static struct test_case_t {
+       const char *name;
+       unsigned long long val;
+} hw_event_types[] = {
+       { "PERF_COUNT_HW_CPU_CYCLES", PERF_COUNT_HW_CPU_CYCLES },
+       { "PERF_COUNT_HW_INSTRUCTIONS", PERF_COUNT_HW_INSTRUCTIONS },
+       { "PERF_COUNT_HW_CACHE_REFERENCES", PERF_COUNT_HW_CACHE_REFERENCES },
+       { "PERF_COUNT_HW_CACHE_MISSES", PERF_COUNT_HW_CACHE_MISSES },
+       { "PERF_COUNT_HW_BRANCH_INSTRUCTIONS",
+         PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
+       { "PERF_COUNT_HW_BRANCH_MISSES", PERF_COUNT_HW_BRANCH_MISSES },
 };
 
-void cleanup(void)
-{                              /* Stub function. */
+static void verify(struct test_case_t *tc);
+static struct perf_event_attr pe;
+
+int main(int ac, char **av)
+{
+       int i, lc;
+       char *msg;
+
+       msg = parse_opts(ac, av, NULL, NULL);
+       if (msg != NULL)
+               tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+
+       setup();
+
+       for (lc = 0; TEST_LOOPING(lc); lc++) {
+               tst_count = 0;
+
+               for (i = 0; i < TST_TOTAL; i++)
+                       verify(&hw_event_types[i]);
+       }
+
+       cleanup();
+       tst_exit();
 }
 
-int main(void)
+static void setup(void)
 {
+       /*
+        * According to perf_event_open's manpage, the official way of
+        * knowing if perf_event_open() support is enabled is checking for
+        * the existence of the file /proc/sys/kernel/perf_event_paranoid.
+        */
+       if (access("/proc/sys/kernel/perf_event_paranoid", F_OK) == -1)
+               tst_brkm(TCONF, NULL, "Kernel doesn't have perf_event support");
+
+       tst_sig(NOFORK, DEF_HANDLER, cleanup);
+
+       TEST_PAUSE;
+
+       pe.type = PERF_TYPE_HARDWARE;
+       pe.size = sizeof(struct perf_event_attr);
+       pe.disabled = 1;
+       pe.exclude_kernel = 1;
+       pe.exclude_hv = 1;
+}
+
+
+static int perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
+               int cpu, int group_fd, unsigned long flags)
+{
+       int ret;
+
+       ret = ltp_syscall(__NR_perf_event_open, hw_event, pid, cpu,
+                         group_fd, flags);
+       return ret;
+}
 
-       unsigned long long count1, count2;
-       int fd1, fd2, ret;
+/* do_work() is copied form performance_counter02.c */
+#define LOOPS  1000000000
 
-       fd1 = ltp_syscall(__NR_perf_event_open,
-                     PERF_COUNT_INSTRUCTIONS, 0, 0, 0, -1);
-       if (fd1 < 0) {
-               tst_brkm(TBROK | TERRNO, cleanup,
-                        "Failed to create PERF_COUNT_INSTRUCTIONS fd");
+static void do_work(void)
+{
+       int i;
+
+       for (i = 0; i < LOOPS; ++i)
+               asm volatile ("" : : "g" (i));
+}
+
+static void verify(struct test_case_t *tc)
+{
+       unsigned long long count;
+       int fd, ret;
+
+       pe.config = tc->val;
+
+       TEST(perf_event_open(&pe, 0, -1, -1, 0));
+       if (TEST_RETURN == -1) {
+               tst_brkm(TFAIL | TTERRNO, cleanup,
+                        "perf_event_open failed unexpectedly");
+               return;
        }
-       fd2 = ltp_syscall(__NR_perf_event_open,
-                     PERF_COUNT_CACHE_MISSES, 0, 0, 0, -1);
-       if (fd2 < 0) {
-               tst_brkm(TBROK | TERRNO, cleanup,
-                        "Failed to create PERF_COUNT_CACHE_MISSES fd");
+
+       fd = TEST_RETURN;
+
+       if (ioctl(fd, PERF_EVENT_IOC_RESET, 0) == -1) {
+               tst_brkm(TFAIL | TTERRNO, cleanup,
+                        "ioctl set PERF_EVENT_IOC_RESET failed");
        }
 
-       do {
+       if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0) == -1) {
+               tst_brkm(TFAIL | TTERRNO, cleanup,
+                        "ioctl set PERF_EVENT_IOC_ENABLE failed");
+       }
 
-               ret = read(fd1, &count1, sizeof(count1));
+       do_work();
 
-               if (ret == sizeof(count1)) {
+       if (ioctl(fd, PERF_EVENT_IOC_DISABLE, 0) == -1) {
+               tst_brkm(TFAIL | TTERRNO, cleanup,
+                        "ioctl set PERF_EVENT_IOC_RESET failed");
+       }
 
-                       ret = read(fd2, &count2, sizeof(count2));
+       ret = read(fd, &count, sizeof(count));
+       if (ret == sizeof(count)) {
+               tst_resm(TINFO, "read event counter succeeded, "
+                        "value: %llu", count);
+               tst_resm(TPASS, "test PERF_TYPE_HARDWARE: %s succeeded",
+                        tc->name);
+       } else {
+               tst_resm(TFAIL | TERRNO, "read event counter failed");
+       }
 
-                       if (ret == sizeof(count2)) {
-                               tst_resm(TINFO,
-                                        "counter1 value: %Ld instructions",
-                                        count1);
-                               tst_resm(TINFO,
-                                        "counter2 value: %Ld cachemisses",
-                                        count2);
-                               sleep(1);
-                       }
+       SAFE_CLOSE(cleanup, fd);
 
-               }
+}
 
-       } while (ret == sizeof(unsigned long long));
+static void cleanup(void)
+{
+       TEST_CLEANUP;
+}
 
-       tst_exit();
+#else
 
+int main(void)
+{
+       tst_brkm(TCONF, NULL, "This system doesn't have "
+                "header file:<linux/perf_event.h> or "
+                "no struct perf_event_attr defined");
 }
+#endif
-- 
1.8.2.1


------------------------------------------------------------------------------
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test & Deployment 
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to