summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKyle McMartin <kyle@parisc-linux.org>2006-03-24 21:24:21 -0700
committerKyle McMartin <kyle@hera.kernel.org>2006-03-30 17:48:54 +0000
commit50a34dbd612925f2ec55b1781632835ef36b97d5 (patch)
tree1624f33bdbdd367efb8fadebe80da7db275ea1e6
parentbc8846c522264d2522b0082321ec8c2051a4536f (diff)
[PARISC] Add PREEMPT support
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
-rw-r--r--arch/parisc/Kconfig6
-rw-r--r--arch/parisc/kernel/entry.S39
-rw-r--r--include/asm-parisc/thread_info.h3
3 files changed, 39 insertions, 9 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 6b3c50964ca..2fdf21989dc 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -177,14 +177,10 @@ config ARCH_DISCONTIGMEM_DEFAULT
def_bool y
depends on ARCH_DISCONTIGMEM_ENABLE
+source "kernel/Kconfig.preempt"
source "kernel/Kconfig.hz"
source "mm/Kconfig"
-config PREEMPT
- bool
-# bool "Preemptible Kernel"
- default n
-
config COMPAT
def_bool y
depends on 64BIT
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 6d17c0a3431..7c95d7663c2 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -1014,14 +1014,21 @@ intr_restore:
nop
nop
+#ifndef CONFIG_PREEMPT
+# define intr_do_preempt intr_restore
+#endif /* !CONFIG_PREEMPT */
+
.import schedule,code
intr_do_resched:
- /* Only do reschedule if we are returning to user space */
+ /* Only call schedule on return to userspace. If we're returning
+ * to kernel space, we may schedule if CONFIG_PREEMPT, otherwise
+ * we jump back to intr_restore.
+ */
LDREG PT_IASQ0(%r16), %r20
- CMPIB= 0,%r20,intr_restore /* backward */
+ CMPIB= 0, %r20, intr_do_preempt
nop
LDREG PT_IASQ1(%r16), %r20
- CMPIB= 0,%r20,intr_restore /* backward */
+ CMPIB= 0, %r20, intr_do_preempt
nop
#ifdef CONFIG_64BIT
@@ -1037,6 +1044,32 @@ intr_do_resched:
#endif
ldo R%intr_check_sig(%r2), %r2
+ /* preempt the current task on returning to kernel
+ * mode from an interrupt, iff need_resched is set,
+ * and preempt_count is 0. otherwise, we continue on
+ * our merry way back to the current running task.
+ */
+#ifdef CONFIG_PREEMPT
+ .import preempt_schedule_irq,code
+intr_do_preempt:
+ rsm PSW_SM_I, %r0 /* disable interrupts */
+
+ /* current_thread_info()->preempt_count */
+ mfctl %cr30, %r1
+ LDREG TI_PRE_COUNT(%r1), %r19
+ CMPIB<> 0, %r19, intr_restore /* if preempt_count > 0 */
+ nop /* prev insn branched backwards */
+
+ /* check if we interrupted a critical path */
+ LDREG PT_PSW(%r16), %r20
+ bb,<,n %r20, 31 - PSW_SM_I, intr_restore
+ nop
+
+ BL preempt_schedule_irq, %r2
+ nop
+
+ b intr_restore /* ssm PSW_SM_I done by intr_restore */
+#endif /* CONFIG_PREEMPT */
.import do_signal,code
intr_do_signal:
diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h
index ac32f140b83..f2f83b04cd8 100644
--- a/include/asm-parisc/thread_info.h
+++ b/include/asm-parisc/thread_info.h
@@ -49,7 +49,8 @@ struct thread_info {
#endif /* !__ASSEMBLY */
-#define PREEMPT_ACTIVE 0x10000000
+#define PREEMPT_ACTIVE_BIT 28
+#define PREEMPT_ACTIVE (1 << PREEMPT_ACTIVE_BIT)
/*
* thread information flags