Module: xenomai-jki
Branch: for-upstream
Commit: 803ff2e093a4260054e1e9e59114bc4e656c84bd
URL:    
http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=803ff2e093a4260054e1e9e59114bc4e656c84bd

Author: Jan Kiszka <jan.kis...@siemens.com>
Date:   Mon Jan 25 16:52:54 2010 +0100

Rename SIGXCPU to SIGDEBUG and deliver reason via siginfo

Now that we raise SIGXCPU not only on unwanted migrations or missing
memory locking but also watchdog events, it's getting fairly hard for
user space to tell those reasons apart.

This patch collects the various reasons and attaches them in a siginfo
value to the renamed SIGDEBUG signal. It even allows to find out the
precise reason for migrations, ie. if a syscall, signal delivery, fault,
or detected priority inversion let the nucleus switch some task to Linux
mode.

The existing example is updated accordingly.

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

---

 examples/native/Makefile      |    2 +-
 examples/native/sigdebug.c    |   82 +++++++++++++++++++++++++++++++++++++++++
 examples/native/sigxcpu.c     |   70 -----------------------------------
 include/asm-generic/syscall.h |    9 ++++
 include/nucleus/shadow.h      |    2 +-
 ksrc/nucleus/Kconfig          |    2 +-
 ksrc/nucleus/pod.c            |    3 +-
 ksrc/nucleus/sched.c          |    2 +-
 ksrc/nucleus/shadow.c         |   45 ++++++++++++++--------
 ksrc/nucleus/synch.c          |    6 ++-
 ksrc/skins/native/syscall.c   |    6 +-
 ksrc/skins/posix/signal.c     |    2 +-
 ksrc/skins/posix/thread.c     |    2 +-
 13 files changed, 135 insertions(+), 98 deletions(-)

diff --git a/examples/native/Makefile b/examples/native/Makefile
index d214f28..b279751 100644
--- a/examples/native/Makefile
+++ b/examples/native/Makefile
@@ -1,7 +1,7 @@
 ###### CONFIGURATION ######
 
 ### List of applications to be build
-APPLICATIONS = trivial-periodic sigxcpu rtprint
+APPLICATIONS = trivial-periodic sigdebug rtprint
 
 ### Note: to override the search path for the xeno-config script, use "make 
XENO=..."
 
