On 09/11/2011 04:29 PM, Jan Kiszka wrote:
> On 2011-09-11 16:24, Gilles Chanteperdrix wrote:
>> On 09/11/2011 12:50 PM, Jan Kiszka wrote:
>>> Hi all,
>>>
>>> just looked into the hrescnt issue again, specifically the corner case
>>> of a shadow thread switching from real-time policy to SCHED_OTHER.
>>
>> Doing this while holding a mutex looks invalid.
> 
> Looking at POSIX e.g., is there anything in the spec that makes this
> invalid? If the kernel preserves or established proper priority
> boosting, I do not see what could break in principle.
> 
> It is nothing I would design into some app, but we should somehow handle
> it (doc update or code adjustments).
> 
>> If we do not do it, the current code is valid.
> 
> Except for its dependency on XNOTHER which is not updated on RT->NORMAL
> transitions.

The fact that this update did not take place made the code work. No 
negative rescnt could happen with that code.

Anyway, here is a patch to allow switching back from RT to NORMAL, but 
send a SIGDEBUG to a thread attempting to release a mutex while its 
counter is already 0. We end up avoiding a big chunk of code that would 
have been useful for a really strange corner case.

diff --git a/examples/native/sigdebug.c b/examples/native/sigdebug.c
index e20714b..7b840f9 100644
--- a/examples/native/sigdebug.c
+++ b/examples/native/sigdebug.c
@@ -34,6 +34,8 @@ static const char *reason_str[] = {
     [SIGDEBUG_MIGRATE_PRIOINV] = "affected by priority inversion",
     [SIGDEBUG_NOMLOCK] = "missing mlockall",
     [SIGDEBUG_WATCHDOG] = "runaway thread",
+    [SIGDEBUG_SCHED_CHANGE_W_MX] =
+    "switched to SCHED_OTHER policy with mutex held",
 };
 
 void warn_upon_switch(int sig, siginfo_t *si, void *context)
diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h
index a9cdc87..5b6c764 100644
--- a/include/asm-generic/syscall.h
+++ b/include/asm-generic/syscall.h
@@ -61,6 +61,7 @@ typedef struct xnsysinfo {
 #define SIGDEBUG_MIGRATE_PRIOINV       4
 #define SIGDEBUG_NOMLOCK               5
 #define SIGDEBUG_WATCHDOG              6
+#define SIGDEBUG_SCHED_CHANGE_W_MX      7
 
 #ifdef __KERNEL__
 
diff --git a/include/nucleus/sched-idle.h b/include/nucleus/sched-idle.h
index 6399a17..3cc7185 100644
--- a/include/nucleus/sched-idle.h
+++ b/include/nucleus/sched-idle.h
@@ -39,6 +39,7 @@ extern struct xnsched_class xnsched_class_idle;
 static inline void __xnsched_idle_setparam(struct xnthread *thread,
                                           const union xnsched_policy_param *p)
 {
+       xnthread_set_state(thread, XNOTHER);
        thread->cprio = p->idle.prio;
 }
 
diff --git a/include/nucleus/sched-rt.h b/include/nucleus/sched-rt.h
index 71f655c..d17b058 100644
--- a/include/nucleus/sched-rt.h
+++ b/include/nucleus/sched-rt.h
@@ -86,6 +86,10 @@ static inline void __xnsched_rt_setparam(struct xnthread 
*thread,
                                         const union xnsched_policy_param *p)
 {
        thread->cprio = p->rt.prio;
+       if (thread->cprio)
+               xnthread_clear_state(thread, XNOTHER);
+       else
+               xnthread_set_state(thread, XNOTHER);
 }
 
 static inline void __xnsched_rt_getparam(struct xnthread *thread,
diff --git a/ksrc/nucleus/pod.c b/ksrc/nucleus/pod.c
index 9a02e80..d19999f 100644
--- a/ksrc/nucleus/pod.c
+++ b/ksrc/nucleus/pod.c
@@ -1896,16 +1896,6 @@ int __xnpod_set_thread_schedparam(struct xnthread 
*thread,
                xnsched_putback(thread);
 
 #ifdef CONFIG_XENO_OPT_PERVASIVE
-       /*
-        * A non-real-time shadow may upgrade to real-time FIFO
-        * scheduling, but the latter may never downgrade to
-        * SCHED_NORMAL Xenomai-wise. In the valid case, we clear
-        * XNOTHER to reflect the change. Note that we keep handling
-        * non real-time shadow specifics in higher code layers, not
-        * to pollute the core scheduler with peculiarities.
-        */
-       if (sched_class == &xnsched_class_rt && sched_param->rt.prio > 0)
-               xnthread_clear_state(thread, XNOTHER);
        if (propagate) {
                if (xnthread_test_state(thread, XNRELAX))
                        xnshadow_renice(thread);
diff --git a/ksrc/nucleus/sched-sporadic.c b/ksrc/nucleus/sched-sporadic.c
index fd37c21..587be4a 100644
--- a/ksrc/nucleus/sched-sporadic.c
+++ b/ksrc/nucleus/sched-sporadic.c
@@ -258,6 +258,7 @@ static void xnsched_sporadic_setparam(struct xnthread 
*thread,
                }
        }
 
+       xnthread_clear_state(thread, XNOTHER);
        thread->cprio = p->pss.current_prio;
 }
 
diff --git a/ksrc/nucleus/sched-tp.c b/ksrc/nucleus/sched-tp.c
index 43a548e..2423e81 100644
--- a/ksrc/nucleus/sched-tp.c
+++ b/ksrc/nucleus/sched-tp.c
@@ -100,6 +100,7 @@ static void xnsched_tp_setparam(struct xnthread *thread,
 {
        struct xnsched *sched = thread->sched;
 
+       xnthread_clear_state(thread, XNOTHER);
        thread->tps = &sched->tp.partitions[p->tp.ptid];
        thread->cprio = p->tp.prio;
 }
diff --git a/ksrc/nucleus/synch.c b/ksrc/nucleus/synch.c
index b956e46..e3442a4 100644
--- a/ksrc/nucleus/synch.c
+++ b/ksrc/nucleus/synch.c
@@ -684,9 +684,13 @@ xnsynch_release_thread(struct xnsynch *synch, struct 
xnthread *lastowner)
 
        XENO_BUGON(NUCLEUS, !testbits(synch->status, XNSYNCH_OWNER));
 
-       if (xnthread_test_state(lastowner, XNOTHER))
-               xnthread_dec_rescnt(lastowner);
-       XENO_BUGON(NUCLEUS, xnthread_get_rescnt(lastowner) < 0);
+       if (xnthread_test_state(lastowner, XNOTHER)) {
+               if (xnthread_get_rescnt(lastowner))
+                       xnshadow_send_sig(lastowner, SIGDEBUG,
+                                         SIGDEBUG_SCHED_CHANGE_W_MX, 1);
+               else
+                       xnthread_dec_rescnt(lastowner);
+       }
        lastownerh = xnthread_handle(lastowner);
 
        if (use_fastlock &&


-- 
                                                                Gilles.

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

Reply via email to