Wait for interrupt and sleep

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
rweickelt
Member++
Posts: 16
Joined: Tue Sep 02, 2014 8:38 pm

Post by rweickelt »

Hi, I'm glad somebody is still interested in this. Thank You for the link to the lock library. There's so much code to digg into. In the meantime, I've extended my code example above so that it makes more sense now.

But I'm afraid, that this would not solve the problem here. Locks are necessary, when two threads want exclusive access to a resource (e.g. a memory location). By using just one hardware lock it would be possible to implement infinite sw locks. The fact that XCORE supports hw locks speaks for itself. It's the first time, that I see them in a commercial product though I have not studied too many multi-core architectures ;-)

Back on track: The possible race condition in the above code is as follows: Let's assume, our thread has no more tasks to dispatch. It will call _suspend in that case. Interrupts are of course disabled here. But before the thread can suspend, interrupts have to be enabled with "setsr SR_IEBLE". Otherwise it would not wake up. If there is no pending interrupt and the thread can suspend, everything is fine.

But what happens, if an interrupt has occurred in the meantime? I see 2 scenarios for the moment where "setsr SR_IEBLE" becomes valid and the registers are saved:
  1. The PC already contains the address of the "waiteu" instruction.
  2. The PC still points to setsr SR_IEBLE


Scenario 1 is okay, because in that case, the PC manipulation in the ISR would apply and the thread would resume after waiteu. Scenario 2 would be a hazardous because after the ISR, waiteu would still be executed and the thread would suspend without interrupts enabled. Perhaps I should not write novels, but just test it.

Supplement
While I wrote the above text, I've noticed, that I could also overcome the problem by not only testing if SPC points to the waiteu instruction, but also for the "setsr" instruction. But it might not be necessary at all.


richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

rweickelt wrote:Scenario 1 is okay, because in that case, the PC manipulation in the ISR would apply and the thread would resume after waiteu. Scenario 2 would be a hazardous because after the ISR, waiteu would still be executed and the thread would suspend without interrupts enabled.
When the interrupt is taken the thread's status register (which stores the bits that control whether events or interrupts are enabled) is copied from the SR to the SSR register. When you return from the interrupt handler the SSR will be copied back to the SR so interrupts will be enabled when you return. You still might not want scenario 2 to happen as you wouldn't the thread to execute the waiteu and pause if the interrupt handler added tasks to the readyList.

However scenario 2 can't happen anyway since the setsr instruction executes atomically - either it executes or it doesn't. For you to end up in the interrupt handler the setsr instruction must have executed (since interrupts were disabled beforehand) and so the pc must have been incremented past the setsr instruction.

There is a race condition in the code but it occurs later. After the interrupt handler returns the thread might take a second interrupt before executing the clrsr instruction. This is only an problem if you expect exactly one interrupt to be taken each time you call _suspend - if you don't mind taking multiple interrupts at this point there is no problem. If you did want to ensure that _suspend handles exactly one interrupt then you would mask off the SR_IEBLE bit of the SSR before returning from the interrupt handler if the SPC is equal to __waiteuInstruction.
User avatar
rweickelt
Member++
Posts: 16
Joined: Tue Sep 02, 2014 8:38 pm

Post by rweickelt »

Hi,
For you to end up in the interrupt handler the setsr instruction must have executed (since interrupts were disabled beforehand) and so the pc must have been incremented past the setsr instruction.
That makes sense.
There is a race condition in the code but it occurs later. After the interrupt handler returns the thread might take a second interrupt before executing the clrsr instruction. This is only an problem if you expect exactly one interrupt to be taken each time you call _suspend - if you don't mind taking multiple interrupts at this point there is no problem. If you did want to ensure that _suspend handles exactly one interrupt then you would mask off the SR_IEBLE bit of the SSR before returning from the interrupt handler if the SPC is equal to __waiteuInstruction.
I don't mind multiple interrupts. I just need the guarantee, that the thread will not suspend after an ISR, right before another iteration in the scheduler loop. So everything is fine in this case.

Many thanks to both of You for commenting. I think, my initial problem has been solved. Though I'm still looking for a more effective way to switch to kernel stack (see also this thread)