comp.lang.ada
 help / color / mirror / Atom feed
From: Patrick Noffke <patrick.noffke@gmail.com>
Subject: Re: Ravenscar and context switching for Cortex-M4
Date: Fri, 7 Aug 2015 13:34:45 -0700 (PDT)
Date: 2015-08-07T13:34:45-07:00	[thread overview]
Message-ID: <8eb4eed3-7d0e-4d3c-a6df-292bcfb8f2de@googlegroups.com> (raw)
In-Reply-To: <50e2f61b-bdc3-485d-a492-b44bac1f8fc0@googlegroups.com>

On Thursday, August 6, 2015 at 4:43:52 PM UTC-5, Patrick Noffke wrote:
> > 
> > There is another bug that I've discovered in the GNAT 2015 Ravenscar-full runtime (Cortex-M4) that appears to be caused by the Interrupt_Wrapper changing the task's priority.  When there is no Runnable task, Leave_Kernel will Insert the non-Runnable task back into the ready queue (with state of Delayed or Suspended).  This task is also stored in the Running_Thread_Table (only one value in the table for a single CPU).  Then an interrupt comes along and raises the priority of the Runnable_Thread_Table task (which is Delayed) to that of the interrupt.  And the task that is woken up by the interrupt goes later in the ready queue, since its priority is now lower than the Delayed task.
> > 
> > This ultimately causes the task that was readied by the interrupt to not run (in my case, it never runs again).  I haven't traced all the subsequent behavior to know exactly why this happens, but if I don't change priorities in the Interrupt_Wrapper, the problem seems to be gone.
> > 

I just sent the following bug report to AdaCore:


I have discovered another bug in your GNAT 2015 Ravenscar runtime on a Cortex-M4 processor.

In s-bbthqu.adb, in the Change_Priority procedure, there is this comment:

      --  When raising the priority, it is not possible that there is another
      --  task with a higher priority (otherwise the other task would be
      --  running). Hence, there is no displacement required within the
      --  queue, because the thread is already in the first position.

That assumption is not correct when there are simultaneous interrupts before PendSV has had a chance to run.

I will detail how the bug manifests, but first I wanted to point out that the calls to Change_Priority in the Interrupt_Handler are not always (if ever) associated with the task that the interrupt may wake up, if there is even a task related to that interrupt.  Typically, when the interrupt fires, the current task is the Environment_Task, which is either Delayed or Suspended.  That task is assigned to Self_Id in the interrupt handler, which has nothing to do with the interrupt in my case.

The call to Change_Priority in Interrupt_Handler is part of the reason for this specific problem.

I have three tasks and two interrupts:
Main Loop (Environment_Task), priority = 0x00
PWM Task, priority = 0xC8
SPI Task, priority = 0x50

PWM ISR, priority = 0xFC
SPI ISR, priority = 0xFB

The PWM task is woken up by a PO associated with the PWM ISR, and similarly for the SPI task/ISR.

The condition for this error is the PWM ISR fires, and is immediately followed by the SPI ISR.  PendSV does not fire between (confirmed by an ITM trace capture).  In that case, the following sequence happens.  I will list active and base priorities for a task below as 0xAA/0xBB (0xAA = active priority, 0xBB = base priority).

1. 0x00 is the current task (i.e. in Runnable_Thread_Table, with Delayed state).
2. PWM ISR fires and calls Change_Priority, raising 0x00 priority to 0xFC.
3. PWM ISR causes PWM task (0xC8) to become ready, so Insert is called and ready queue order is 0xFC/0x00, 0xC8/0xC8.
4. PWM ISR calls Change_Priority to lower current task, so ready queue is 0xC8/0xC8, 0x00/0x00.
5. SPI ISR fires and raises 0x00 to 0xFB (PendSV hasn't fired, so 0x00 is still current task), but Change_Priority does not move it up in the queue (the faulty assumption in the above comment), so the ready queue is then 0xC8/0xC8, 0xFB/0x00.
6. Insert is called with the 0x50 task, so the ready queue is then 0xC8/0xC8, 0xFB/0x00, 0x50/0x50.
7. SPI ISR calls Change_Priority to lower current task, which puts 0x50 at the head (Change_Priority assigns Thread.Next to the head, and 0x00's "Next" is 0x50).  This causes 0xC8 to be thrown away, leaving the order at 0x50/0x50, 0x00/0x00.
8. 0x50 is run, followed by Extract, leaving only 0x00/0x00 on the queue.

Regards,
Patrick

      reply	other threads:[~2015-08-07 20:34 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-12 20:25 Ravenscar and context switching for Cortex-M4 Patrick Noffke
2015-02-12 21:28 ` Niklas Holsti
2015-02-13 12:41   ` G.B.
2015-02-13 16:25     ` Simon Wright
2015-02-13 18:08     ` Niklas Holsti
2015-02-13 19:01       ` Simon Wright
2015-02-13 23:45       ` Georg Bauhaus
2015-02-16 16:27 ` Patrick Noffke
2015-02-16 16:34   ` Patrick Noffke
2015-02-16 21:28   ` Simon Wright
2015-02-19 20:14     ` Patrick Noffke
2015-02-19 21:03       ` Bob Duff
2015-02-20 13:05         ` Simon Wright
2015-02-19 22:13       ` Patrick Noffke
2015-02-19 22:44         ` Patrick Noffke
2015-02-20  8:31           ` Simon Wright
2015-06-24 15:20           ` Patrick Noffke
2015-08-06 21:05     ` Patrick Noffke
2015-08-06 21:43       ` Patrick Noffke
2015-08-07 20:34         ` Patrick Noffke [this message]
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox