summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-07-03 08:30:07 -0500
committerThomas Gleixner <tglx@linutronix.de>2009-07-29 23:30:38 +0200
commite9888fb95225bb3b786d79fd983eb67e1acad338 (patch)
treed09bc138fec534e17b57a559f36a5d8c7e49973f /lib
parent94b3cbf2548a023b4187e252043eac367f84740c (diff)
downloadlwn-e9888fb95225bb3b786d79fd983eb67e1acad338.tar.gz
lwn-e9888fb95225bb3b786d79fd983eb67e1acad338.zip
rt: core implementation
Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig.debug4
-rw-r--r--lib/Makefile3
-rw-r--r--lib/kernel_lock.c14
-rw-r--r--lib/locking-selftest.c29
-rw-r--r--lib/radix-tree.c6
5 files changed, 42 insertions, 14 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 12327b2bb785..8a2ddd3f0922 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -397,6 +397,8 @@ config DEBUG_RT_MUTEXES
help
This allows rt mutex semantics violations and rt mutex related
deadlocks (lockups) to be detected and reported automatically.
+ When realtime preemption is enabled this includes spinlocks,
+ rwlocks, mutexes and (rw)semaphores
config DEBUG_PI_LIST
bool
@@ -420,7 +422,7 @@ config DEBUG_SPINLOCK
config DEBUG_MUTEXES
bool "Mutex debugging: basic checks"
- depends on DEBUG_KERNEL
+ depends on DEBUG_KERNEL && !PREEMPT_RT
help
This feature allows mutex semantics violations to be detected and
reported.
diff --git a/lib/Makefile b/lib/Makefile
index b6d1857bbf08..0d2ee155f4c9 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -34,7 +34,8 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
-lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
+obj-$(CONFIG_PREEMPT_RT) += plist.o
+obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o
lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
index 54625bec6fb9..709c432b8a92 100644
--- a/lib/kernel_lock.c
+++ b/lib/kernel_lock.c
@@ -35,6 +35,8 @@ DEFINE_SEMAPHORE(kernel_sem);
* about recursion, both due to the down() and due to the enabling of
* preemption. schedule() will re-check the preemption flag after
* reacquiring the semaphore.
+ *
+ * Called with interrupts disabled.
*/
int __lockfunc __reacquire_kernel_lock(void)
{
@@ -67,11 +69,15 @@ void __lockfunc lock_kernel(void)
struct task_struct *task = current;
int depth = task->lock_depth + 1;
- if (likely(!depth))
+ if (likely(!depth)) {
/*
* No recursion worries - we set up lock_depth _after_
*/
down(&kernel_sem);
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+ current->last_kernel_lock = __builtin_return_address(0);
+#endif
+ }
task->lock_depth = depth;
}
@@ -82,8 +88,12 @@ void __lockfunc unlock_kernel(void)
BUG_ON(task->lock_depth < 0);
- if (likely(--task->lock_depth < 0))
+ if (likely(--task->lock_depth < 0)) {
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+ current->last_kernel_lock = NULL;
+#endif
up(&kernel_sem);
+ }
}
EXPORT_SYMBOL(lock_kernel);
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index 619313ed6c46..65e7eab8498e 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -158,7 +158,7 @@ static void init_shared_classes(void)
local_bh_disable(); \
local_irq_disable(); \
lockdep_softirq_enter(); \
- WARN_ON(!in_softirq());
+ /* FIXME: preemptible softirqs. WARN_ON(!in_softirq()); */
#define SOFTIRQ_EXIT() \
lockdep_softirq_exit(); \
@@ -550,6 +550,11 @@ GENERATE_TESTCASE(init_held_rsem)
#undef E
/*
+ * FIXME: turns these into raw-spinlock tests on -rt
+ */
+#ifndef CONFIG_PREEMPT_RT
+
+/*
* locking an irq-safe lock with irqs enabled:
*/
#define E1() \
@@ -890,6 +895,8 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft)
#include "locking-selftest-softirq.h"
// GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion2_soft)
+#endif /* !CONFIG_PREEMPT_RT */
+
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define I_SPINLOCK(x) lockdep_reset_lock(&lock_##x.dep_map)
# define I_RWLOCK(x) lockdep_reset_lock(&rwlock_##x.dep_map)
@@ -998,7 +1005,7 @@ static inline void print_testname(const char *testname)
#define DO_TESTCASE_1(desc, name, nr) \
print_testname(desc"/"#nr); \
- dotest(name##_##nr, SUCCESS, LOCKTYPE_RWLOCK); \
+ dotest(name##_##nr, SUCCESS, LOCKTYPE_RWLOCK); \
printk("\n");
#define DO_TESTCASE_1B(desc, name, nr) \
@@ -1006,17 +1013,17 @@ static inline void print_testname(const char *testname)
dotest(name##_##nr, FAILURE, LOCKTYPE_RWLOCK); \
printk("\n");
-#define DO_TESTCASE_3(desc, name, nr) \
- print_testname(desc"/"#nr); \
- dotest(name##_spin_##nr, FAILURE, LOCKTYPE_SPIN); \
- dotest(name##_wlock_##nr, FAILURE, LOCKTYPE_RWLOCK); \
+#define DO_TESTCASE_3(desc, name, nr) \
+ print_testname(desc"/"#nr); \
+ dotest(name##_spin_##nr, FAILURE, LOCKTYPE_SPIN); \
+ dotest(name##_wlock_##nr, FAILURE, LOCKTYPE_RWLOCK); \
dotest(name##_rlock_##nr, SUCCESS, LOCKTYPE_RWLOCK); \
printk("\n");
-#define DO_TESTCASE_3RW(desc, name, nr) \
- print_testname(desc"/"#nr); \
+#define DO_TESTCASE_3RW(desc, name, nr) \
+ print_testname(desc"/"#nr); \
dotest(name##_spin_##nr, FAILURE, LOCKTYPE_SPIN|LOCKTYPE_RWLOCK);\
- dotest(name##_wlock_##nr, FAILURE, LOCKTYPE_RWLOCK); \
+ dotest(name##_wlock_##nr, FAILURE, LOCKTYPE_RWLOCK); \
dotest(name##_rlock_##nr, SUCCESS, LOCKTYPE_RWLOCK); \
printk("\n");
@@ -1047,7 +1054,7 @@ static inline void print_testname(const char *testname)
print_testname(desc); \
dotest(name##_spin, FAILURE, LOCKTYPE_SPIN); \
dotest(name##_wlock, FAILURE, LOCKTYPE_RWLOCK); \
- dotest(name##_rlock, SUCCESS, LOCKTYPE_RWLOCK); \
+ dotest(name##_rlock, SUCCESS, LOCKTYPE_RWLOCK); \
dotest(name##_mutex, FAILURE, LOCKTYPE_MUTEX); \
dotest(name##_wsem, FAILURE, LOCKTYPE_RWSEM); \
dotest(name##_rsem, FAILURE, LOCKTYPE_RWSEM); \
@@ -1179,6 +1186,7 @@ void locking_selftest(void)
/*
* irq-context testcases:
*/
+#ifndef CONFIG_PREEMPT_RT
DO_TESTCASE_2x6("irqs-on + irq-safe-A", irqsafe1);
DO_TESTCASE_2x3("sirq-safe-A => hirqs-on", irqsafe2A);
DO_TESTCASE_2x6("safe-A + irqs-on", irqsafe2B);
@@ -1188,6 +1196,7 @@ void locking_selftest(void)
DO_TESTCASE_6x2("irq read-recursion", irq_read_recursion);
// DO_TESTCASE_6x2B("irq read-recursion #2", irq_read_recursion2);
+#endif
if (unexpected_testcase_failures) {
printk("-----------------------------------------------------------------\n");
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 23abbd93cae1..e209012e5d31 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -157,12 +157,14 @@ radix_tree_node_alloc(struct radix_tree_root *root)
* succeed in getting a node here (and never reach
* kmem_cache_alloc)
*/
+ rtp = &get_cpu_var(radix_tree_preloads);
rtp = &__get_cpu_var(radix_tree_preloads);
if (rtp->nr) {
ret = rtp->nodes[rtp->nr - 1];
rtp->nodes[rtp->nr - 1] = NULL;
rtp->nr--;
}
+ put_cpu_var(radix_tree_preloads);
}
if (ret == NULL)
ret = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
@@ -195,6 +197,8 @@ radix_tree_node_free(struct radix_tree_node *node)
call_rcu(&node->rcu_head, radix_tree_node_rcu_free);
}
+#ifndef CONFIG_PREEMPT_RT
+
/*
* Load up this CPU's radix_tree_node buffer with sufficient objects to
* ensure that the addition of a single element in the tree cannot fail. On
@@ -227,6 +231,8 @@ out:
}
EXPORT_SYMBOL(radix_tree_preload);
+#endif
+
/*
* Return the maximum key which can be store into a
* radix tree with height HEIGHT.