Module: xenomai-jki Branch: for-forge Commit: f3456627f2d6090bea0929199678fbba572c7084 URL: http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=f3456627f2d6090bea0929199678fbba572c7084
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, ¶ms); + 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, ¶ms); + 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