diff --git a/examples/native/sigdebug.c b/examples/native/sigdebug.c
new file mode 100644
index 0000000..be167e7
--- /dev/null
+++ b/examples/native/sigdebug.c
@@ -0,0 +1,82 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <getopt.h>
+#include <execinfo.h>
+#include <sys/mman.h>
+#include <native/task.h>
+
+RT_TASK task;
+
+void task_body (void *cookie)
+{
+    /* Ask Xenomai to warn us upon switches to secondary mode. */
+    rt_task_set_mode(0, T_WARNSW, NULL);
+
+    /* A real-time task always starts in primary mode. */
+
+    for (;;) {
+       rt_task_sleep(1000000000);
+        /* Running in primary mode... */
+       printf("Switched to secondary mode\n");
+        /* ...printf() => write(2): we have just switched to secondary
+          mode: SIGDEBUG should have been sent to us by now. */
+    }
+}
+
+static const char *reason_str[] = {
+    [SIGDEBUG_UNDEFINED] = "undefined",
+    [SIGDEBUG_MIGRATE_SIGNAL] = "received signal",
+    [SIGDEBUG_MIGRATE_SYSCALL] = "invoked syscall",
+    [SIGDEBUG_MIGRATE_FAULT] = "triggered fault",
+    [SIGDEBUG_MIGRATE_PRIOINV] = "affected by priority inversion",
+    [SIGDEBUG_NOMLOCK] = "missing mlockall",
+    [SIGDEBUG_WATCHDOG] = "runaway thread",
+};
+
+void warn_upon_switch(int sig, siginfo_t *si, void *context)
+{
+    unsigned int reason = si->si_value.sival_int;
+    void *bt[32];
+    int nentries;
+
+    printf("\nSIGDEBUG received, reason %d: %s\n", reason,
+           reason <= SIGDEBUG_WATCHDOG ? reason_str[reason] : "<unknown>");
+    /* Dump a backtrace of the frame which caused the switch to
+       secondary mode: */
+    nentries = backtrace(bt,sizeof(bt) / sizeof(bt[0]));
+    backtrace_symbols_fd(bt,nentries,fileno(stdout));
+}
+
+int main (int argc, char **argv)
+{
+    struct sigaction sa;
+    int err;
+
+    mlockall(MCL_CURRENT | MCL_FUTURE);
+
+    sigemptyset(&sa.sa_mask);
+    sa.sa_sigaction = warn_upon_switch;
+    sa.sa_flags = SA_SIGINFO;
+    sigaction(SIGDEBUG, &sa, NULL);
+
+    err = rt_task_create(&task,"mytask",0,1,T_FPU);
+
+    if (err) {
+       fprintf(stderr,"failed to create task, code %d\n",err);
+       return 0;
+    }
+
+    err = rt_task_start(&task,&task_body,NULL);
+
+    if (err) {
+       fprintf(stderr,"failed to start task, code %d\n",err);
+       return 0;
+    }
+
+    pause();
+
+    return 0;
+}
diff --git a/examples/native/sigxcpu.c b/examples/native/sigxcpu.c
deleted file mode 100644
index e21c098..0000000
--- a/examples/native/sigxcpu.c
+++ /dev/null
@@ -1,70 +0,0 @@
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include <getopt.h>
-#include <execinfo.h>
-#include <sys/mman.h>
-#include <native/task.h>
-
-RT_TASK task;
-
-void task_body (void *cookie)
-
-{
-    /* Ask Xenomai to warn us upon switches to secondary mode. */
-    rt_task_set_mode(0, T_WARNSW, NULL);
-
-    /* A real-time task always starts in primary mode. */
-
-    for (;;) {
-       rt_task_sleep(1000000000);
-        /* Running in primary mode... */
-       printf("Switched to secondary mode\n");
-        /* ...printf() => write(2): we have just switched to secondary
-          mode: SIGXCPU should have been sent to us by now. */
-    }
-}
-
-void warn_upon_switch(int sig __attribute__((unused)))
-
-{
-    void *bt[32];
-    int nentries;
-
-    /* Dump a backtrace of the frame which caused the switch to
-       secondary mode: */
-    nentries = backtrace(bt,sizeof(bt) / sizeof(bt[0]));
-    backtrace_symbols_fd(bt,nentries,fileno(stdout));
-}
-
-int main (int argc, char **argv)
-
-{
-    int err;
-
-    mlockall(MCL_CURRENT | MCL_FUTURE);
-
-    signal(SIGXCPU, warn_upon_switch);
-
-    err = rt_task_create(&task,"mytask",0,1,T_FPU);
-
-    if (err)
-       {
-       fprintf(stderr,"failed to create task, code %d\n",err);
-       return 0;
-       }
-
-    err = rt_task_start(&task,&task_body,NULL);
-
-    if (err)
-       {
-       fprintf(stderr,"failed to start task, code %d\n",err);
-       return 0;
-       }
-
-    pause();
-
-    return 0;
-}
diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h
index e8290a8..315822e 100644
--- a/include/asm-generic/syscall.h
+++ b/include/asm-generic/syscall.h
@@ -63,6 +63,15 @@ typedef struct xnsysinfo {
 #define sigshadow_arg(code) (((code) >> 8) & 0xff)
 #define sigshadow_int(action, arg) ((action) | ((arg) << 8))
 
+#define SIGDEBUG                       SIGXCPU
+#define SIGDEBUG_UNDEFINED             0
+#define SIGDEBUG_MIGRATE_SIGNAL                1
+#define SIGDEBUG_MIGRATE_SYSCALL       2
+#define SIGDEBUG_MIGRATE_FAULT         3
+#define SIGDEBUG_MIGRATE_PRIOINV       4
+#define SIGDEBUG_NOMLOCK               5
+#define SIGDEBUG_WATCHDOG              6
+
 union xnsiginfo {
        struct siginfo pse51_si;
 };
diff --git a/include/nucleus/shadow.h b/include/nucleus/shadow.h
index 0742044..b6971da 100644
--- a/include/nucleus/shadow.h
+++ b/include/nucleus/shadow.h
@@ -75,7 +75,7 @@ void xnshadow_unmap(struct xnthread *thread);
 
 int xnshadow_harden(void);
 
-void xnshadow_relax(int notify);
+void xnshadow_relax(int notify, int reason);
 
 void xnshadow_renice(struct xnthread *thread);
 
diff --git a/ksrc/nucleus/Kconfig b/ksrc/nucleus/Kconfig
index 8e4c0b1..211a4ad 100644
--- a/ksrc/nucleus/Kconfig
+++ b/ksrc/nucleus/Kconfig
@@ -301,7 +301,7 @@ config XENO_OPT_DEBUG_SYNCH_RELAX
        This option detects situations where a real-time thread
        attempts to sleep on a Xenomai mutex object, that is owned by
        another thread currently running in secondary mode (i.e. plain
-       Linux execution mode). The SIGXCPU signal may be sent in such
+       Linux execution mode). The SIGDEBUG signal may be sent in such
        a case to the sleeper, provided the WARNSW flag is enabled for
        it, as set by e.g. rt_task_set_mode() or pthread_set_mode_np().
 
