All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai-core] Policy switching and XNOTHER maintenance
@ 2011-09-11 10:50 Jan Kiszka
  2011-09-11 11:49 ` Jan Kiszka
  2011-09-11 14:24 ` Gilles Chanteperdrix
  0 siblings, 2 replies; 14+ messages in thread
From: Jan Kiszka @ 2011-09-11 10:50 UTC (permalink / raw)
  To: xenomai-core

[-- Attachment #1: Type: text/plain, Size: 771 bytes --]

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.

Looks like we don't support this at all ATM:

do_setsched_event ignores events that enabled SCHED_OTHER, and the
XNOTHER flag is only set on xnshadow_map, not updated anywhere else.
Fixing this is not straightforward as that flag resides in a state
variable that is owned by the thread (ie. updated non-atomically) while
do_setsched_event can also be called over different contexts.

Or am I missing something?

In the light of this, I would vote for reverting f9bfab3457 ("only
update rescnt for XNOTHER threads") as it only adds conditional branches
to the hot paths without solving the issue.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-11 10:50 [Xenomai-core] Policy switching and XNOTHER maintenance Jan Kiszka
@ 2011-09-11 11:49 ` Jan Kiszka
  2011-09-11 14:24 ` Gilles Chanteperdrix
  1 sibling, 0 replies; 14+ messages in thread
From: Jan Kiszka @ 2011-09-11 11:49 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai-core

[-- Attachment #1: Type: text/plain, Size: 1195 bytes --]

On 2011-09-11 12:50, 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.
> 
> Looks like we don't support this at all ATM:
> 
> do_setsched_event ignores events that enabled SCHED_OTHER, and the
> XNOTHER flag is only set on xnshadow_map, not updated anywhere else.
> Fixing this is not straightforward as that flag resides in a state
> variable that is owned by the thread (ie. updated non-atomically) while
> do_setsched_event can also be called over different contexts.

OK, it just takes nklock to update the thread state.

> 
> Or am I missing something?

From __xnpod_set_thread_schedparam:

"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."

What prevents us from setting XNOTHER if the priority drops to 0, i.e.
the Linux task re-enters SCHED_NORMAL (while Xenomai will still schedule
it via its RT class of course)? We cannot deny such a transition on the
Linux side anyway, can we?

Jan



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-11 10:50 [Xenomai-core] Policy switching and XNOTHER maintenance Jan Kiszka
  2011-09-11 11:49 ` Jan Kiszka
@ 2011-09-11 14:24 ` Gilles Chanteperdrix
  2011-09-11 14:29   ` Jan Kiszka
  1 sibling, 1 reply; 14+ messages in thread
From: Gilles Chanteperdrix @ 2011-09-11 14:24 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai-core

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. If we do not do it, the
current code is valid.

-- 
                                                                Gilles.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-11 14:24 ` Gilles Chanteperdrix
@ 2011-09-11 14:29   ` Jan Kiszka
  2011-09-16 20:13     ` Gilles Chanteperdrix
  0 siblings, 1 reply; 14+ messages in thread
From: Jan Kiszka @ 2011-09-11 14:29 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

[-- Attachment #1: Type: text/plain, Size: 770 bytes --]

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.

Jan



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-11 14:29   ` Jan Kiszka
@ 2011-09-16 20:13     ` Gilles Chanteperdrix
  2011-09-16 20:39       ` Gilles Chanteperdrix
  0 siblings, 1 reply; 14+ messages in thread
From: Gilles Chanteperdrix @ 2011-09-16 20:13 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai-core

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.


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-16 20:13     ` Gilles Chanteperdrix
@ 2011-09-16 20:39       ` Gilles Chanteperdrix
  2011-09-18 14:02         ` Philippe Gerum
  0 siblings, 1 reply; 14+ messages in thread
From: Gilles Chanteperdrix @ 2011-09-16 20:39 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai-core

On 09/16/2011 10:13 PM, Gilles Chanteperdrix wrote:
> 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.
> 

Here comes version 2:
diff --git a/include/nucleus/sched-idle.h b/include/nucleus/sched-idle.h
index 6399a17..417170f 100644
--- a/include/nucleus/sched-idle.h
+++ b/include/nucleus/sched-idle.h
@@ -39,6 +39,8 @@ extern struct xnsched_class xnsched_class_idle;
 static inline void __xnsched_idle_setparam(struct xnthread *thread,
 					   const union xnsched_policy_param *p)
 {
+	if (xnthread_test_state(thread, XNSHADOW))
+		xnthread_clear_state(thread, XNOTHER);
 	thread->cprio = p->idle.prio;
 }
 
diff --git a/include/nucleus/sched-rt.h b/include/nucleus/sched-rt.h
index 71f655c..cc1cefa 100644
--- a/include/nucleus/sched-rt.h
+++ b/include/nucleus/sched-rt.h
@@ -86,6 +86,12 @@ static inline void __xnsched_rt_setparam(struct xnthread *thread,
 					 const union xnsched_policy_param *p)
 {
 	thread->cprio = p->rt.prio;
+	if (xnthread_test_state(thread, XNSHADOW)) {
+		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..ffc9bab 100644
--- a/ksrc/nucleus/sched-sporadic.c
+++ b/ksrc/nucleus/sched-sporadic.c
@@ -258,6 +258,8 @@ static void xnsched_sporadic_setparam(struct xnthread *thread,
 		}
 	}
 
+	if (xnthread_test_state(thread, XNSHADOW))
+		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..a2af1d3 100644
--- a/ksrc/nucleus/sched-tp.c
+++ b/ksrc/nucleus/sched-tp.c
@@ -100,6 +100,8 @@ static void xnsched_tp_setparam(struct xnthread *thread,
 {
 	struct xnsched *sched = thread->sched;
 
+	if (xnthread_test_state(thread, XNSHADOW))
+		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..47bc0c5 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) == 0)
+			xnshadow_send_sig(lastowner, SIGDEBUG,
+					  SIGDEBUG_MIGRATE_PRIOINV, 1);
+		else
+			xnthread_dec_rescnt(lastowner);
+	}
 	lastownerh = xnthread_handle(lastowner);
 
 	if (use_fastlock &&



-- 
                                                                Gilles.


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-16 20:39       ` Gilles Chanteperdrix
@ 2011-09-18 14:02         ` Philippe Gerum
  2011-09-18 14:34           ` Jan Kiszka
  0 siblings, 1 reply; 14+ messages in thread
From: Philippe Gerum @ 2011-09-18 14:02 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Jan Kiszka, xenomai-core

On Fri, 2011-09-16 at 22:39 +0200, Gilles Chanteperdrix wrote:
> On 09/16/2011 10:13 PM, Gilles Chanteperdrix wrote:
> > 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.
> > 
> 
> Here comes version 2:
> diff --git a/include/nucleus/sched-idle.h b/include/nucleus/sched-idle.h
> index 6399a17..417170f 100644
> --- a/include/nucleus/sched-idle.h
> +++ b/include/nucleus/sched-idle.h
> @@ -39,6 +39,8 @@ extern struct xnsched_class xnsched_class_idle;
>  static inline void __xnsched_idle_setparam(struct xnthread *thread,
>  					   const union xnsched_policy_param *p)
>  {
> +	if (xnthread_test_state(thread, XNSHADOW))
> +		xnthread_clear_state(thread, XNOTHER);
>  	thread->cprio = p->idle.prio;
>  }
>  
> diff --git a/include/nucleus/sched-rt.h b/include/nucleus/sched-rt.h
> index 71f655c..cc1cefa 100644
> --- a/include/nucleus/sched-rt.h
> +++ b/include/nucleus/sched-rt.h
> @@ -86,6 +86,12 @@ static inline void __xnsched_rt_setparam(struct xnthread *thread,
>  					 const union xnsched_policy_param *p)
>  {
>  	thread->cprio = p->rt.prio;
> +	if (xnthread_test_state(thread, XNSHADOW)) {
> +		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..ffc9bab 100644
> --- a/ksrc/nucleus/sched-sporadic.c
> +++ b/ksrc/nucleus/sched-sporadic.c
> @@ -258,6 +258,8 @@ static void xnsched_sporadic_setparam(struct xnthread *thread,
>  		}
>  	}
>  
> +	if (xnthread_test_state(thread, XNSHADOW))
> +		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..a2af1d3 100644
> --- a/ksrc/nucleus/sched-tp.c
> +++ b/ksrc/nucleus/sched-tp.c
> @@ -100,6 +100,8 @@ static void xnsched_tp_setparam(struct xnthread *thread,
>  {
>  	struct xnsched *sched = thread->sched;
>  
> +	if (xnthread_test_state(thread, XNSHADOW))
> +		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..47bc0c5 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) == 0)
> +			xnshadow_send_sig(lastowner, SIGDEBUG,
> +					  SIGDEBUG_MIGRATE_PRIOINV, 1);
> +		else
> +			xnthread_dec_rescnt(lastowner);
> +	}
>  	lastownerh = xnthread_handle(lastowner);
>  
>  	if (use_fastlock &&
> 
> 
> 

Agreed, the logic of this patch sounds right. Switching from -rt to -nrt
while holding a -rt mutex is pathological behavior. We don't have to
support apps implementing voluntary priority inversion.

-- 
Philippe.




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-18 14:02         ` Philippe Gerum
@ 2011-09-18 14:34           ` Jan Kiszka
  2011-09-18 15:10             ` Philippe Gerum
  0 siblings, 1 reply; 14+ messages in thread
From: Jan Kiszka @ 2011-09-18 14:34 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai-core

[-- Attachment #1: Type: text/plain, Size: 6283 bytes --]

On 2011-09-18 16:02, Philippe Gerum wrote:
> On Fri, 2011-09-16 at 22:39 +0200, Gilles Chanteperdrix wrote:
>> On 09/16/2011 10:13 PM, Gilles Chanteperdrix wrote:
>>> 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.
>>>
>>
>> Here comes version 2:
>> diff --git a/include/nucleus/sched-idle.h b/include/nucleus/sched-idle.h
>> index 6399a17..417170f 100644
>> --- a/include/nucleus/sched-idle.h
>> +++ b/include/nucleus/sched-idle.h
>> @@ -39,6 +39,8 @@ extern struct xnsched_class xnsched_class_idle;
>>  static inline void __xnsched_idle_setparam(struct xnthread *thread,
>>  					   const union xnsched_policy_param *p)
>>  {
>> +	if (xnthread_test_state(thread, XNSHADOW))
>> +		xnthread_clear_state(thread, XNOTHER);
>>  	thread->cprio = p->idle.prio;
>>  }
>>  
>> diff --git a/include/nucleus/sched-rt.h b/include/nucleus/sched-rt.h
>> index 71f655c..cc1cefa 100644
>> --- a/include/nucleus/sched-rt.h
>> +++ b/include/nucleus/sched-rt.h
>> @@ -86,6 +86,12 @@ static inline void __xnsched_rt_setparam(struct xnthread *thread,
>>  					 const union xnsched_policy_param *p)
>>  {
>>  	thread->cprio = p->rt.prio;
>> +	if (xnthread_test_state(thread, XNSHADOW)) {
>> +		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..ffc9bab 100644
>> --- a/ksrc/nucleus/sched-sporadic.c
>> +++ b/ksrc/nucleus/sched-sporadic.c
>> @@ -258,6 +258,8 @@ static void xnsched_sporadic_setparam(struct xnthread *thread,
>>  		}
>>  	}
>>  
>> +	if (xnthread_test_state(thread, XNSHADOW))
>> +		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..a2af1d3 100644
>> --- a/ksrc/nucleus/sched-tp.c
>> +++ b/ksrc/nucleus/sched-tp.c
>> @@ -100,6 +100,8 @@ static void xnsched_tp_setparam(struct xnthread *thread,
>>  {
>>  	struct xnsched *sched = thread->sched;
>>  
>> +	if (xnthread_test_state(thread, XNSHADOW))
>> +		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..47bc0c5 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) == 0)
>> +			xnshadow_send_sig(lastowner, SIGDEBUG,
>> +					  SIGDEBUG_MIGRATE_PRIOINV, 1);
>> +		else
>> +			xnthread_dec_rescnt(lastowner);
>> +	}
>>  	lastownerh = xnthread_handle(lastowner);
>>  
>>  	if (use_fastlock &&
>>
>>
>>
> 
> Agreed, the logic of this patch sounds right. Switching from -rt to -nrt
> while holding a -rt mutex is pathological behavior. We don't have to
> support apps implementing voluntary priority inversion.
> 

No concerns either.

Now we just need

diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
index 21cc191..27bc829 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -2756,9 +2756,12 @@ static inline void do_setsched_event(struct task_struct *p, int priority)
 	union xnsched_policy_param param;
 	struct xnsched *sched;
 
-	if (!thread || p->policy != SCHED_FIFO)
+	if (!thread)
 		return;
 
+	if (p->policy == SCHED_FIFO)
+		priority = 0;
+
 	/*
 	 * Linux's priority scale is a subset of the core pod's
 	 * priority scale, so there is no need to bound the priority


to track the policy change when done via Linux.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-18 14:34           ` Jan Kiszka
@ 2011-09-18 15:10             ` Philippe Gerum
  2011-09-18 15:11               ` Jan Kiszka
  0 siblings, 1 reply; 14+ messages in thread
From: Philippe Gerum @ 2011-09-18 15:10 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai-core

On Sun, 2011-09-18 at 16:34 +0200, Jan Kiszka wrote:
> On 2011-09-18 16:02, Philippe Gerum wrote:
> > On Fri, 2011-09-16 at 22:39 +0200, Gilles Chanteperdrix wrote:
> >> On 09/16/2011 10:13 PM, Gilles Chanteperdrix wrote:
> >>> 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.
> >>>
> >>
> >> Here comes version 2:
> >> diff --git a/include/nucleus/sched-idle.h b/include/nucleus/sched-idle.h
> >> index 6399a17..417170f 100644
> >> --- a/include/nucleus/sched-idle.h
> >> +++ b/include/nucleus/sched-idle.h
> >> @@ -39,6 +39,8 @@ extern struct xnsched_class xnsched_class_idle;
> >>  static inline void __xnsched_idle_setparam(struct xnthread *thread,
> >>  					   const union xnsched_policy_param *p)
> >>  {
> >> +	if (xnthread_test_state(thread, XNSHADOW))
> >> +		xnthread_clear_state(thread, XNOTHER);
> >>  	thread->cprio = p->idle.prio;
> >>  }
> >>  
> >> diff --git a/include/nucleus/sched-rt.h b/include/nucleus/sched-rt.h
> >> index 71f655c..cc1cefa 100644
> >> --- a/include/nucleus/sched-rt.h
> >> +++ b/include/nucleus/sched-rt.h
> >> @@ -86,6 +86,12 @@ static inline void __xnsched_rt_setparam(struct xnthread *thread,
> >>  					 const union xnsched_policy_param *p)
> >>  {
> >>  	thread->cprio = p->rt.prio;
> >> +	if (xnthread_test_state(thread, XNSHADOW)) {
> >> +		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..ffc9bab 100644
> >> --- a/ksrc/nucleus/sched-sporadic.c
> >> +++ b/ksrc/nucleus/sched-sporadic.c
> >> @@ -258,6 +258,8 @@ static void xnsched_sporadic_setparam(struct xnthread *thread,
> >>  		}
> >>  	}
> >>  
> >> +	if (xnthread_test_state(thread, XNSHADOW))
> >> +		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..a2af1d3 100644
> >> --- a/ksrc/nucleus/sched-tp.c
> >> +++ b/ksrc/nucleus/sched-tp.c
> >> @@ -100,6 +100,8 @@ static void xnsched_tp_setparam(struct xnthread *thread,
> >>  {
> >>  	struct xnsched *sched = thread->sched;
> >>  
> >> +	if (xnthread_test_state(thread, XNSHADOW))
> >> +		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..47bc0c5 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) == 0)
> >> +			xnshadow_send_sig(lastowner, SIGDEBUG,
> >> +					  SIGDEBUG_MIGRATE_PRIOINV, 1);
> >> +		else
> >> +			xnthread_dec_rescnt(lastowner);
> >> +	}
> >>  	lastownerh = xnthread_handle(lastowner);
> >>  
> >>  	if (use_fastlock &&
> >>
> >>
> >>
> > 
> > Agreed, the logic of this patch sounds right. Switching from -rt to -nrt
> > while holding a -rt mutex is pathological behavior. We don't have to
> > support apps implementing voluntary priority inversion.
> > 
> 
> No concerns either.
> 
> Now we just need
> 
> diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
> index 21cc191..27bc829 100644
> --- a/ksrc/nucleus/shadow.c
> +++ b/ksrc/nucleus/shadow.c
> @@ -2756,9 +2756,12 @@ static inline void do_setsched_event(struct task_struct *p, int priority)
>  	union xnsched_policy_param param;
>  	struct xnsched *sched;
>  
> -	if (!thread || p->policy != SCHED_FIFO)
> +	if (!thread)
>  		return;
>  
> +	if (p->policy == SCHED_FIFO)
			^^
		inverted?

> +		priority = 0;
> +
>  	/*
>  	 * Linux's priority scale is a subset of the core pod's
>  	 * priority scale, so there is no need to bound the priority
> 
> 
> to track the policy change when done via Linux.
> 
> Jan
> 

-- 
Philippe.




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-18 15:10             ` Philippe Gerum
@ 2011-09-18 15:11               ` Jan Kiszka
  2011-09-18 15:13                 ` Jan Kiszka
  0 siblings, 1 reply; 14+ messages in thread
From: Jan Kiszka @ 2011-09-18 15:11 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai-core

[-- Attachment #1: Type: text/plain, Size: 6550 bytes --]

On 2011-09-18 17:10, Philippe Gerum wrote:
> On Sun, 2011-09-18 at 16:34 +0200, Jan Kiszka wrote:
>> On 2011-09-18 16:02, Philippe Gerum wrote:
>>> On Fri, 2011-09-16 at 22:39 +0200, Gilles Chanteperdrix wrote:
>>>> On 09/16/2011 10:13 PM, Gilles Chanteperdrix wrote:
>>>>> 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.
>>>>>
>>>>
>>>> Here comes version 2:
>>>> diff --git a/include/nucleus/sched-idle.h b/include/nucleus/sched-idle.h
>>>> index 6399a17..417170f 100644
>>>> --- a/include/nucleus/sched-idle.h
>>>> +++ b/include/nucleus/sched-idle.h
>>>> @@ -39,6 +39,8 @@ extern struct xnsched_class xnsched_class_idle;
>>>>  static inline void __xnsched_idle_setparam(struct xnthread *thread,
>>>>  					   const union xnsched_policy_param *p)
>>>>  {
>>>> +	if (xnthread_test_state(thread, XNSHADOW))
>>>> +		xnthread_clear_state(thread, XNOTHER);
>>>>  	thread->cprio = p->idle.prio;
>>>>  }
>>>>  
>>>> diff --git a/include/nucleus/sched-rt.h b/include/nucleus/sched-rt.h
>>>> index 71f655c..cc1cefa 100644
>>>> --- a/include/nucleus/sched-rt.h
>>>> +++ b/include/nucleus/sched-rt.h
>>>> @@ -86,6 +86,12 @@ static inline void __xnsched_rt_setparam(struct xnthread *thread,
>>>>  					 const union xnsched_policy_param *p)
>>>>  {
>>>>  	thread->cprio = p->rt.prio;
>>>> +	if (xnthread_test_state(thread, XNSHADOW)) {
>>>> +		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..ffc9bab 100644
>>>> --- a/ksrc/nucleus/sched-sporadic.c
>>>> +++ b/ksrc/nucleus/sched-sporadic.c
>>>> @@ -258,6 +258,8 @@ static void xnsched_sporadic_setparam(struct xnthread *thread,
>>>>  		}
>>>>  	}
>>>>  
>>>> +	if (xnthread_test_state(thread, XNSHADOW))
>>>> +		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..a2af1d3 100644
>>>> --- a/ksrc/nucleus/sched-tp.c
>>>> +++ b/ksrc/nucleus/sched-tp.c
>>>> @@ -100,6 +100,8 @@ static void xnsched_tp_setparam(struct xnthread *thread,
>>>>  {
>>>>  	struct xnsched *sched = thread->sched;
>>>>  
>>>> +	if (xnthread_test_state(thread, XNSHADOW))
>>>> +		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..47bc0c5 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) == 0)
>>>> +			xnshadow_send_sig(lastowner, SIGDEBUG,
>>>> +					  SIGDEBUG_MIGRATE_PRIOINV, 1);
>>>> +		else
>>>> +			xnthread_dec_rescnt(lastowner);
>>>> +	}
>>>>  	lastownerh = xnthread_handle(lastowner);
>>>>  
>>>>  	if (use_fastlock &&
>>>>
>>>>
>>>>
>>>
>>> Agreed, the logic of this patch sounds right. Switching from -rt to -nrt
>>> while holding a -rt mutex is pathological behavior. We don't have to
>>> support apps implementing voluntary priority inversion.
>>>
>>
>> No concerns either.
>>
>> Now we just need
>>
>> diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
>> index 21cc191..27bc829 100644
>> --- a/ksrc/nucleus/shadow.c
>> +++ b/ksrc/nucleus/shadow.c
>> @@ -2756,9 +2756,12 @@ static inline void do_setsched_event(struct task_struct *p, int priority)
>>  	union xnsched_policy_param param;
>>  	struct xnsched *sched;
>>  
>> -	if (!thread || p->policy != SCHED_FIFO)
>> +	if (!thread)
>>  		return;
>>  
>> +	if (p->policy == SCHED_FIFO)
> 			^^
> 		inverted?

Of course.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-18 15:11               ` Jan Kiszka
@ 2011-09-18 15:13                 ` Jan Kiszka
  2011-09-18 15:18                   ` Gilles Chanteperdrix
  0 siblings, 1 reply; 14+ messages in thread
From: Jan Kiszka @ 2011-09-18 15:13 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai-core

[-- Attachment #1: Type: text/plain, Size: 6853 bytes --]

On 2011-09-18 17:11, Jan Kiszka wrote:
> On 2011-09-18 17:10, Philippe Gerum wrote:
>> On Sun, 2011-09-18 at 16:34 +0200, Jan Kiszka wrote:
>>> On 2011-09-18 16:02, Philippe Gerum wrote:
>>>> On Fri, 2011-09-16 at 22:39 +0200, Gilles Chanteperdrix wrote:
>>>>> On 09/16/2011 10:13 PM, Gilles Chanteperdrix wrote:
>>>>>> 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.
>>>>>>
>>>>>
>>>>> Here comes version 2:
>>>>> diff --git a/include/nucleus/sched-idle.h b/include/nucleus/sched-idle.h
>>>>> index 6399a17..417170f 100644
>>>>> --- a/include/nucleus/sched-idle.h
>>>>> +++ b/include/nucleus/sched-idle.h
>>>>> @@ -39,6 +39,8 @@ extern struct xnsched_class xnsched_class_idle;
>>>>>  static inline void __xnsched_idle_setparam(struct xnthread *thread,
>>>>>  					   const union xnsched_policy_param *p)
>>>>>  {
>>>>> +	if (xnthread_test_state(thread, XNSHADOW))
>>>>> +		xnthread_clear_state(thread, XNOTHER);
>>>>>  	thread->cprio = p->idle.prio;
>>>>>  }
>>>>>  
>>>>> diff --git a/include/nucleus/sched-rt.h b/include/nucleus/sched-rt.h
>>>>> index 71f655c..cc1cefa 100644
>>>>> --- a/include/nucleus/sched-rt.h
>>>>> +++ b/include/nucleus/sched-rt.h
>>>>> @@ -86,6 +86,12 @@ static inline void __xnsched_rt_setparam(struct xnthread *thread,
>>>>>  					 const union xnsched_policy_param *p)
>>>>>  {
>>>>>  	thread->cprio = p->rt.prio;
>>>>> +	if (xnthread_test_state(thread, XNSHADOW)) {
>>>>> +		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..ffc9bab 100644
>>>>> --- a/ksrc/nucleus/sched-sporadic.c
>>>>> +++ b/ksrc/nucleus/sched-sporadic.c
>>>>> @@ -258,6 +258,8 @@ static void xnsched_sporadic_setparam(struct xnthread *thread,
>>>>>  		}
>>>>>  	}
>>>>>  
>>>>> +	if (xnthread_test_state(thread, XNSHADOW))
>>>>> +		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..a2af1d3 100644
>>>>> --- a/ksrc/nucleus/sched-tp.c
>>>>> +++ b/ksrc/nucleus/sched-tp.c
>>>>> @@ -100,6 +100,8 @@ static void xnsched_tp_setparam(struct xnthread *thread,
>>>>>  {
>>>>>  	struct xnsched *sched = thread->sched;
>>>>>  
>>>>> +	if (xnthread_test_state(thread, XNSHADOW))
>>>>> +		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..47bc0c5 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) == 0)
>>>>> +			xnshadow_send_sig(lastowner, SIGDEBUG,
>>>>> +					  SIGDEBUG_MIGRATE_PRIOINV, 1);
>>>>> +		else
>>>>> +			xnthread_dec_rescnt(lastowner);
>>>>> +	}
>>>>>  	lastownerh = xnthread_handle(lastowner);
>>>>>  
>>>>>  	if (use_fastlock &&
>>>>>
>>>>>
>>>>>
>>>>
>>>> Agreed, the logic of this patch sounds right. Switching from -rt to -nrt
>>>> while holding a -rt mutex is pathological behavior. We don't have to
>>>> support apps implementing voluntary priority inversion.
>>>>
>>>
>>> No concerns either.
>>>
>>> Now we just need
>>>
>>> diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
>>> index 21cc191..27bc829 100644
>>> --- a/ksrc/nucleus/shadow.c
>>> +++ b/ksrc/nucleus/shadow.c
>>> @@ -2756,9 +2756,12 @@ static inline void do_setsched_event(struct task_struct *p, int priority)
>>>  	union xnsched_policy_param param;
>>>  	struct xnsched *sched;
>>>  
>>> -	if (!thread || p->policy != SCHED_FIFO)
>>> +	if (!thread)
>>>  		return;
>>>  
>>> +	if (p->policy == SCHED_FIFO)
>> 			^^
>> 		inverted?
> 
> Of course.

Thinking about SCHED_RR or other policies, this still looks fishy and
needs some thoughts.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-18 15:13                 ` Jan Kiszka
@ 2011-09-18 15:18                   ` Gilles Chanteperdrix
  2011-09-18 15:24                     ` Jan Kiszka
  0 siblings, 1 reply; 14+ messages in thread
From: Gilles Chanteperdrix @ 2011-09-18 15:18 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai-core

On 09/18/2011 05:13 PM, Jan Kiszka wrote:
> On 2011-09-18 17:11, Jan Kiszka wrote:
>> On 2011-09-18 17:10, Philippe Gerum wrote:
>>> On Sun, 2011-09-18 at 16:34 +0200, Jan Kiszka wrote:
>>>> On 2011-09-18 16:02, Philippe Gerum wrote:
>>>>> On Fri, 2011-09-16 at 22:39 +0200, Gilles Chanteperdrix wrote:
>>>>>> On 09/16/2011 10:13 PM, Gilles Chanteperdrix wrote:
>>>>>>> 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.
>>>>>>>
>>>>>>
>>>>>> Here comes version 2:
>>>>>> diff --git a/include/nucleus/sched-idle.h b/include/nucleus/sched-idle.h
>>>>>> index 6399a17..417170f 100644
>>>>>> --- a/include/nucleus/sched-idle.h
>>>>>> +++ b/include/nucleus/sched-idle.h
>>>>>> @@ -39,6 +39,8 @@ extern struct xnsched_class xnsched_class_idle;
>>>>>>  static inline void __xnsched_idle_setparam(struct xnthread *thread,
>>>>>>  					   const union xnsched_policy_param *p)
>>>>>>  {
>>>>>> +	if (xnthread_test_state(thread, XNSHADOW))
>>>>>> +		xnthread_clear_state(thread, XNOTHER);
>>>>>>  	thread->cprio = p->idle.prio;
>>>>>>  }
>>>>>>  
>>>>>> diff --git a/include/nucleus/sched-rt.h b/include/nucleus/sched-rt.h
>>>>>> index 71f655c..cc1cefa 100644
>>>>>> --- a/include/nucleus/sched-rt.h
>>>>>> +++ b/include/nucleus/sched-rt.h
>>>>>> @@ -86,6 +86,12 @@ static inline void __xnsched_rt_setparam(struct xnthread *thread,
>>>>>>  					 const union xnsched_policy_param *p)
>>>>>>  {
>>>>>>  	thread->cprio = p->rt.prio;
>>>>>> +	if (xnthread_test_state(thread, XNSHADOW)) {
>>>>>> +		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..ffc9bab 100644
>>>>>> --- a/ksrc/nucleus/sched-sporadic.c
>>>>>> +++ b/ksrc/nucleus/sched-sporadic.c
>>>>>> @@ -258,6 +258,8 @@ static void xnsched_sporadic_setparam(struct xnthread *thread,
>>>>>>  		}
>>>>>>  	}
>>>>>>  
>>>>>> +	if (xnthread_test_state(thread, XNSHADOW))
>>>>>> +		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..a2af1d3 100644
>>>>>> --- a/ksrc/nucleus/sched-tp.c
>>>>>> +++ b/ksrc/nucleus/sched-tp.c
>>>>>> @@ -100,6 +100,8 @@ static void xnsched_tp_setparam(struct xnthread *thread,
>>>>>>  {
>>>>>>  	struct xnsched *sched = thread->sched;
>>>>>>  
>>>>>> +	if (xnthread_test_state(thread, XNSHADOW))
>>>>>> +		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..47bc0c5 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) == 0)
>>>>>> +			xnshadow_send_sig(lastowner, SIGDEBUG,
>>>>>> +					  SIGDEBUG_MIGRATE_PRIOINV, 1);
>>>>>> +		else
>>>>>> +			xnthread_dec_rescnt(lastowner);
>>>>>> +	}
>>>>>>  	lastownerh = xnthread_handle(lastowner);
>>>>>>  
>>>>>>  	if (use_fastlock &&
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>> Agreed, the logic of this patch sounds right. Switching from -rt to -nrt
>>>>> while holding a -rt mutex is pathological behavior. We don't have to
>>>>> support apps implementing voluntary priority inversion.
>>>>>
>>>>
>>>> No concerns either.
>>>>
>>>> Now we just need
>>>>
>>>> diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
>>>> index 21cc191..27bc829 100644
>>>> --- a/ksrc/nucleus/shadow.c
>>>> +++ b/ksrc/nucleus/shadow.c
>>>> @@ -2756,9 +2756,12 @@ static inline void do_setsched_event(struct task_struct *p, int priority)
>>>>  	union xnsched_policy_param param;
>>>>  	struct xnsched *sched;
>>>>  
>>>> -	if (!thread || p->policy != SCHED_FIFO)
>>>> +	if (!thread)
>>>>  		return;
>>>>  
>>>> +	if (p->policy == SCHED_FIFO)
>>> 			^^
>>> 		inverted?
>>
>> Of course.
> 
> Thinking about SCHED_RR or other policies, this still looks fishy and
> needs some thoughts.

What about:

diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
index 21cc191..7fe44a1 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -2756,9 +2756,12 @@ static inline void do_setsched_event(struct task_struct *p, int priority)
 	union xnsched_policy_param param;
 	struct xnsched *sched;
 
-	if (!thread || p->policy != SCHED_FIFO)
+	if (!thread || (p->policy != SCHED_FIFO && p->policy != SCHED_OTHER))
 		return;
 
+	if (p->policy == SCHED_OTHER)
+		priority = 0;
+
 	/*
 	 * Linux's priority scale is a subset of the core pod's
 	 * priority scale, so there is no need to bound the priority


-- 
                                                                Gilles.


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-18 15:18                   ` Gilles Chanteperdrix
@ 2011-09-18 15:24                     ` Jan Kiszka
  2011-09-18 15:47                       ` Gilles Chanteperdrix
  0 siblings, 1 reply; 14+ messages in thread
From: Jan Kiszka @ 2011-09-18 15:24 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

[-- Attachment #1: Type: text/plain, Size: 8102 bytes --]

On 2011-09-18 17:18, Gilles Chanteperdrix wrote:
> On 09/18/2011 05:13 PM, Jan Kiszka wrote:
>> On 2011-09-18 17:11, Jan Kiszka wrote:
>>> On 2011-09-18 17:10, Philippe Gerum wrote:
>>>> On Sun, 2011-09-18 at 16:34 +0200, Jan Kiszka wrote:
>>>>> On 2011-09-18 16:02, Philippe Gerum wrote:
>>>>>> On Fri, 2011-09-16 at 22:39 +0200, Gilles Chanteperdrix wrote:
>>>>>>> On 09/16/2011 10:13 PM, Gilles Chanteperdrix wrote:
>>>>>>>> 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.
>>>>>>>>
>>>>>>>
>>>>>>> Here comes version 2:
>>>>>>> diff --git a/include/nucleus/sched-idle.h b/include/nucleus/sched-idle.h
>>>>>>> index 6399a17..417170f 100644
>>>>>>> --- a/include/nucleus/sched-idle.h
>>>>>>> +++ b/include/nucleus/sched-idle.h
>>>>>>> @@ -39,6 +39,8 @@ extern struct xnsched_class xnsched_class_idle;
>>>>>>>  static inline void __xnsched_idle_setparam(struct xnthread *thread,
>>>>>>>  					   const union xnsched_policy_param *p)
>>>>>>>  {
>>>>>>> +	if (xnthread_test_state(thread, XNSHADOW))
>>>>>>> +		xnthread_clear_state(thread, XNOTHER);
>>>>>>>  	thread->cprio = p->idle.prio;
>>>>>>>  }
>>>>>>>  
>>>>>>> diff --git a/include/nucleus/sched-rt.h b/include/nucleus/sched-rt.h
>>>>>>> index 71f655c..cc1cefa 100644
>>>>>>> --- a/include/nucleus/sched-rt.h
>>>>>>> +++ b/include/nucleus/sched-rt.h
>>>>>>> @@ -86,6 +86,12 @@ static inline void __xnsched_rt_setparam(struct xnthread *thread,
>>>>>>>  					 const union xnsched_policy_param *p)
>>>>>>>  {
>>>>>>>  	thread->cprio = p->rt.prio;
>>>>>>> +	if (xnthread_test_state(thread, XNSHADOW)) {
>>>>>>> +		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..ffc9bab 100644
>>>>>>> --- a/ksrc/nucleus/sched-sporadic.c
>>>>>>> +++ b/ksrc/nucleus/sched-sporadic.c
>>>>>>> @@ -258,6 +258,8 @@ static void xnsched_sporadic_setparam(struct xnthread *thread,
>>>>>>>  		}
>>>>>>>  	}
>>>>>>>  
>>>>>>> +	if (xnthread_test_state(thread, XNSHADOW))
>>>>>>> +		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..a2af1d3 100644
>>>>>>> --- a/ksrc/nucleus/sched-tp.c
>>>>>>> +++ b/ksrc/nucleus/sched-tp.c
>>>>>>> @@ -100,6 +100,8 @@ static void xnsched_tp_setparam(struct xnthread *thread,
>>>>>>>  {
>>>>>>>  	struct xnsched *sched = thread->sched;
>>>>>>>  
>>>>>>> +	if (xnthread_test_state(thread, XNSHADOW))
>>>>>>> +		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..47bc0c5 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) == 0)
>>>>>>> +			xnshadow_send_sig(lastowner, SIGDEBUG,
>>>>>>> +					  SIGDEBUG_MIGRATE_PRIOINV, 1);
>>>>>>> +		else
>>>>>>> +			xnthread_dec_rescnt(lastowner);
>>>>>>> +	}
>>>>>>>  	lastownerh = xnthread_handle(lastowner);
>>>>>>>  
>>>>>>>  	if (use_fastlock &&
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>> Agreed, the logic of this patch sounds right. Switching from -rt to -nrt
>>>>>> while holding a -rt mutex is pathological behavior. We don't have to
>>>>>> support apps implementing voluntary priority inversion.
>>>>>>
>>>>>
>>>>> No concerns either.
>>>>>
>>>>> Now we just need
>>>>>
>>>>> diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
>>>>> index 21cc191..27bc829 100644
>>>>> --- a/ksrc/nucleus/shadow.c
>>>>> +++ b/ksrc/nucleus/shadow.c
>>>>> @@ -2756,9 +2756,12 @@ static inline void do_setsched_event(struct task_struct *p, int priority)
>>>>>  	union xnsched_policy_param param;
>>>>>  	struct xnsched *sched;
>>>>>  
>>>>> -	if (!thread || p->policy != SCHED_FIFO)
>>>>> +	if (!thread)
>>>>>  		return;
>>>>>  
>>>>> +	if (p->policy == SCHED_FIFO)
>>>> 			^^
>>>> 		inverted?
>>>
>>> Of course.
>>
>> Thinking about SCHED_RR or other policies, this still looks fishy and
>> needs some thoughts.
> 
> What about:
> 
> diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
> index 21cc191..7fe44a1 100644
> --- a/ksrc/nucleus/shadow.c
> +++ b/ksrc/nucleus/shadow.c
> @@ -2756,9 +2756,12 @@ static inline void do_setsched_event(struct task_struct *p, int priority)
>  	union xnsched_policy_param param;
>  	struct xnsched *sched;
>  
> -	if (!thread || p->policy != SCHED_FIFO)
> +	if (!thread || (p->policy != SCHED_FIFO && p->policy != SCHED_OTHER))
>  		return;
>  
> +	if (p->policy == SCHED_OTHER)
> +		priority = 0;
> +
>  	/*
>  	 * Linux's priority scale is a subset of the core pod's
>  	 * priority scale, so there is no need to bound the priority

No other policies can be issued against the Linux part of a shadow? Then
it's OK. I just don't recall the details here ATM.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Xenomai-core] Policy switching and XNOTHER maintenance
  2011-09-18 15:24                     ` Jan Kiszka
@ 2011-09-18 15:47                       ` Gilles Chanteperdrix
  0 siblings, 0 replies; 14+ messages in thread
From: Gilles Chanteperdrix @ 2011-09-18 15:47 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai-core

On 09/18/2011 05:24 PM, Jan Kiszka wrote:
> On 2011-09-18 17:18, Gilles Chanteperdrix wrote:
>> What about:
>>
>> diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
>> index 21cc191..7fe44a1 100644
>> --- a/ksrc/nucleus/shadow.c
>> +++ b/ksrc/nucleus/shadow.c
>> @@ -2756,9 +2756,12 @@ static inline void do_setsched_event(struct task_struct *p, int priority)
>>  	union xnsched_policy_param param;
>>  	struct xnsched *sched;
>>  
>> -	if (!thread || p->policy != SCHED_FIFO)
>> +	if (!thread || (p->policy != SCHED_FIFO && p->policy != SCHED_OTHER))
>>  		return;
>>  
>> +	if (p->policy == SCHED_OTHER)
>> +		priority = 0;
>> +
>>  	/*
>>  	 * Linux's priority scale is a subset of the core pod's
>>  	 * priority scale, so there is no need to bound the priority
> 
> No other policies can be issued against the Linux part of a shadow? Then
> it's OK. I just don't recall the details here ATM.
> 
> Jan
> 

This should be OK, according to the comment:
	 * BIG FAT WARNING: Change of scheduling parameters from the
	 * Linux side are propagated only to threads that belong to
	 * the Xenomai RT scheduling class. Threads from other classes
	 * are remain unaffected, since we could not map this
	 * information 1:1 between Linux and Xenomai.
	 */


-- 
                                                                Gilles.


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2011-09-18 15:47 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-11 10:50 [Xenomai-core] Policy switching and XNOTHER maintenance Jan Kiszka
2011-09-11 11:49 ` Jan Kiszka
2011-09-11 14:24 ` Gilles Chanteperdrix
2011-09-11 14:29   ` Jan Kiszka
2011-09-16 20:13     ` Gilles Chanteperdrix
2011-09-16 20:39       ` Gilles Chanteperdrix
2011-09-18 14:02         ` Philippe Gerum
2011-09-18 14:34           ` Jan Kiszka
2011-09-18 15:10             ` Philippe Gerum
2011-09-18 15:11               ` Jan Kiszka
2011-09-18 15:13                 ` Jan Kiszka
2011-09-18 15:18                   ` Gilles Chanteperdrix
2011-09-18 15:24                     ` Jan Kiszka
2011-09-18 15:47                       ` Gilles Chanteperdrix

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.