<div dir="ltr"><div dir="ltr"><div dir="ltr">Sure, I will build and try. <div>Is _ISR_Get_level() something CPU-specific ? I mean we use it to figure out if interrupts are enabled or not, right ?</div><div>forgot to say, I use a STM32H7. Does _ISR_Get_level work on it ?</div><div><br></div><div>Also, I thought the scheduler code runs with interrupts enabled, I mean doesn't it use the tick interrupt itself ?</div><div>How does that work on RTEMS ?</div><div><br></div></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Mar 29, 2019 at 12:04 PM Sebastian Huber <<a href="mailto:sebastian.huber@embedded-brains.de">sebastian.huber@embedded-brains.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hello Catalin,<br>
<br>
On 29/03/2019 10:56, Catalin Demergian wrote:<br>
> Hi,<br>
> We had some time ago (sept/oct 2018) a long discussion where I was <br>
> suspecting a<br>
> scheduler issue (subject <br>
> "rtems_message_queue_receive/rtems_event_receive issues")<br>
><br>
> We got to the point where I realized that _Chain_Append_unprotected <br>
> might fail to add an<br>
> element in the queue, with the effect of having a task in a funny <br>
> state where state=READY, but<br>
> the task will not be in the ready chain, so the task will never get <br>
> CPU time anymore since a task<br>
> needs to be blocked in order to be unblocked when new data arrives.<br>
><br>
> We were using USB then, but this issue re-became hot because we just <br>
> got the same issue<br>
> over serial :)<br>
> I believe there is a possible chain of events that can make <br>
> _Chain_Append_unprotected to fail,<br>
> explanations follow.<br>
><br>
> /*<br>
><br>
> ** @note It does NOT disable interrupts to ensure the atomicity of the*<br>
><br>
> **       append operation.*<br>
><br>
> */<br>
><br>
> RTEMS_INLINE_ROUTINE void _Chain_Append_unprotected(<br>
><br>
>   Chain_Control *the_chain,<br>
><br>
>   Chain_Node    *the_node<br>
><br>
> )<br>
><br>
> {<br>
><br>
>   Chain_Node *tail = _Chain_Tail( the_chain );<br>
><br>
>   Chain_Node *old_last = tail->previous;<br>
><br>
>   the_node->next = tail;<br>
><br>
> *  tail->previous = the_node;*<br>
><br>
> *  old_last->next = the_node;*<br>
><br>
>   the_node->previous = old_last;<br>
><br>
> }<br>
><br>
> The<br>
><br>
> *  tail->previous = the_node;*<br>
><br>
> *  old_last->next = the_node;*<br>
><br>
> lines are the ones that actually add the element<br>
><br>
> to the ready chain.<br>
><br>
> If a thread executes those lines, but just before executing<br>
><br>
> the_node->previous = old_last;<br>
><br>
> another thread comes to add another node in this chain, it will set <br>
> another node in<br>
><br>
> tail->previous and old_last->next, and as a result, when the interrupted<br>
><br>
> thread will continue to execute the last line, it will be for nothing, <br>
> because the initial node will not be added to the ready chain.<br>
><br>
><br>
> If this chain of events occur (*and after a while they will*), we get <br>
> starvation for that task.<br>
><br>
> I'm reproducing this issue in a long duration test, the duration <br>
> before this happens varies from run to run, but it always happens.<br>
><br>
><br>
> *What I'm proposing is the following*: call _Chain_Append instead of <br>
> _Chain_Append_unprotected in <br>
> schedulerpriorityimpl.h, _Scheduler_priority_Ready_queue_enqueue function.<br>
><br>
><br>
> void _Chain_Append(<br>
><br>
>   Chain_Control *the_chain,<br>
><br>
>   Chain_Node    *node<br>
><br>
> )<br>
><br>
> {<br>
><br>
>   ISR_Level level;<br>
><br>
>   _ISR_Disable( level );<br>
><br>
>     _Chain_Append_unprotected( the_chain, node );<br>
><br>
> _ISR_Enable( level );<br>
><br>
> }<br>
><br>
><br>
> This way the add-element-to-chain operation becomes atomic.<br>
><br>
> I was able to run a long duration test (8 hrs) in my setup with this <br>
> fix successfully.<br>
><br>
><br>
> What do you think ?<br>
><br>
<br>
The _Scheduler_priority_Ready_queue_enqueue() should only be called with <br>
interrupts disabled. So, disabling interrupts again should have no <br>
effect. Could you please try out the attached patch and build the BSP <br>
with --enable-rtems-debug?<br>
<br>
-- <br>
Sebastian Huber, embedded brains GmbH<br>
<br>
Address : Dornierstr. 4, D-82178 Puchheim, Germany<br>
Phone   : +49 89 189 47 41-16<br>
Fax     : +49 89 189 47 41-09<br>
E-Mail  : <a href="mailto:sebastian.huber@embedded-brains.de" target="_blank">sebastian.huber@embedded-brains.de</a><br>
PGP     : Public key available on request.<br>
<br>
Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.<br>
<br>
</blockquote></div>