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 <benjamin.walsh@windriver.com>
This commit is contained in:
parent
84a92048cf
commit
5986ec040b
1 changed files with 9 additions and 2 deletions
|
@ -100,6 +100,13 @@ SECTION_FUNC(TEXT, _rirq_exit)
|
||||||
mov r1, _nanokernel
|
mov r1, _nanokernel
|
||||||
ld_s r2, [r1, __tNANO_current_OFFSET]
|
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
|
#if NUM_REGULAR_IRQ_PRIO_LEVELS > 1
|
||||||
/* check if we're a nested interrupt: if so, let the interrupted interrupt
|
/* check if we're a nested interrupt: if so, let the interrupted interrupt
|
||||||
* handle the reschedule */
|
* handle the reschedule */
|
||||||
|
@ -140,9 +147,9 @@ SECTION_FUNC(TEXT, _rirq_exit)
|
||||||
brgt.d r0, 0, _rirq_no_reschedule
|
brgt.d r0, 0, _rirq_no_reschedule
|
||||||
ld sp, [r2, __tTCS_preempReg_OFFSET + __tPreempt_sp_OFFSET]
|
ld sp, [r2, __tTCS_preempReg_OFFSET + __tPreempt_sp_OFFSET]
|
||||||
|
|
||||||
|
/* check if the current thread needs to be rescheduled */
|
||||||
push_s r2
|
push_s r2
|
||||||
push_s r1
|
push_s r1
|
||||||
/* check if the current thread needs to be rescheduled */
|
|
||||||
push_s blink
|
push_s blink
|
||||||
jl _is_next_thread_current
|
jl _is_next_thread_current
|
||||||
pop_s blink
|
pop_s blink
|
||||||
|
@ -171,7 +178,7 @@ _rirq_reschedule:
|
||||||
|
|
||||||
st _CAUSE_RIRQ, [r2, __tTCS_relinquish_cause_OFFSET]
|
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
|
mov r2, r0
|
||||||
st_s r2, [r1, __tNANO_current_OFFSET]
|
st_s r2, [r1, __tNANO_current_OFFSET]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue