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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Thu Jun 26 11:37:10 2014 +0200

cobalt/thread: enable SIGDEBUG on denied lock break detection

Send SIGDEBUG to the thread being denied a suspension/sleep state due
to XNTRAPLB, if the atypical/abnormal detection feature is armed.
The new SIGDEBUG_LOCK_BREAK alert code matches this case in the
siginfo data conveyed by SIGDEBUG.

At this chance, the related TCB state and information flag names have
been updated to better reflect the semantics:

XNTRAPSW -> XNWARN (SIGDEBUG warning enabled for atypical/abnormal
conditions)

XNSWREP -> XNPIALERT (Priority inversion alert sent [via SIGDEBUG])

---

 include/cobalt/kernel/thread.h      |    2 +-
 include/cobalt/uapi/kernel/thread.h |    7 ++++---
 include/cobalt/uapi/signal.h        |    1 +
 include/cobalt/uapi/thread.h        |    2 +-
 kernel/cobalt/debug.c               |    1 +
 kernel/cobalt/posix/thread.c        |    2 +-
 kernel/cobalt/sched.c               |    2 ++
 kernel/cobalt/shadow.c              |    2 +-
 kernel/cobalt/synch.c               |   12 ++++++------
 kernel/cobalt/thread.c              |   33 ++++++++++++++++++++++++++-------
 10 files changed, 44 insertions(+), 20 deletions(-)

diff --git a/include/cobalt/kernel/thread.h b/include/cobalt/kernel/thread.h
index 3b9bcc7..f961556 100644
--- a/include/cobalt/kernel/thread.h
+++ b/include/cobalt/kernel/thread.h
@@ -38,7 +38,7 @@
  * @{
  */
 #define XNTHREAD_BLOCK_BITS   
(XNSUSP|XNPEND|XNDELAY|XNDORMANT|XNRELAX|XNMIGRATE|XNHELD)
-#define XNTHREAD_MODE_BITS    (XNLOCK|XNRRB|XNTRAPSW|XNTRAPLB)
+#define XNTHREAD_MODE_BITS    (XNLOCK|XNRRB|XNWARN|XNTRAPLB)
 
 struct xnthread;
 struct xnsched;
diff --git a/include/cobalt/uapi/kernel/thread.h 
b/include/cobalt/uapi/kernel/thread.h
index be6ac0e..9025233 100644
--- a/include/cobalt/uapi/kernel/thread.h
+++ b/include/cobalt/uapi/kernel/thread.h
@@ -44,7 +44,7 @@
 #define XNDEBUG   0x00000800 /**< Hit a debugger breakpoint */
 #define XNLOCK    0x00001000 /**< Holds the scheduler lock (i.e. not 
preemptible) */
 #define XNRRB     0x00002000 /**< Undergoes a round-robin scheduling */
-#define XNTRAPSW  0x00004000 /**< Trap execution mode switches */
+#define XNWARN    0x00004000 /**< Issue SIGDEBUG on error detection */
 #define XNFPU     0x00008000 /**< Thread uses FPU */
 #define XNROOT    0x00010000 /**< Root thread (that is, Linux/IDLE) */
 #define XNWEAK    0x00020000 /**< Non real-time shadow (from the WEAK class) */
@@ -70,8 +70,9 @@
 #define XNWAKEN   0x00000010 /**< Thread waken up upon resource availability */
 #define XNROBBED  0x00000020 /**< Robbed from resource ownership */
 #define XNCANCELD 0x00000040 /**< Cancellation request is pending */
-#define XNSWREP   0x00000080 /**< Mode switch already reported */
-#define XNMOVED   0x00000100 /**< CPU migration in primary mode occurred */
+#define XNMOVED   0x00000080 /**< CPU migration in primary mode occurred */
+#define XNPIALERT 0x00001000 /**< Priority inversion alert (SIGDEBUG sent) */
+#define XNLBALERT 0x00002000 /**< Scheduler lock break alert (SIGDEBUG sent) */
 
 /** @} */
 
diff --git a/include/cobalt/uapi/signal.h b/include/cobalt/uapi/signal.h
index 2508008..187e561 100644
--- a/include/cobalt/uapi/signal.h
+++ b/include/cobalt/uapi/signal.h
@@ -59,6 +59,7 @@
 #define SIGDEBUG_NOMLOCK               5
 #define SIGDEBUG_WATCHDOG              6
 #define SIGDEBUG_RESCNT_IMBALANCE      7
+#define SIGDEBUG_LOCK_BREAK            8
 
 #define COBALT_DELAYMAX                        2147483647U
 
