From 5986ec040b2f1ab0f9314b83109e97609f99a16b Mon Sep 17 00:00:00 2001 From: Benjamin Walsh Date: Mon, 7 Nov 2016 15:49:23 -0500 Subject: [PATCH] arc: fix race condition when returning from interrupt A race condition would happend if a FIRQ interrupted a return-from-interrupt from a RIRQ at the wrong moment: if a decision was already taken which thread to context switch in and the FIRQ woke up another thread of higher priority, the ready queue would be corrupted. The solution is to lock interrupts at the moment the interrupt return code starts looking at the kernel queues. Interrupts do not need to be unlocked before exiting: the return-from-interrupt (rtie) instruction will restore the correct interrupt locking state for the thread being context switched in. Change-Id: I777665c2faeca7b1f2a77ddd9ee2a520080bae88 Signed-off-by: Benjamin Walsh --- arch/arc/core/regular_irq.S | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/arc/core/regular_irq.S b/arch/arc/core/regular_irq.S index a96ead35e6e..dee8e58d3df 100644 --- a/arch/arc/core/regular_irq.S +++ b/arch/arc/core/regular_irq.S @@ -100,6 +100,13 @@ SECTION_FUNC(TEXT, _rirq_exit) mov r1, _nanokernel ld_s r2, [r1, __tNANO_current_OFFSET] + /* + * Lock interrupts to ensure kernel queues do not change from this + * point on until return from interrupt. + */ + + clri + #if NUM_REGULAR_IRQ_PRIO_LEVELS > 1 /* check if we're a nested interrupt: if so, let the interrupted interrupt * handle the reschedule */ @@ -140,9 +147,9 @@ SECTION_FUNC(TEXT, _rirq_exit) brgt.d r0, 0, _rirq_no_reschedule ld sp, [r2, __tTCS_preempReg_OFFSET + __tPreempt_sp_OFFSET] + /* check if the current thread needs to be rescheduled */ push_s r2 push_s r1 - /* check if the current thread needs to be rescheduled */ push_s blink jl _is_next_thread_current pop_s blink @@ -171,7 +178,7 @@ _rirq_reschedule: st _CAUSE_RIRQ, [r2, __tTCS_relinquish_cause_OFFSET] - /* incoming fiber is in r0: it becomes the new 'current' */ + /* incoming thread is in r0: it becomes the new 'current' */ mov r2, r0 st_s r2, [r1, __tNANO_current_OFFSET]