Any absolutely safe way to disable and restore global int?

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was looking at the Atmel implementation of saving the the global interrupt state and disabling interrupts. It looks like it has a slim window of vulnerability. I do not have a real issue so this is a theoretical observation.

Here is the implementation that caught my eye.

static inline irqflags_t cpu_irq_save(void)
{
irqflags_t flags;

flags = sysreg_read(AVR32_SR);
cpu_irq_disable();

return flags;
}

The window of vulnerability is from reading the flag to disabling it. If an interrupt would happen between these instructions that modified the state of the enable, it might get restored to something incorrect. It may be more error prone in an RTOS like FreeRTOS.

Many processors have an atomic read state and set bit instruction. There is 0 vulnerability.

Are there better implementations than this?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Tom,

normally you should never return from a routine/interrupt handler without re-enabling the global interrupt if it was disabled earlier by the routine itself.
This way you can use the quoted method safely.

BR,
Menahem

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would have done it a bit differently

cpu_irq_disable();
flags = sysreg_read(AVR32_SR) & ( ~AVR32_SR_GM_MASK );

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yep, you are absolutely right, i focused only on the GM bit, the others should be handled as you wrote. Sorry.

To be honest i use my simple home made platform sw which restores only the GM and EM bits.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

tomclary683 wrote:
I was looking at the Atmel implementation of saving the the global interrupt state and disabling interrupts. It looks like it has a slim window of vulnerability.

static inline irqflags_t cpu_irq_save(void)
{
	irqflags_t flags;

	flags = sysreg_read(AVR32_SR);
	cpu_irq_disable();

	return flags;
}

The window of vulnerability is from reading the flag to disabling it. If an interrupt would happen between these instructions that modified the state of the enable, it might get restored to something incorrect. It may be more error prone in an RTOS like FreeRTOS.

This problem doesn’t exist. When an interrupt or other exception is triggered, the current SR content is pushed onto the stack. When the interrupt or exception exits, the saved SR content is restored and with it the interrupt level masks. Even if any interrupt mask flags are modified inside the interrupt or exception handler, they will return to their previous states upon exit.

The function quoted above merely saves the flags of the current execution context. From the perspective of that function, the flags don’t change during it’s execution. No race condition possible and it’s safe to use.

Well, I strongly emphasized that the problem cannot occur, but actually there is a way to trigger that. It’s possible to modify the stored SR content on the stack and mess with the mask flags manually. When the handler exits, those modified flags will become active. However, that’s a truly dangerous thing to do and all hell would break loose if you did that. You’d deserve whatever happens.