137 lines
5.0 KiB
Diff
137 lines
5.0 KiB
Diff
From 93b892ee12b8eb43a72f308c981f3c68c6ae8b45 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Gleixner <tglx@linutronix.de>
|
|
Date: Wed, 31 Oct 2012 12:04:11 +0100
|
|
Subject: [PATCH 36/62] arm: Add support for lazy preemption
|
|
|
|
Implement the arm pieces for lazy preempt.
|
|
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
---
|
|
arch/arm/Kconfig | 1 +
|
|
arch/arm/include/asm/thread_info.h | 6 +++++-
|
|
arch/arm/kernel/asm-offsets.c | 1 +
|
|
arch/arm/kernel/entry-armv.S | 19 ++++++++++++++++---
|
|
arch/arm/kernel/signal.c | 3 ++-
|
|
5 files changed, 25 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
|
|
index 6d5afe2e6ba3..717e596dc13b 100644
|
|
--- a/arch/arm/Kconfig
|
|
+++ b/arch/arm/Kconfig
|
|
@@ -115,6 +115,7 @@ config ARM
|
|
select HAVE_PERF_EVENTS
|
|
select HAVE_PERF_REGS
|
|
select HAVE_PERF_USER_STACK_DUMP
|
|
+ select HAVE_PREEMPT_LAZY
|
|
select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE
|
|
select HAVE_REGS_AND_STACK_ACCESS_API
|
|
select HAVE_RSEQ
|
|
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
|
|
index 7f092cb55a41..ffcbf8ebed4b 100644
|
|
--- a/arch/arm/include/asm/thread_info.h
|
|
+++ b/arch/arm/include/asm/thread_info.h
|
|
@@ -62,6 +62,7 @@ struct cpu_context_save {
|
|
struct thread_info {
|
|
unsigned long flags; /* low level flags */
|
|
int preempt_count; /* 0 => preemptable, <0 => bug */
|
|
+ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */
|
|
__u32 cpu; /* cpu */
|
|
__u32 cpu_domain; /* cpu domain */
|
|
struct cpu_context_save cpu_context; /* cpu context */
|
|
@@ -129,6 +130,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
|
|
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
|
|
#define TIF_UPROBE 3 /* breakpointed or singlestepping */
|
|
#define TIF_NOTIFY_SIGNAL 4 /* signal notifications exist */
|
|
+#define TIF_NEED_RESCHED_LAZY 5
|
|
|
|
#define TIF_USING_IWMMXT 17
|
|
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
|
|
@@ -148,6 +150,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
|
|
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
|
|
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
|
|
#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
|
|
+#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
|
|
#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
|
|
|
|
/* Checks for any syscall work in entry-common.S */
|
|
@@ -157,7 +160,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
|
|
/*
|
|
* Change these and you break ASM code in entry-common.S
|
|
*/
|
|
-#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
|
|
+#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY | \
|
|
+ _TIF_SIGPENDING | \
|
|
_TIF_NOTIFY_RESUME | _TIF_UPROBE | \
|
|
_TIF_NOTIFY_SIGNAL)
|
|
|
|
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
|
|
index 2c8d76fd7c66..c3bdec7d2df9 100644
|
|
--- a/arch/arm/kernel/asm-offsets.c
|
|
+++ b/arch/arm/kernel/asm-offsets.c
|
|
@@ -43,6 +43,7 @@ int main(void)
|
|
BLANK();
|
|
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
|
|
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
|
|
+ DEFINE(TI_PREEMPT_LAZY, offsetof(struct thread_info, preempt_lazy_count));
|
|
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
|
|
DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain));
|
|
DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));
|
|
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
|
|
index c39303e5c234..cfb4660e9fea 100644
|
|
--- a/arch/arm/kernel/entry-armv.S
|
|
+++ b/arch/arm/kernel/entry-armv.S
|
|
@@ -222,11 +222,18 @@ ENDPROC(__dabt_svc)
|
|
|
|
#ifdef CONFIG_PREEMPTION
|
|
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
|
|
- ldr r0, [tsk, #TI_FLAGS] @ get flags
|
|
teq r8, #0 @ if preempt count != 0
|
|
+ bne 1f @ return from exeption
|
|
+ ldr r0, [tsk, #TI_FLAGS] @ get flags
|
|
+ tst r0, #_TIF_NEED_RESCHED @ if NEED_RESCHED is set
|
|
+ blne svc_preempt @ preempt!
|
|
+
|
|
+ ldr r8, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count
|
|
+ teq r8, #0 @ if preempt lazy count != 0
|
|
movne r0, #0 @ force flags to 0
|
|
- tst r0, #_TIF_NEED_RESCHED
|
|
+ tst r0, #_TIF_NEED_RESCHED_LAZY
|
|
blne svc_preempt
|
|
+1:
|
|
#endif
|
|
|
|
svc_exit r5, irq = 1 @ return from exception
|
|
@@ -241,8 +248,14 @@ ENDPROC(__irq_svc)
|
|
1: bl preempt_schedule_irq @ irq en/disable is done inside
|
|
ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS
|
|
tst r0, #_TIF_NEED_RESCHED
|
|
+ bne 1b
|
|
+ tst r0, #_TIF_NEED_RESCHED_LAZY
|
|
reteq r8 @ go again
|
|
- b 1b
|
|
+ ldr r0, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count
|
|
+ teq r0, #0 @ if preempt lazy count != 0
|
|
+ beq 1b
|
|
+ ret r8 @ go again
|
|
+
|
|
#endif
|
|
|
|
__und_fault:
|
|
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
|
|
index e07f359254c3..b50a3248e79f 100644
|
|
--- a/arch/arm/kernel/signal.c
|
|
+++ b/arch/arm/kernel/signal.c
|
|
@@ -607,7 +607,8 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
|
|
*/
|
|
trace_hardirqs_off();
|
|
do {
|
|
- if (likely(thread_flags & _TIF_NEED_RESCHED)) {
|
|
+ if (likely(thread_flags & (_TIF_NEED_RESCHED |
|
|
+ _TIF_NEED_RESCHED_LAZY))) {
|
|
schedule();
|
|
} else {
|
|
if (unlikely(!user_mode(regs)))
|
|
--
|
|
2.43.0
|
|
|