From: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
To: xenomai@lists.linux.dev
Cc: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
Subject: [PATCH 2/3] [POC] Add rt_signal test
Date: Wed, 16 Aug 2023 12:18:41 +0200 [thread overview]
Message-ID: <20230816101842.3377643-2-johannes.kirchmair@sigmatek.at> (raw)
In-Reply-To: <20230816101842.3377643-1-johannes.kirchmair@sigmatek.at>
This commit adds simple rt signal test for SIGFPE, SIGILL and SIGSEGV.
---
configure.ac | 1 +
testsuite/Makefile.am | 1 +
testsuite/rt-signal-tests/Makefile.am | 31 +++
testsuite/rt-signal-tests/rt_signal_test.c | 231 +++++++++++++++++++++
4 files changed, 264 insertions(+)
create mode 100644 testsuite/rt-signal-tests/Makefile.am
create mode 100644 testsuite/rt-signal-tests/rt_signal_test.c
diff --git a/configure.ac b/configure.ac
index 3ce34048e..3325482fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1007,6 +1007,7 @@ AC_CONFIG_FILES([ \
testsuite/switchtest/Makefile \
testsuite/gpiotest/Makefile \
testsuite/gpiobench/Makefile \
+ testsuite/rt-signal-tests/Makefile \
testsuite/spitest/Makefile \
testsuite/smokey/Makefile \
testsuite/smokey/arith/Makefile \
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 4932f6d33..59f36967a 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -5,6 +5,7 @@ if XENO_COBALT
SUBDIRS += \
clocktest \
gpiotest \
+ rt-signal-tests \
spitest \
switchtest \
xeno-test
diff --git a/testsuite/rt-signal-tests/Makefile.am b/testsuite/rt-signal-tests/Makefile.am
new file mode 100644
index 000000000..084347631
--- /dev/null
+++ b/testsuite/rt-signal-tests/Makefile.am
@@ -0,0 +1,31 @@
+testdir = @XENO_TEST_DIR@
+
+CCLD = $(top_srcdir)/scripts/wrap-link.sh $(CC)
+
+test_PROGRAMS = rt_signal_test_fpe rt_signal_test_segfault rt_signal_test_ill
+
+alchemycppflags = \
+ $(XENO_USER_CFLAGS) \
+ -I$(top_srcdir)/include
+
+alchemyldadd = \
+ @XENO_AUTOINIT_LDFLAGS@ \
+ $(XENO_POSIX_WRAPPERS) \
+ ../../lib/alchemy/libalchemy.la \
+ ../../lib/copperplate/libcopperplate.la \
+ @XENO_CORE_LDADD@ \
+ @XENO_USER_LDADD@ \
+ -lrt -lpthread -lm
+
+rt_signal_test_fpe_SOURCES = rt_signal_test.c
+rt_signal_test_fpe_CPPFLAGS = $(alchemycppflags) -DTEST_FPE=1
+rt_signal_test_fpe_LDADD = $(alchemyldadd)
+
+rt_signal_test_segfault_SOURCES = rt_signal_test.c
+rt_signal_test_segfault_CPPFLAGS = $(alchemycppflags) -DTEST_SEGFAULT=1
+rt_signal_test_segfault_LDADD = $(alchemyldadd)
+
+rt_signal_test_ill_SOURCES = rt_signal_test.c
+rt_signal_test_ill_CPPFLAGS = $(alchemycppflags)
+rt_signal_test_ill_LDADD = $(alchemyldadd)
+
diff --git a/testsuite/rt-signal-tests/rt_signal_test.c b/testsuite/rt-signal-tests/rt_signal_test.c
new file mode 100644
index 000000000..ef569b30d
--- /dev/null
+++ b/testsuite/rt-signal-tests/rt_signal_test.c
@@ -0,0 +1,231 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <copperplate/traceobj.h>
+#include <alchemy/task.h>
+#include <assert.h>
+#include <setjmp.h>
+#include <asm/ucontext.h>
+
+#ifdef TEST_SEGFAULT
+#define TEST_SIGNAL SIGSEGV
+#elif defined(TEST_FPE)
+#define TEST_SIGNAL SIGFPE
+#else
+#define TEST_SIGNAL SIGILL
+#endif
+
+#define BIT_FAULT_HANDLER_ENTERD 1
+#define BIT_FAULT_HANDLER_FINISHED 2
+#define BIT_FAULT_HANDLER_WRONG_TASK 4
+#define BIT_FAULT_HANDLER_WRONG_SIG 8
+#define BIT_DOMAIN_SWITCH 16
+
+static RT_TASK t1;
+static sig_atomic_t status = 0;
+static sig_atomic_t cause = 0;
+
+// #define JMP_CLEANUP
+#ifdef JMP_CLEANUP
+static jmp_buf jmpenv;
+#endif
+
+static int status_ok(void)
+{
+ return status ==
+ (BIT_FAULT_HANDLER_ENTERD | BIT_FAULT_HANDLER_FINISHED);
+}
+
+static const char *sigdebug_msg[] = {
+ [SIGDEBUG_UNDEFINED] = "latency: received SIGXCPU for unknown reason",
+ [SIGDEBUG_MIGRATE_SIGNAL] = "received signal",
+ [SIGDEBUG_MIGRATE_SYSCALL] = "invoked syscall",
+ [SIGDEBUG_MIGRATE_FAULT] = "triggered fault",
+ [SIGDEBUG_MIGRATE_PRIOINV] = "affected by priority inversion",
+ [SIGDEBUG_NOMLOCK] = "Xenomai: process memory not locked "
+ "(missing mlockall?)",
+ [SIGDEBUG_WATCHDOG] = "Xenomai: watchdog triggered "
+ "(period too short?)",
+};
+
+
+#ifndef JMP_CLEANUP
+static int get_step(void)
+{
+#ifdef TEST_SEGFAULT
+#if defined(__i386__) || defined(__x86_64__)
+ return 11;
+#else
+ return 4;
+#endif
+#elif defined(TEST_FPE)
+ return 2;
+#else
+#if defined(__i386__) || defined(__x86_64__)
+ return 2;
+#else
+ return 4;
+#endif
+#endif
+}
+
+static void do_cleanup(void *context)
+{
+ int step = 0;
+ struct ucontext *uc = context;
+
+ step = get_step();
+
+#if defined(__i386__)
+ uc->uc_mcontext.eip += step;
+#elif defined(__x86_64__)
+ uc->uc_mcontext.rip += step;
+#elif defined(__aarch64__)
+ uc->uc_mcontext.pc += step;
+#endif
+}
+#endif
+
+static void signal_handler(int sig, siginfo_t *info, void *context)
+{
+ RT_TASK *self;
+ (void)context;
+
+ if (sig == SIGDEBUG) {
+ cause = sigdebug_reason(info);
+
+ if (cause > SIGDEBUG_WATCHDOG)
+ cause = SIGDEBUG_UNDEFINED;
+
+ /* XXX: caused by rt_task_delete() */
+ if (!(status & BIT_FAULT_HANDLER_ENTERD) &&
+ cause == SIGDEBUG_MIGRATE_SYSCALL) {
+ return;
+ }
+
+ status |= BIT_DOMAIN_SWITCH;
+ } else {
+ status |= BIT_FAULT_HANDLER_ENTERD;
+ if (sig != TEST_SIGNAL) {
+ status |= BIT_FAULT_HANDLER_WRONG_SIG;
+ return;
+ }
+
+ self = rt_task_self();
+
+ if (self == NULL || !rt_task_same(self, &t1)) {
+ status |= BIT_FAULT_HANDLER_WRONG_TASK;
+ } else {
+ status |= BIT_FAULT_HANDLER_FINISHED;
+ }
+
+#ifdef JMP_CLEANUP
+ longjmp(jmpenv, 1);
+#else
+ do_cleanup(context);
+#endif
+ }
+}
+
+static void do_div_by_0(void)
+{
+#if defined(__i386__) || defined (__x86_64__)
+ __asm__("xorl %eax, %eax\n\t"
+ "movl %eax, %ecx\n\t"
+ "cltd\n\t"
+ "idivl %ecx");
+#endif
+ //TODO find a cortex-A way to trigger an FPE
+}
+
+static void do_ill(void)
+{
+#if defined(__i386__) || defined (__x86_64__)
+ __asm__("ud2");
+#else
+ __asm__("udf #0xdead");
+#endif
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+static void do_segfault(void)
+{
+ *((int *)0x73) = 0xdecafbad;
+}
+#pragma GCC diagnostic pop
+
+static void task_proc(void *arg)
+{
+ int ret;
+ (void)arg;
+
+ ret = cobalt_rt_signal(TEST_SIGNAL, signal_handler);
+ assert(ret == 0);
+ (void)ret;
+
+#ifdef JMP_CLEANUP
+ if (setjmp(jmpenv) != 0)
+ return;
+#endif
+
+#ifdef TEST_SEGFAULT
+ do_segfault();
+#elif defined(TEST_FPE)
+ do_div_by_0();
+#else
+ do_ill();
+#endif
+
+ if (0) { // so we don't geht defined but not used errors
+ do_segfault();
+ do_div_by_0();
+ do_ill();
+ }
+}
+
+static int test_sucessfull(void)
+{
+ if (status_ok()) {
+ fputs("Test passed\n", stderr);
+ return 1;
+ }
+
+ if (!(status & BIT_FAULT_HANDLER_ENTERD))
+ fputs("Test failed: signal handler not invoked!\n", stderr);
+ if ((status & BIT_FAULT_HANDLER_WRONG_TASK))
+ fputs("Test failed: Signal handler in wrong task!\n", stderr);
+ if ((status & BIT_FAULT_HANDLER_WRONG_SIG))
+ fputs("Test failed: Signal handler of wrong signal!\n", stderr);
+ if ((status & BIT_DOMAIN_SWITCH)) {
+ fputs("Test failed: domain switch happened!\n", stderr);
+ fprintf(stderr, "Caused by: %s\n", sigdebug_msg[cause]);
+ }
+
+ return 0;
+}
+
+int main(void)
+{
+ struct sigaction sa;
+ int ret;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_sigaction = signal_handler;
+ sa.sa_flags = SA_SIGINFO | SA_NODEFER;
+ sigaction(TEST_SIGNAL, &sa, NULL);
+ sigaction(SIGDEBUG, &sa, NULL);
+
+ ret = rt_task_create(&t1, "rt-task", 0, 20, T_JOINABLE | T_WARNSW);
+ assert(ret == 0);
+
+ ret = rt_task_start(&t1, task_proc, NULL);
+ assert(ret == 0);
+
+ ret = rt_task_join(&t1);
+ assert(ret == 0);
+ (void)ret; // so the compiler does not complain about not checking ret
+
+ return test_sucessfull() ? EXIT_SUCCESS : EXIT_FAILURE;
+}
--
2.25.1
next prev parent reply other threads:[~2023-08-16 10:19 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-16 10:18 [PATCH 1/3] [POC] test implementaion of rt-signals Johannes Kirchmair
2023-08-16 10:18 ` Johannes Kirchmair [this message]
2023-08-16 10:18 ` [PATCH 3/3] [POC] add a tool to measure rt_signal latency Johannes Kirchmair
2023-08-16 11:24 ` [PATCH 1/3] [POC] test implementaion of rt-signals Florian Bezdeka
2023-08-16 11:36 ` Jan Kiszka
2023-08-16 11:59 ` Johannes Kirchmair
2023-09-07 10:48 ` Johannes Kirchmair
2023-09-11 8:41 ` Florian Bezdeka
2023-09-01 12:00 ` Jan Kiszka
2023-09-01 13:38 ` Jan Kiszka
2023-09-04 6:55 ` Johannes Kirchmair
2023-09-07 13:39 ` Jan Kiszka
2023-09-07 13:58 ` Johannes Kirchmair
2023-09-01 13:51 ` Jan Kiszka
2023-09-01 14:11 ` Jan Kiszka
2023-09-04 7:04 ` Johannes Kirchmair
2024-03-05 15:54 ` Richard Weinberger
2024-03-05 17:05 ` Jan Kiszka
2024-03-05 17:14 ` Richard Weinberger
-- strict thread matches above, loose matches on Subject: below --
2023-09-08 10:50 Johannes Kirchmair
2023-09-08 10:50 ` [PATCH 2/3] [POC] Add rt_signal test Johannes Kirchmair
2023-05-09 13:13 [PATCH 1/3] [POC] test implementaion of rt-signals Johannes Kirchmair
2023-05-09 13:13 ` [PATCH 2/3] [POC] Add rt_signal test Johannes Kirchmair
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230816101842.3377643-2-johannes.kirchmair@sigmatek.at \
--to=johannes.kirchmair@sigmatek.at \
--cc=xenomai@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).