RISC-V: Add _TIF_NEED_RESCHED check for kernel thread when CONFIG_PREEMPT=y
The cond_resched() can be used to yield the CPU resource if CONFIG_PREEMPT is not defined. Otherwise, cond_resched() is a dummy function. In order to avoid kernel thread occupying entire CPU, when CONFIG_PREEMPT=y, the kernel thread needs to follow the rescheduling mechanism like a user thread. Signed-off-by: Vincent Chen <vincentc@andestech.com> Tested-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
This commit is contained in:
committed by
Palmer Dabbelt
parent
49a57857ae
commit
99fd6e875d
@@ -39,6 +39,7 @@ void asm_offsets(void)
|
|||||||
OFFSET(TASK_STACK, task_struct, stack);
|
OFFSET(TASK_STACK, task_struct, stack);
|
||||||
OFFSET(TASK_TI, task_struct, thread_info);
|
OFFSET(TASK_TI, task_struct, thread_info);
|
||||||
OFFSET(TASK_TI_FLAGS, task_struct, thread_info.flags);
|
OFFSET(TASK_TI_FLAGS, task_struct, thread_info.flags);
|
||||||
|
OFFSET(TASK_TI_PREEMPT_COUNT, task_struct, thread_info.preempt_count);
|
||||||
OFFSET(TASK_TI_KERNEL_SP, task_struct, thread_info.kernel_sp);
|
OFFSET(TASK_TI_KERNEL_SP, task_struct, thread_info.kernel_sp);
|
||||||
OFFSET(TASK_TI_USER_SP, task_struct, thread_info.user_sp);
|
OFFSET(TASK_TI_USER_SP, task_struct, thread_info.user_sp);
|
||||||
OFFSET(TASK_TI_CPU, task_struct, thread_info.cpu);
|
OFFSET(TASK_TI_CPU, task_struct, thread_info.cpu);
|
||||||
|
@@ -144,6 +144,10 @@ _save_context:
|
|||||||
REG_L x2, PT_SP(sp)
|
REG_L x2, PT_SP(sp)
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
#if !IS_ENABLED(CONFIG_PREEMPT)
|
||||||
|
.set resume_kernel, restore_all
|
||||||
|
#endif
|
||||||
|
|
||||||
ENTRY(handle_exception)
|
ENTRY(handle_exception)
|
||||||
SAVE_ALL
|
SAVE_ALL
|
||||||
|
|
||||||
@@ -228,7 +232,7 @@ ret_from_exception:
|
|||||||
REG_L s0, PT_SSTATUS(sp)
|
REG_L s0, PT_SSTATUS(sp)
|
||||||
csrc sstatus, SR_SIE
|
csrc sstatus, SR_SIE
|
||||||
andi s0, s0, SR_SPP
|
andi s0, s0, SR_SPP
|
||||||
bnez s0, restore_all
|
bnez s0, resume_kernel
|
||||||
|
|
||||||
resume_userspace:
|
resume_userspace:
|
||||||
/* Interrupts must be disabled here so flags are checked atomically */
|
/* Interrupts must be disabled here so flags are checked atomically */
|
||||||
@@ -250,6 +254,18 @@ restore_all:
|
|||||||
RESTORE_ALL
|
RESTORE_ALL
|
||||||
sret
|
sret
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_PREEMPT)
|
||||||
|
resume_kernel:
|
||||||
|
REG_L s0, TASK_TI_PREEMPT_COUNT(tp)
|
||||||
|
bnez s0, restore_all
|
||||||
|
need_resched:
|
||||||
|
REG_L s0, TASK_TI_FLAGS(tp)
|
||||||
|
andi s0, s0, _TIF_NEED_RESCHED
|
||||||
|
beqz s0, restore_all
|
||||||
|
call preempt_schedule_irq
|
||||||
|
j need_resched
|
||||||
|
#endif
|
||||||
|
|
||||||
work_pending:
|
work_pending:
|
||||||
/* Enter slow path for supplementary processing */
|
/* Enter slow path for supplementary processing */
|
||||||
la ra, ret_from_exception
|
la ra, ret_from_exception
|
||||||
|
Reference in New Issue
Block a user