Hello Catalin,
On 29/03/2019 10:56, Catalin Demergian wrote:
Hi,
We had some time ago (sept/oct 2018) a long discussion where I was
suspecting a
scheduler issue (subject
"rtems_message_queue_receive/rtems_event_receive issues")
We got to the point where I realized that _Chain_Append_unprotected
might fail to add an
element in the queue, with the effect of having a task in a funny
state where state=READY, but
the task will not be in the ready chain, so the task will never get
CPU time anymore since a task
needs to be blocked in order to be unblocked when new data arrives.
We were using USB then, but this issue re-became hot because we just
got the same issue
over serial :)
I believe there is a possible chain of events that can make
_Chain_Append_unprotected to fail,
explanations follow.
/*
** @note It does NOT disable interrupts to ensure the atomicity of the*
** append operation.*
*/
RTEMS_INLINE_ROUTINE void _Chain_Append_unprotected(
Chain_Control *the_chain,
Chain_Node *the_node
)
{
Chain_Node *tail = _Chain_Tail( the_chain );
Chain_Node *old_last = tail->previous;
the_node->next = tail;
* tail->previous = the_node;*
* old_last->next = the_node;*
the_node->previous = old_last;
}
The
* tail->previous = the_node;*
* old_last->next = the_node;*
lines are the ones that actually add the element
to the ready chain.
If a thread executes those lines, but just before executing
the_node->previous = old_last;
another thread comes to add another node in this chain, it will set
another node in
tail->previous and old_last->next, and as a result, when the interrupted
thread will continue to execute the last line, it will be for nothing,
because the initial node will not be added to the ready chain.
If this chain of events occur (*and after a while they will*), we get
starvation for that task.
I'm reproducing this issue in a long duration test, the duration
before this happens varies from run to run, but it always happens.
*What I'm proposing is the following*: call _Chain_Append instead of
_Chain_Append_unprotected in
schedulerpriorityimpl.h, _Scheduler_priority_Ready_queue_enqueue function.
void _Chain_Append(
Chain_Control *the_chain,
Chain_Node *node
)
{
ISR_Level level;
_ISR_Disable( level );
_Chain_Append_unprotected( the_chain, node );
_ISR_Enable( level );
}
This way the add-element-to-chain operation becomes atomic.
I was able to run a long duration test (8 hrs) in my setup with this
fix successfully.
What do you think ?
The _Scheduler_priority_Ready_queue_enqueue() should only be called with
interrupts disabled. So, disabling interrupts again should have no
effect. Could you please try out the attached patch and build the BSP
with --enable-rtems-debug?
--
Sebastian Huber, embedded brains GmbH
Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone : +49 89 189 47 41-16
Fax : +49 89 189 47 41-09
E-Mail : sebastian.hu...@embedded-brains.de
PGP : Public key available on request.
Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.
>From cc9ddd9ddcba5b925704f2ea66e312074b19dd2c Mon Sep 17 00:00:00 2001
From: Sebastian Huber <sebastian.hu...@embedded-brains.de>
Date: Fri, 29 Mar 2019 11:02:40 +0100
Subject: [PATCH] score: Add asserts
---
cpukit/include/rtems/score/schedulerpriorityimpl.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/cpukit/include/rtems/score/schedulerpriorityimpl.h b/cpukit/include/rtems/score/schedulerpriorityimpl.h
index 354065fac4..05cc2eaf12 100644
--- a/cpukit/include/rtems/score/schedulerpriorityimpl.h
+++ b/cpukit/include/rtems/score/schedulerpriorityimpl.h
@@ -89,6 +89,7 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_enqueue(
{
Chain_Control *ready_chain = ready_queue->ready_chain;
+ _Assert(_ISR_Get_level() != 0);
_Chain_Append_unprotected( ready_chain, node );
_Priority_bit_map_Add( bit_map, &ready_queue->Priority_map );
}
@@ -110,6 +111,7 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_enqueue_first(
{
Chain_Control *ready_chain = ready_queue->ready_chain;
+ _Assert(_ISR_Get_level() != 0);
_Chain_Prepend_unprotected( ready_chain, node );
_Priority_bit_map_Add( bit_map, &ready_queue->Priority_map );
}
@@ -129,6 +131,7 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_extract(
{
Chain_Control *ready_chain = ready_queue->ready_chain;
+ _Assert(_ISR_Get_level() != 0);
if ( _Chain_Has_only_one_node( ready_chain ) ) {
_Chain_Initialize_empty( ready_chain );
_Chain_Initialize_node( node );
--
2.16.4
_______________________________________________
users mailing list
users@rtems.org
http://lists.rtems.org/mailman/listinfo/users