diff --git a/include/cobalt/uapi/thread.h b/include/cobalt/uapi/thread.h
index 6da5475..94c378a 100644
--- a/include/cobalt/uapi/thread.h
+++ b/include/cobalt/uapi/thread.h
@@ -20,7 +20,7 @@
 
 #include <cobalt/uapi/kernel/thread.h>
 
-#define PTHREAD_WARNSW             XNTRAPSW
+#define PTHREAD_WARNSW             XNWARN
 #define PTHREAD_LOCK_SCHED         XNLOCK
 #define PTHREAD_DISABLE_LOCKBREAK  XNTRAPLB
 #define PTHREAD_CONFORMING     0
diff --git a/kernel/cobalt/debug.c b/kernel/cobalt/debug.c
index 8a0c436..fa32c4b 100644
--- a/kernel/cobalt/debug.c
+++ b/kernel/cobalt/debug.c
@@ -423,6 +423,7 @@ static const char *reason_str[] = {
     [SIGDEBUG_NOMLOCK] = "mlock-check",
     [SIGDEBUG_WATCHDOG] = "runaway-break",
     [SIGDEBUG_RESCNT_IMBALANCE] = "resource-count-imbalance",
+    [SIGDEBUG_LOCK_BREAK] = "scheduler-lock-break",
 };
 
 static int relax_vfile_show(struct xnvfile_regular_iterator *it, void *data)
