Module: xenomai-3
Branch: next
Commit: d6cc09786459a61cb9bc3a9f44e2d58036a1d347
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=d6cc09786459a61cb9bc3a9f44e2d58036a1d347

Author: Jan Kiszka <jan.kis...@siemens.com>
Date:   Fri Dec 12 13:46:24 2014 +0100

smokey/sigdebug: Port from 2.6

This integrates the 2.6 testcase for validating the SIGDEBUG support to
forge, taking interface changes into account, switching from native to
POSIX and adding a test for the lock-break instrumentation. The latter
is currently broken and will only succeed after the related fix is
applied.

Signed-off-by: Jan Kiszka <jan.kis...@siemens.com>

---

 configure.ac                          |    1 +
 testsuite/smokey/Makefile.am          |    6 +-
 testsuite/smokey/sigdebug/Makefile.am |   10 ++
 testsuite/smokey/sigdebug/sigdebug.c  |  303 +++++++++++++++++++++++++++++++++
 4 files changed, 318 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index fe647e4..2d4d61d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -924,6 +924,7 @@ AC_CONFIG_FILES([ \
        testsuite/smokey/iddp/Makefile \
        testsuite/smokey/bufp/Makefile \
        testsuite/smokey/fork-exec/Makefile \
+       testsuite/smokey/sigdebug/Makefile \
        testsuite/clocktest/Makefile \
        testsuite/xeno-test/Makefile \
        testsuite/regression/Makefile \
diff --git a/testsuite/smokey/Makefile.am b/testsuite/smokey/Makefile.am
index 449a69a..9ee9cf0 100644
--- a/testsuite/smokey/Makefile.am
+++ b/testsuite/smokey/Makefile.am
@@ -20,7 +20,8 @@ SUBDIRS =             \
        sched-quota     \
        sched-tp        \
        vdso-access     \
-       xddp
+       xddp            \
+       sigdebug
 else
 SUBDIRS =
 wrappers =
@@ -59,4 +60,5 @@ DIST_SUBDIRS =                \
        sched-quota     \
        sched-tp        \
        vdso-access     \
-       xddp
+       xddp            \
+       sigdebug
diff --git a/testsuite/smokey/sigdebug/Makefile.am 
b/testsuite/smokey/sigdebug/Makefile.am
new file mode 100644
index 0000000..06b976d
--- /dev/null
+++ b/testsuite/smokey/sigdebug/Makefile.am
@@ -0,0 +1,10 @@
+
+noinst_LIBRARIES = libsigdebug.a
+
+libsigdebug_a_SOURCES = sigdebug.c
+
+CCLD = $(top_srcdir)/scripts/wrap-link.sh $(CC)
+
+libsigdebug_a_CPPFLAGS =               \
+       @XENO_USER_CFLAGS@      \
+       -I$(top_srcdir)/include
diff --git a/testsuite/smokey/sigdebug/sigdebug.c 
b/testsuite/smokey/sigdebug/sigdebug.c
new file mode 100644
index 0000000..03f3d33
--- /dev/null
+++ b/testsuite/smokey/sigdebug/sigdebug.c
@@ -0,0 +1,303 @@
+/*
+ * Functional testing of unwanted domain switch debugging mechanism.
+ *
+ * Copyright (C) Siemens AG, 2012-2014
+ *
+ * Authors:
+ *  Jan Kiszka  <jan.kis...@siemens.com>
+ *
+ * Released under the terms of GPLv2.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <asm/unistd.h>
+#include <smokey/smokey.h>
+
+smokey_test_plugin(sigdebug,
+                  SMOKEY_NOARGS,
+                  "Check SIGDEBUG reporting."
+);
+
+unsigned int expected_reason;
+bool sigdebug_received;
+pthread_mutex_t prio_invert;
+sem_t send_signal;
+char *mem;
+FILE *wd;
+
+static void setup_checkdebug(unsigned int reason)
+{
+       sigdebug_received = false;
+       expected_reason = reason;
+}
+
+static void check_inner(const char *fn, int line, const char *msg,
+                       int status, int expected)
+{
+       if (status == expected)
+               return;
+
+       pthread_setmode_np(PTHREAD_WARNSW, 0, NULL);
+       rt_print_flush_buffers();
+       fprintf(stderr, "FAILURE %s:%d: %s returned %d instead of %d - %s\n",
+               fn, line, msg, status, expected, strerror(-status));
+       exit(EXIT_FAILURE);
+}
+
+static void check_sigdebug_inner(const char *fn, int line, const char *reason)
+{
+       if (sigdebug_received)
+               return;
+
+       pthread_setmode_np(PTHREAD_WARNSW, 0, NULL);
+       rt_print_flush_buffers();
+       fprintf(stderr, "FAILURE %s:%d: no %s received\n", fn, line, reason);
+       exit(EXIT_FAILURE);
+}
+
+#define check(msg, status, expected) ({                                        
\
+       int __status = status;                                          \
+       check_inner(__FUNCTION__, __LINE__, msg, __status, expected);   \
+       __status;                                                       \
+})
+
+#define check_no_error(msg, status) ({                                 \
+       int __status = status;                                          \
+       check_inner(__FUNCTION__, __LINE__, msg,                        \
+                   __status < 0 ? __status : 0, 0);                    \
+       __status;                                                       \
+})
+
+#define check_sigdebug_received(reason) do {                           \
+       const char *__reason = reason;                                  \
+       check_sigdebug_inner(__FUNCTION__, __LINE__, __reason);         \
+} while (0)
+
+static void *rt_thread_body(void *cookie)
+{
+       struct timespec now, delay = {.tv_sec = 0, .tv_nsec = 10000000LL};
+       unsigned long long end;
+       int err;
+
+       err = pthread_setmode_np(0, PTHREAD_WARNSW, NULL);
+       check_no_error("pthread_setmode_np", err);
+
+       printf("syscall\n");
+       setup_checkdebug(SIGDEBUG_MIGRATE_SYSCALL);
+       syscall(__NR_gettid);
+       check_sigdebug_received("SIGDEBUG_MIGRATE_SYSCALL");
+
+       printf("signal\n");
+       setup_checkdebug(SIGDEBUG_MIGRATE_SIGNAL);
+       err = sem_post(&send_signal);
+       check_no_error("sem_post", err);
+       err = clock_nanosleep(CLOCK_MONOTONIC, 0, &delay, NULL);
+       check_no_error("clock_nanosleep", err);
+       check_sigdebug_received("SIGDEBUG_MIGRATE_SIGNAL");
+
+       printf("relaxed mutex owner\n");
+       setup_checkdebug(SIGDEBUG_MIGRATE_PRIOINV);
+       err = pthread_mutex_lock(&prio_invert);
+       check_no_error("pthread_mutex_lock", err);
+       check_sigdebug_received("SIGDEBUG_MIGRATE_PRIOINV");
+
+       printf("page fault\n");
+       setup_checkdebug(SIGDEBUG_MIGRATE_FAULT);
+       delay.tv_nsec = 0;
+       err = clock_nanosleep(CLOCK_MONOTONIC, 0, &delay, NULL);
+       check_no_error("clock_nanosleep", err);
+       *mem ^= 0xFF;
+       check_sigdebug_received("SIGDEBUG_MIGRATE_FAULT");
+
+       if (wd) {
+               printf("watchdog\n");
+               rt_print_flush_buffers();
+               setup_checkdebug(SIGDEBUG_WATCHDOG);
+               clock_gettime(CLOCK_MONOTONIC, &now);
+               end = now.tv_sec * 1000000000ULL + now.tv_nsec + 2100000000ULL;
+               err = clock_nanosleep(CLOCK_MONOTONIC, 0, &delay, NULL);
+               check_no_error("clock_nanosleep", err);
+               do
+                       clock_gettime(CLOCK_MONOTONIC, &now);
+               while (now.tv_sec * 1000000000ULL + now.tv_nsec < end &&
+                        !sigdebug_received);
+               check_sigdebug_received("SIGDEBUG_WATCHDOG");
+       }
+
+       printf("lock break\n");
+       setup_checkdebug(SIGDEBUG_LOCK_BREAK);
+       err = pthread_setmode_np(0, PTHREAD_LOCK_SCHED |
+                                   PTHREAD_DISABLE_LOCKBREAK, NULL);
+       check_no_error("pthread_setmode_np", err);
+       delay.tv_nsec = 1000000LL;
+       err = clock_nanosleep(CLOCK_MONOTONIC, 0, &delay, NULL);
+       check("clock_nanosleep", err, EINTR);
+       check_sigdebug_received("SIGDEBUG_LOCK_BREAK");
+
+       return NULL;
+}
+
+static void sigdebug_handler(int sig, siginfo_t *si, void *context)
+{
+       unsigned int reason = sigdebug_reason(si);
+
+       if (reason != expected_reason) {
+               rt_print_flush_buffers();
+               fprintf(stderr, "FAILURE: sigdebug_handler expected reason %d,"
+                       " received %d\n", expected_reason, reason);
+               exit(EXIT_FAILURE);
+       }
+       sigdebug_received = true;
+}
+
+static void dummy_handler(int sig, siginfo_t *si, void *context)
+{
+}
+
+static int run_sigdebug(struct smokey_test *t, int argc, char *const argv[])
+{
+       char tempname[] = "/tmp/sigdebug-XXXXXX";
+       char buf[BUFSIZ], dev[BUFSIZ];
+       struct sched_param params = {.sched_priority = 1};
+       pthread_t rt_thread;
+       pthread_attr_t attr;
+       pthread_mutexattr_t mutex_attr;
+       struct timespec delay = {.tv_sec = 0, .tv_nsec = 20000000ULL};
+       long int start, trash, end;
+       unsigned char *mayday, *p;
+       struct sigaction sa;
+       int old_wd_value;
+       char r, w, x, s;
+       int tmp_fd, d;
+       FILE *maps;
+       int err;
+
+       rt_print_auto_init(1);
+
+       if (argc < 2 || strcmp(argv[1], "--skip-watchdog") != 0) {
+               wd = fopen("/sys/module/xenomai/parameters/watchdog_timeout",
+                          "w+");
+               if (!wd) {
+                       fprintf(stderr, "FAILURE: no watchdog available and "
+                                       "--skip-watchdog not specified\n");
+                       exit(EXIT_FAILURE);
+               }
+               err = fscanf(wd, "%d", &old_wd_value);
+               check("get watchdog", err, 1);
+               err = fprintf(wd, "2");
+               check("set watchdog", err, 1);
+               fflush(wd);
+       }
+
+       maps = fopen("/proc/self/maps", "r");
+       if (maps == NULL) {
+               perror("open /proc/self/maps");
+               exit(EXIT_FAILURE);
+       }
+
+       while (fgets(buf, sizeof(buf), maps)) {
+               if (sscanf(buf, "%lx-%lx %c%c%c%c %lx %x:%x %d%s\n",
+                          &start, &end, &r, &w, &x, &s, &trash,
+                          &d, &d, &d, dev) == 11
+                   && r == 'r' && x == 'x'
+                   && !strcmp(dev, "/dev/rtheap") && end - start == 4096) {
+                       printf("mayday page starting at 0x%lx [%s]\n"
+                              "mayday code:", start, dev);
+                       mayday = (unsigned char *)start;
+                       for (p = mayday; p < mayday + 32; p++)
+                               printf(" %.2x", *p);
+                       printf("\n");
+               }
+       }
+       fclose(maps);
+
+       sigemptyset(&sa.sa_mask);
+       sa.sa_sigaction = sigdebug_handler;
+       sa.sa_flags = SA_SIGINFO;
+       sigaction(SIGDEBUG, &sa, NULL);
+
+       sa.sa_sigaction = dummy_handler;
+       sigaction(SIGUSR1, &sa, NULL);
+
+       errno = 0;
+       tmp_fd = mkstemp(tempname);
+       check_no_error("mkstemp", -errno);
+       unlink(tempname);
+       check_no_error("unlink", -errno);
+       mem = mmap(NULL, 1, PROT_READ | PROT_WRITE, MAP_SHARED, tmp_fd, 0);
+       check_no_error("mmap", -errno);
+       err = write(tmp_fd, "X", 1);
+       check("write", err, 1);
+
+       err = pthread_setschedparam(pthread_self(), SCHED_FIFO, &params);
+       check_no_error("pthread_setschedparam", err);
+
+       err = pthread_mutexattr_init(&mutex_attr);
+       check_no_error("pthread_mutexattr_init", err);
+       err = pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT);
+       check_no_error("pthread_mutexattr_setprotocol", err);
+       err = pthread_mutex_init(&prio_invert, &mutex_attr);
+       check_no_error("pthread_mutex_init", err);
+
+       err = pthread_mutex_lock(&prio_invert);
+       check_no_error("pthread_mutex_lock", err);
+
+       err = sem_init(&send_signal, 0, 0);
+       check_no_error("sem_init", err);
+
+       err = pthread_attr_init(&attr);
+       check_no_error("pthread_attr_init", err);
+       err = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+       check_no_error("pthread_attr_setinheritsched", err);
+       err = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+       check_no_error("pthread_attr_setschedpolicy", err);
+       params.sched_priority = 2;
+       err = pthread_attr_setschedparam(&attr, &params);
+       check_no_error("pthread_attr_setschedparam", err);
+
+       printf("mlockall\n");
+       munlockall();
+       setup_checkdebug(SIGDEBUG_NOMLOCK);
+       err = pthread_create(&rt_thread, &attr, rt_thread_body, NULL);
+       check("pthread_setschedparam", err, EINTR);
+       check_sigdebug_received("SIGDEBUG_NOMLOCK");
+       mlockall(MCL_CURRENT | MCL_FUTURE);
+
+       err = pthread_create(&rt_thread, &attr, rt_thread_body, NULL);
+       check_no_error("pthread_create", err);
+
+       err = sem_wait(&send_signal);
+       check_no_error("sem_wait", err);
+       err = __real_pthread_kill(rt_thread, SIGUSR1);
+       check_no_error("pthread_kill", err);
+
+       __real_clock_nanosleep(CLOCK_MONOTONIC, 0, &delay, NULL);
+
+       err = pthread_mutex_unlock(&prio_invert);
+       check_no_error("pthread_mutex_unlock", err);
+
+       err = pthread_join(rt_thread, NULL);
+       check_no_error("pthread_join", err);
+
+       err = pthread_mutex_destroy(&prio_invert);
+       check_no_error("pthread_mutex_destroy", err);
+
+       err = sem_destroy(&send_signal);
+       check_no_error("sem_destroy", err);
+
+       if (wd) {
+               fprintf(wd, "%d", old_wd_value);
+               fclose(wd);
+       }
+
+       return 0;
+}


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to