forked from Imagelibrary/rtems
nios2: Optimize ISR dispatch variant
Use _Thread_Do_dispatch() in _Nios2_ISR_Dispatch_with_shadow_non_preemptive().
This commit is contained in:
@@ -55,16 +55,16 @@ _Nios2_ISR_Dispatch_with_shadow_non_preemptive:
|
|||||||
ldw r4, 8(et)
|
ldw r4, 8(et)
|
||||||
|
|
||||||
/* Increment and store thread dispatch disable level */
|
/* Increment and store thread dispatch disable level */
|
||||||
addi r9, r16, 1
|
addi r17, r16, 1
|
||||||
stw r9, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
|
stw r17, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
|
||||||
|
|
||||||
/* Call high level handler with argument */
|
/* Call high level handler with argument */
|
||||||
callr r8
|
callr r8
|
||||||
|
|
||||||
/* Load thread dispatch necessary */
|
/* Load the thread dispatch necessary indicator */
|
||||||
ldb r12, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
|
ldb r12, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
|
||||||
|
|
||||||
/* Load thread dispatch after ISR disable indicator */
|
/* Load the thread dispatch after ISR disable indicator */
|
||||||
ldw r13, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
|
ldw r13, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
|
||||||
|
|
||||||
/* Read status */
|
/* Read status */
|
||||||
@@ -74,31 +74,36 @@ _Nios2_ISR_Dispatch_with_shadow_non_preemptive:
|
|||||||
subi ea, ea, 4
|
subi ea, ea, 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restore the thread dispatch disable level. We must do this before
|
* If the current thread dispatch disable level (r17) is one, then
|
||||||
* we return to the normal register set, because otherwise we have
|
* negate the thread dispatch necessary indicator, otherwise the value
|
||||||
* problems if someone deletes or restarts the interrupted thread while
|
* is irrelevant. Or it with the previous thread dispatch disable
|
||||||
* we are in the thread dispatch helper.
|
* level value (r16). The r15 which will be used as a status to
|
||||||
|
* determine if a thread dispatch is necessary and allowed.
|
||||||
*/
|
*/
|
||||||
stw r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
|
xor r12, r17, r12
|
||||||
|
or r15, r12, r16
|
||||||
|
|
||||||
/* Is thread dispatch allowed? */
|
/*
|
||||||
bne r16, zero, no_thread_dispatch
|
* Get the previous register set from r14. If it is zero, then this is
|
||||||
|
* the outermost interrupt. Or it to the thread dispatch status (r15).
|
||||||
|
*/
|
||||||
|
andhi r12, r14, 0x3f
|
||||||
|
or r15, r12, r15
|
||||||
|
|
||||||
/* Is thread dispatch necessary? */
|
/*
|
||||||
beq r12, zero, no_thread_dispatch
|
* Or the thread dispatch after ISR disable indicator (r13) to the
|
||||||
|
* thread dispatch status (r15).
|
||||||
|
*/
|
||||||
|
or r15, r13, r15
|
||||||
|
|
||||||
/* Is outermost interrupt? */
|
/* Is a thread dispatch necessary and allowed? */
|
||||||
andhi r14, r14, 0x3f
|
bne r15, zero, no_thread_dispatch
|
||||||
bne r14, zero, no_thread_dispatch
|
|
||||||
|
|
||||||
/* Is thread dispatch after ISR allowed? */
|
|
||||||
bne r13, zero, no_thread_dispatch
|
|
||||||
|
|
||||||
/* Obtain stack frame in normal register set */
|
/* Obtain stack frame in normal register set */
|
||||||
rdprs r15, sp, -FRAME_SIZE
|
rdprs r15, sp, -FRAME_SIZE
|
||||||
|
|
||||||
/* Disable thread dispatch after ISR */
|
/* Disable thread dispatch after ISR */
|
||||||
stw r12, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
|
stw r17, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
|
||||||
|
|
||||||
/* Save context */
|
/* Save context */
|
||||||
stw sstatus, FRAME_OFFSET_STATUS(r15)
|
stw sstatus, FRAME_OFFSET_STATUS(r15)
|
||||||
@@ -111,12 +116,15 @@ _Nios2_ISR_Dispatch_with_shadow_non_preemptive:
|
|||||||
/* Update stack pointer in normal register set */
|
/* Update stack pointer in normal register set */
|
||||||
wrprs sp, r15
|
wrprs sp, r15
|
||||||
|
|
||||||
|
/* Jump to thread dispatch helper */
|
||||||
|
eret
|
||||||
|
|
||||||
no_thread_dispatch:
|
no_thread_dispatch:
|
||||||
|
|
||||||
/*
|
/* Restore the thread dispatch disable level */
|
||||||
* Return to thread dispatch helper, interrupted thread or interrupted
|
stw r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
|
||||||
* lower level interrupt service routine.
|
|
||||||
*/
|
/* Return to interrupted context */
|
||||||
eret
|
eret
|
||||||
|
|
||||||
thread_dispatch_helper:
|
thread_dispatch_helper:
|
||||||
@@ -141,9 +149,26 @@ thread_dispatch_helper:
|
|||||||
stw r14, FRAME_OFFSET_R14(sp)
|
stw r14, FRAME_OFFSET_R14(sp)
|
||||||
stw r15, FRAME_OFFSET_R15(sp)
|
stw r15, FRAME_OFFSET_R15(sp)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable interrupts (1).
|
||||||
|
*
|
||||||
|
* We have the following invariants:
|
||||||
|
* 1. status.RSIE == 0: thread context initialization
|
||||||
|
* 2. status.CRS == 0: thread context initialization
|
||||||
|
* 3. status.PRS: arbitrary
|
||||||
|
* 4. status.IL < interrupt disable IL: else we would not be here
|
||||||
|
* 5. status.IH == 0: thread context initialization
|
||||||
|
* 6. status.U == 0: thread context initialization
|
||||||
|
* 7. status.PIE == 1: thread context initialization
|
||||||
|
* Thus we can use a constant to disable interrupts.
|
||||||
|
*/
|
||||||
|
movi r5, %lo(_Nios2_ISR_Status_interrupts_disabled)
|
||||||
|
wrctl status, r5
|
||||||
|
|
||||||
do_thread_dispatch:
|
do_thread_dispatch:
|
||||||
|
|
||||||
call _Thread_Dispatch
|
addi r4, gp, %gprel(_Per_CPU_Information)
|
||||||
|
call _Thread_Do_dispatch
|
||||||
|
|
||||||
/* Restore some volatile registers */
|
/* Restore some volatile registers */
|
||||||
ldw ra, FRAME_OFFSET_RA(sp)
|
ldw ra, FRAME_OFFSET_RA(sp)
|
||||||
@@ -160,19 +185,7 @@ do_thread_dispatch:
|
|||||||
ldw r11, FRAME_OFFSET_R11(sp)
|
ldw r11, FRAME_OFFSET_R11(sp)
|
||||||
ldw r12, FRAME_OFFSET_R12(sp)
|
ldw r12, FRAME_OFFSET_R12(sp)
|
||||||
|
|
||||||
/*
|
/* Disable interrupts, see (1) */
|
||||||
* Disable interrupts.
|
|
||||||
*
|
|
||||||
* We have the following invariants:
|
|
||||||
* 1. status.RSIE == 0: thread context initialization
|
|
||||||
* 2. status.CRS == 0: thread context initialization
|
|
||||||
* 3. status.PRS: arbitrary
|
|
||||||
* 4. status.IL < interrupt disable IL: else we would not be here
|
|
||||||
* 5. status.IH == 0: thread context initialization
|
|
||||||
* 6. status.U == 0: thread context initialization
|
|
||||||
* 7. status.PIE == 1: thread context initialization
|
|
||||||
* Thus we can use a constant to disable interrupts.
|
|
||||||
*/
|
|
||||||
rdctl r14, status
|
rdctl r14, status
|
||||||
movi r15, %lo(_Nios2_ISR_Status_interrupts_disabled)
|
movi r15, %lo(_Nios2_ISR_Status_interrupts_disabled)
|
||||||
wrctl status, r15
|
wrctl status, r15
|
||||||
@@ -181,7 +194,7 @@ do_thread_dispatch:
|
|||||||
ldb r13, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
|
ldb r13, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
|
||||||
|
|
||||||
/* Is thread dispatch necessary? */
|
/* Is thread dispatch necessary? */
|
||||||
bne r13, zero, enable_interrupts_before_thread_dispatch
|
bne r13, zero, prepare_thread_dispatch
|
||||||
|
|
||||||
/* Enable thread dispatch after ISR */
|
/* Enable thread dispatch after ISR */
|
||||||
stw zero, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
|
stw zero, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
|
||||||
@@ -204,9 +217,14 @@ do_thread_dispatch:
|
|||||||
/* Return to interrupted thread */
|
/* Return to interrupted thread */
|
||||||
eret
|
eret
|
||||||
|
|
||||||
enable_interrupts_before_thread_dispatch:
|
prepare_thread_dispatch:
|
||||||
|
|
||||||
/* Restore status */
|
/* Disable thread dispatching */
|
||||||
wrctl status, r14
|
movi r4, 1
|
||||||
|
stw r4, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
|
||||||
|
stw r4, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
|
||||||
|
|
||||||
|
/* Set interrupt level argument for _Thread_Do_dispatch() */
|
||||||
|
mov r5, r15
|
||||||
|
|
||||||
br do_thread_dispatch
|
br do_thread_dispatch
|
||||||
|
|||||||
Reference in New Issue
Block a user