diff --git a/kernel/cobalt/posix/thread.c b/kernel/cobalt/posix/thread.c
index 895cbda..9669d19 100644
--- a/kernel/cobalt/posix/thread.c
+++ b/kernel/cobalt/posix/thread.c
@@ -419,7 +419,7 @@ static inline int pthread_create(struct cobalt_thread 
**thread_p,
 
 static inline int pthread_set_mode_np(int clrmask, int setmask, int *mode_r)
 {
-       const int valid_flags = XNLOCK|XNTRAPSW|XNTRAPLB;
+       const int valid_flags = XNLOCK|XNWARN|XNTRAPLB;
        struct xnthread *curr = xnshadow_current();
        int old;
 
diff --git a/kernel/cobalt/sched.c b/kernel/cobalt/sched.c
index a3791a1..0d08c49 100644
--- a/kernel/cobalt/sched.c
+++ b/kernel/cobalt/sched.c
@@ -338,6 +338,7 @@ void ___xnsched_unlock(struct xnsched *sched)
 
        if (--xnthread_lock_count(curr) == 0) {
                xnthread_clear_state(curr, XNLOCK);
+               xnthread_clear_info(curr, XNLBALERT);
                sched->lflags &= ~XNINLOCK;
                xnsched_run();
        }
@@ -350,6 +351,7 @@ void ___xnsched_unlock_fully(struct xnsched *sched)
 
        xnthread_lock_count(curr) = 0;
        xnthread_clear_state(curr, XNLOCK);
+       xnthread_clear_info(curr, XNLBALERT);
        sched->lflags &= ~XNINLOCK;
        xnsched_run();
 }
diff --git a/kernel/cobalt/shadow.c b/kernel/cobalt/shadow.c
index b6d54bf..1754d25 100644
--- a/kernel/cobalt/shadow.c
+++ b/kernel/cobalt/shadow.c
@@ -577,7 +577,7 @@ void xnshadow_relax(int notify, int reason)
 
        if (xnthread_test_state(thread, XNUSER) && notify) {
                xndebug_notify_relax(thread, reason);
-               if (xnthread_test_state(thread, XNTRAPSW)) {
+               if (xnthread_test_state(thread, XNWARN)) {
                        /* Help debugging spurious relaxes. */
                        memset(&si, 0, sizeof(si));
                        si.si_signo = SIGDEBUG;
diff --git a/kernel/cobalt/synch.c b/kernel/cobalt/synch.c
index 82d2262..15157f7 100644
--- a/kernel/cobalt/synch.c
+++ b/kernel/cobalt/synch.c
@@ -826,14 +826,14 @@ EXPORT_SYMBOL_GPL(xnsynch_release_all_ownerships);
  */
 void xnsynch_detect_relaxed_owner(struct xnsynch *synch, struct xnthread 
*sleeper)
 {
-       if (xnthread_test_state(sleeper, XNTRAPSW) &&
-           !xnthread_test_info(sleeper, XNSWREP) &&
+       if (xnthread_test_state(sleeper, XNWARN) &&
+           !xnthread_test_info(sleeper, XNPIALERT) &&
            xnthread_test_state(synch->owner, XNRELAX)) {
-               xnthread_set_info(sleeper, XNSWREP);
+               xnthread_set_info(sleeper, XNPIALERT);
                xnshadow_send_sig(sleeper, SIGDEBUG,
                                  SIGDEBUG_MIGRATE_PRIOINV);
        } else
-               xnthread_clear_info(sleeper,  XNSWREP);
+               xnthread_clear_info(sleeper,  XNPIALERT);
 }
 
 /*
@@ -851,8 +851,8 @@ void xnsynch_detect_claimed_relax(struct xnthread *owner)
 
        xnthread_for_each_claimed(synch, owner) {
                xnsynch_for_each_sleeper(sleeper, synch) {
-                       if (xnthread_test_state(sleeper, XNTRAPSW)) {
-                               xnthread_set_info(sleeper, XNSWREP);
+                       if (xnthread_test_state(sleeper, XNWARN)) {
+                               xnthread_set_info(sleeper, XNPIALERT);
                                xnshadow_send_sig(sleeper, SIGDEBUG,
                                                  SIGDEBUG_MIGRATE_PRIOINV);
                        }
diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
index 69b454f..a36ffc7 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -654,7 +654,7 @@ EXPORT_SYMBOL_GPL(xnthread_start);
 
 /**
  * @fn void xnthread_set_mode(struct xnthread *thread,int clrmask,int setmask)
- * @brief Change a thread's control mode.
+ * @brief Change thread control mode.
  *
  * Change the control mode of a given thread. The control mode affects
  * the behaviour of the nucleus regarding the specified thread.
@@ -676,14 +676,26 @@ EXPORT_SYMBOL_GPL(xnthread_start);
  * locked, otherwise such lock will take effect next time @a thread
  * resumes on a CPU.
  *
- * - XNTRAPSW causes the thread to receive a SIGDEBUG signal when it
- * switches to secondary mode. This is a debugging aid for detecting
- * spurious relaxes.
+ * - XNWARN is a debugging aid, causing the thread to receive a
+ * SIGDEBUG signal when the following atypical or abnormal behavior is
+ * detected:
+ *
+ * - @a thread switches to secondary mode (usable for detecting
+ * spurious relaxes).
+ *
+ * - @a thread is about to sleep on a Cobalt mutex currently owned by
+ * a thread running in secondary mode, which reveals a priority
+ * inversion case.
+ *
+ * - @a thread has both XNTRAPLB and XNLOCK set, and attempts to
+ * block on a Cobalt service, causing a lock break.
  *
  * - XNTRAPLB disallows breaking the scheduler lock. In the default
  * case, a thread which holds the scheduler lock is allowed to drop it
  * temporarily for sleeping. If this mode bit is set, such thread
- * would return immediately with XNBREAK set from xnthread_suspend().
+ * would return immediately with XNBREAK set from
+ * xnthread_suspend(). If XNWARN is set for @a thread, SIGDEBUG is
+ * sent in addition to raising the break condition.
  *
  * @coretags{task-unrestricted, might-switch}
  *
@@ -692,12 +704,13 @@ EXPORT_SYMBOL_GPL(xnthread_start);
  */
 int xnthread_set_mode(struct xnthread *thread, int clrmask, int setmask)
 {
-       struct xnthread *curr = xnsched_current_thread();
+       struct xnthread *curr;
        unsigned long oldmode;
        spl_t s;
 
        xnlock_get_irqsave(&nklock, s);
 
+       curr = xnsched_current_thread();
        oldmode = xnthread_state_flags(thread) & XNTHREAD_MODE_BITS;
        xnthread_clear_state(thread, clrmask & XNTHREAD_MODE_BITS);
        xnthread_set_state(thread, setmask & XNTHREAD_MODE_BITS);
@@ -824,7 +837,7 @@ void xnthread_suspend(struct xnthread *thread, int mask,
                                goto abort;
                        if (thread == sched->curr &&
                            (oldstate & (XNTRAPLB|XNLOCK)) == (XNTRAPLB|XNLOCK))
-                               goto abort;
+                               goto lock_break;
                }
                xnthread_clear_info(thread,
                                    
XNRMID|XNTIMEO|XNBREAK|XNWAKEN|XNROBBED|XNKICKED);
@@ -941,6 +954,12 @@ out:
        xnlock_put_irqrestore(&nklock, s);
        return;
 
+lock_break:
+       if (xnthread_test_state(thread, XNWARN) &&
+           !xnthread_test_info(thread, XNLBALERT)) {
+               xnthread_set_info(thread, XNLBALERT);
+               xnshadow_send_sig(thread, SIGDEBUG, SIGDEBUG_LOCK_BREAK);
+       }
 abort:
        if (wchan) {
                thread->wchan = wchan;


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

Reply via email to