diff --git a/ksrc/nucleus/pod.c b/ksrc/nucleus/pod.c
index 6184515..93713f2 100644
--- a/ksrc/nucleus/pod.c
+++ b/ksrc/nucleus/pod.c
@@ -2599,7 +2599,8 @@ int xnpod_trap_fault(xnarch_fltinfo_t *fltinfo)
                           locking anyway. */
                        xnstat_counter_inc(&thread->stat.pf);
 
-               xnshadow_relax(xnarch_fault_notify(fltinfo));
+               xnshadow_relax(xnarch_fault_notify(fltinfo),
+                              SIGDEBUG_MIGRATE_FAULT);
        }
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
 #endif /* __KERNEL__ */
diff --git a/ksrc/nucleus/sched.c b/ksrc/nucleus/sched.c
index aa6c288..4ec0013 100644
--- a/ksrc/nucleus/sched.c
+++ b/ksrc/nucleus/sched.c
@@ -99,7 +99,7 @@ static void xnsched_watchdog_handler(struct xntimer *timer)
                xnprintf("watchdog triggered -- signaling runaway thread "
                         "'%s'\n", xnthread_name(thread));
                xnthread_set_info(thread, XNAMOK | XNKICKED);
-               xnshadow_send_sig(thread, SIGXCPU, 0, 1);
+               xnshadow_send_sig(thread, SIGDEBUG, SIGDEBUG_WATCHDOG, 1);
        } else
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
        {
diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
index fa27e0c..d82d6c7 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -778,7 +778,7 @@ static inline void request_syscall_restart(xnthread_t 
*thread,
                xnthread_clear_info(thread, XNKICKED);
        }
 
-       xnshadow_relax(notify);
+       xnshadow_relax(notify, SIGDEBUG_MIGRATE_SIGNAL);
 }
 
 static inline void set_linux_task_priority(struct task_struct *p, int prio)
@@ -861,7 +861,7 @@ static void lostage_handler(void *cookie)
 
                case LO_SIGTHR_REQ:
                        xnshadow_sig_demux(arg, sig, sigarg);
-                       if (sig == SIGSHADOW) {
+                       if (sig == SIGSHADOW || sig == SIGDEBUG) {
                                siginfo_t si;
                                memset(&si, '\0', sizeof(si));
                                si.si_signo = sig;
@@ -1112,7 +1112,7 @@ EXPORT_SYMBOL_GPL(xnshadow_harden);
 
 /*! 
  * @internal
- * \fn void xnshadow_relax(int notify);
+ * \fn void xnshadow_relax(int notify, int reason);
  * \brief Switch a shadow thread back to the Linux domain.
  *
  * This service yields the control of the running shadow back to
@@ -1122,10 +1122,12 @@ EXPORT_SYMBOL_GPL(xnshadow_harden);
  * behalf of the root thread.
  *
  * @param notify A boolean flag indicating whether threads monitored
- * from secondary mode switches should be sent a SIGXCPU signal. For
+ * from secondary mode switches should be sent a SIGDEBUG signal. For
  * instance, some internal operations like task exit should not
  * trigger such signal.
  *
+ * @param reason The reason to report along with the SIGDEBUG signal.
+ *
  * Environments:
  *
  * This service can be called from:
@@ -1138,9 +1140,10 @@ EXPORT_SYMBOL_GPL(xnshadow_harden);
  * properties of the Linux task.
  */
 
-void xnshadow_relax(int notify)
+void xnshadow_relax(int notify, int reason)
 {
        xnthread_t *thread = xnpod_current_thread();
+       siginfo_t si;
        int prio;
        spl_t s;
 
@@ -1172,10 +1175,14 @@ void xnshadow_relax(int notify)
        xnstat_counter_inc(&thread->stat.ssw);  /* Account for secondary mode 
switch. */
 
        if (notify) {
-               if (xnthread_test_state(thread, XNTRAPSW))
+               if (xnthread_test_state(thread, XNTRAPSW)) {
                        /* Help debugging spurious relaxes. */
-                       send_sig(SIGXCPU, current, 1);
-
+                       memset(&si, 0, sizeof(si));
+                       si.si_signo = SIGDEBUG;
+                       si.si_code = SI_QUEUE;
+                       si.si_int = reason;
+                       send_sig_info(SIGDEBUG, &si, current);
+               }
                xnsynch_detect_claimed_relax(thread);
        }
 
@@ -1295,9 +1302,15 @@ int xnshadow_map(xnthread_t *thread, xncompletion_t 
__user *u_completion,
                return -EFAULT;
 
 #ifdef CONFIG_MMU
-       if (!(current->mm->def_flags & VM_LOCKED))
-               send_sig(SIGXCPU, current, 1);
-       else
+       if (!(current->mm->def_flags & VM_LOCKED)) {
+               siginfo_t si;
+
+               memset(&si, 0, sizeof(si));
+               si.si_signo = SIGDEBUG;
+               si.si_code = SI_QUEUE;
+               si.si_int = SIGDEBUG_NOMLOCK;
+               send_sig_info(SIGDEBUG, &si, current);
+       } else
                if ((ret = rthal_disable_ondemand_mappings(current)))
                        return ret;
 #endif /* CONFIG_MMU */
@@ -1529,7 +1542,7 @@ static int xnshadow_sys_migrate(struct pt_regs *regs)
                        return 0;
        else /* rthal_current_domain != rthal_root_domain */
     if (__xn_reg_arg1(regs) == XENOMAI_LINUX_DOMAIN) {
-               xnshadow_relax(0);
+               xnshadow_relax(0, 0);
                return 1;
        } else
                return 0;
@@ -2114,7 +2127,7 @@ static inline int do_hisyscall_event(unsigned event, 
unsigned domid, void *data)
                if (domid == RTHAL_DOMAIN_ID) {
                        /* Request originates from the Xenomai domain: just 
relax the
                           caller and execute the syscall immediately after. */
-                       xnshadow_relax(1);
+                       xnshadow_relax(1, SIGDEBUG_MIGRATE_SYSCALL);
                        switched = 1;
                } else
                        /* Request originates from the Linux domain: propagate 
the
@@ -2208,7 +2221,7 @@ static inline int do_hisyscall_event(unsigned event, 
unsigned domid, void *data)
         * it. Before we let it go, ensure that the current thread has
         * properly entered the Linux domain.
         */
-       xnshadow_relax(1);
+       xnshadow_relax(1, SIGDEBUG_MIGRATE_SYSCALL);
 
        goto propagate_syscall;
 
@@ -2305,7 +2318,7 @@ static inline int do_losyscall_event(unsigned event, 
unsigned domid, void *data)
        if (err == -ENOSYS && (sysflags & __xn_exec_adaptive) != 0) {
                if (switched) {
                        switched = 0;
-                       xnshadow_relax(1);
+                       xnshadow_relax(1, SIGDEBUG_MIGRATE_SYSCALL);
                }
 
                sysflags ^=
@@ -2326,7 +2339,7 @@ static inline int do_losyscall_event(unsigned event, 
unsigned domid, void *data)
                handle_rt_signals(thread, regs, sysflags);
        }
        if (!sigs && (sysflags & __xn_exec_switchback) != 0 && switched)
-               xnshadow_relax(0);
+               xnshadow_relax(0, 0);
 
       ret_handled:
        trace_mark(xn_nucleus, syscall_lostage_exit,
diff --git a/ksrc/nucleus/synch.c b/ksrc/nucleus/synch.c
index 91de768..619929e 100644
--- a/ksrc/nucleus/synch.c
+++ b/ksrc/nucleus/synch.c
@@ -992,7 +992,8 @@ void xnsynch_detect_relaxed_owner(struct xnsynch *synch, 
struct xnthread *sleepe
        if (xnthread_test_state(sleeper, XNTRAPSW|XNSWREP) == XNTRAPSW &&
            xnthread_test_state(synch->owner, XNRELAX)) {
                xnthread_set_state(sleeper, XNSWREP);
-               xnshadow_send_sig(sleeper, SIGXCPU, 0, 1);
+               xnshadow_send_sig(sleeper, SIGDEBUG,
+                                 SIGDEBUG_MIGRATE_PRIOINV, 1);
        } else
                xnthread_clear_state(sleeper,  XNSWREP);
 }
@@ -1017,7 +1018,8 @@ void xnsynch_detect_claimed_relax(struct xnthread *owner)
                        sleeper = link2thread(ht, plink);
                        if (xnthread_test_state(sleeper, XNRELAX)) {
                                xnthread_set_state(sleeper, XNSWREP);
-                               xnshadow_send_sig(sleeper, SIGXCPU, 0, 1);
+                               xnshadow_send_sig(sleeper, SIGDEBUG,
+                                                 SIGDEBUG_MIGRATE_PRIOINV, 1);
                        }
                }
        }
diff --git a/ksrc/skins/native/syscall.c b/ksrc/skins/native/syscall.c
index b92d605..40e5cfd 100644
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -597,7 +597,7 @@ static int __rt_task_set_mode(struct pt_regs *regs)
                return err;
 
        if ((clrmask & T_PRIMARY) != 0)
-               xnshadow_relax(0);
+               xnshadow_relax(0, 0);
        else
                mode_r |= T_PRIMARY;
 
@@ -2092,7 +2092,7 @@ static int __rt_queue_bind(struct pt_regs *regs)
           might have entered it in primary mode. */
 
        if (xnpod_primary_p())
-               xnshadow_relax(0);
+               xnshadow_relax(0, 0);
 
        return 0;
 
@@ -2616,7 +2616,7 @@ static int __rt_heap_bind(struct pt_regs *regs)
           might have entered it in primary mode. */
 
        if (xnpod_primary_p())
-               xnshadow_relax(0);
+               xnshadow_relax(0, 0);
 
        return 0;
 
diff --git a/ksrc/skins/posix/signal.c b/ksrc/skins/posix/signal.c
index 193674c..94bc3e4 100644
--- a/ksrc/skins/posix/signal.c
+++ b/ksrc/skins/posix/signal.c
@@ -1057,7 +1057,7 @@ static void pse51_dispatch_shadow_signals(xnsigmask_t 
sigs)
 {
        /* Migrate to secondary mode in order to get the signals delivered by
           Linux. */
-       xnshadow_relax(1);
+       xnshadow_relax(1, SIGDEBUG_MIGRATE_SIGNAL);
 }
 
 void pse51_signal_handle_request(pthread_t thread)
diff --git a/ksrc/skins/posix/thread.c b/ksrc/skins/posix/thread.c
index 87ff38c..853ea53 100644
--- a/ksrc/skins/posix/thread.c
+++ b/ksrc/skins/posix/thread.c
@@ -684,7 +684,7 @@ int pthread_set_mode_np(int clrmask, int setmask)
 
 #ifdef CONFIG_XENO_OPT_PERVASIVE
        if (xnthread_test_state(cur, XNSHADOW) && (clrmask & 
XNTHREAD_STATE_SPARE1) != 0)
-               xnshadow_relax(0);
+               xnshadow_relax(0, 0);
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
 
        return 0;


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to