[parisc-linux] bits of PREEMPT support
Kyle McMartin
kyle at parisc-linux.org
Sun Feb 26 00:31:18 MST 2006
Linux duet 2.6.16-rc4-ga0124d78-dirty #32 SMP PREEMPT Sun Feb 26 01:42:36 EST 2006 parisc64 GNU/Linux
My hope is that PREEMPT will expose some bugs for us...
Seems to be self-hosting, at least, a make -j8 on the kernel succeeded.
For this to be unbuggy, someone probably needs to do the legwork to
forward port the previous work in ftp.p-l.org/patches.
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index eca33cf..cf79639 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -169,14 +169,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 9af4b22..920fb9c 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -1014,14 +1014,23 @@ 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...
+ *
+ * NOTE: Conditional nullification because of branch direction
+ * doesn't matter, since both are NULL.
+ */
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,7 +1046,37 @@ 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:
+ /* current_thread_info()->preempt_count */
+ mfctl %cr30, %r1
+ LDREG TI_PRE_COUNT(%r1), %r19
+ CMPIB<> 0, %r19, intr_check_sig /* if preempt_count > 0 */
+ nop /* prev insn branched backwards */
+
+ /* this block looks redundant... we wouldn't be here if
+ * TIF_NEED_RESCHED wasn't set */
+ LDREG TI_FLAGS(%r1), %r20
+ bb,>=,n %r20, 31 - TIF_NEED_RESCHED, intr_check_sig
+ nop /* backward */
+
+ ssm 0, %r20 /* are interrupts disabled? */
+ bb,<,n %r20, 31 - PSW_I, intr_check_sig
+ nop /* backward */
+
+1: BL preempt_schedule_irq, %r2
+ nop
+ mfctl %cr30, %r1
+ LDREG TI_FLAGS(%r1), %r20
+ bb,<,n %r20, 31 - TIF_NEED_RESCHED, 1b
+#endif /* CONFIG_PREEMPT */
.import do_signal,code
intr_do_signal:
/*
diff --git a/include/asm-parisc/spinlock.h b/include/asm-parisc/spinlock.h
index 16c2ac0..bfa8125 100644
--- a/include/asm-parisc/spinlock.h
+++ b/include/asm-parisc/spinlock.h
@@ -134,14 +134,22 @@ static __inline__ int __raw_write_trylo
return 1;
}
-static __inline__ int __raw_is_read_locked(raw_rwlock_t *rw)
+/*
+ * read_can_lock - would read_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+static __inline__ int __raw_read_can_lock(raw_rwlock_t *rw)
{
- return rw->counter > 0;
+ return rw->counter >= 0;
}
-static __inline__ int __raw_is_write_locked(raw_rwlock_t *rw)
+/*
+ * write_can_lock - would write_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+static __inline int __raw_write_can_lock(raw_rwlock_t *rw)
{
- return rw->counter < 0;
+ return !rw->counter;
}
#endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h
index ac32f14..f2f83b0 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
More information about the parisc-linux
mailing list