aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig.debug8
-rw-r--r--lib/Makefile1
-rw-r--r--lib/dec_and_lock.c3
-rw-r--r--lib/kernel_lock.c3
-rw-r--r--lib/radix-tree.c2
-rw-r--r--lib/sort.c5
-rw-r--r--lib/spinlock_debug.c257
7 files changed, 267 insertions, 12 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 3754c9a8f5c..016e89a44ac 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -170,11 +170,11 @@ config DEBUG_FS
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
- depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV || UML)
+ depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML)
default y if DEBUG_INFO && UML
help
If you say Y here the resulting kernel image will be slightly larger
- and slower, but it will give very useful debugging information.
- If you don't debug the kernel, you can say N, but we may not be able
- to solve problems without frame pointers.
+ and slower, but it might give very useful debugging information
+ on some architectures or you use external debuggers.
+ If you don't debug the kernel, you can say N.
diff --git a/lib/Makefile b/lib/Makefile
index d9c38ba05e7..44a46750690 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -16,6 +16,7 @@ CFLAGS_kobject.o += -DDEBUG
CFLAGS_kobject_uevent.o += -DDEBUG
endif
+obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o
diff --git a/lib/dec_and_lock.c b/lib/dec_and_lock.c
index 6658d81e183..2377af057d0 100644
--- a/lib/dec_and_lock.c
+++ b/lib/dec_and_lock.c
@@ -25,8 +25,6 @@
* this is trivially done efficiently using a load-locked
* store-conditional approach, for example.
*/
-
-#ifndef ATOMIC_DEC_AND_LOCK
int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
{
spin_lock(lock);
@@ -37,4 +35,3 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
}
EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
index bd2bc5d887b..cb5490ec00f 100644
--- a/lib/kernel_lock.c
+++ b/lib/kernel_lock.c
@@ -177,8 +177,7 @@ static inline void __lock_kernel(void)
static inline void __unlock_kernel(void)
{
- _raw_spin_unlock(&kernel_flag);
- preempt_enable();
+ spin_unlock(&kernel_flag);
}
/*
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index b972dd29289..6a8bc6e0643 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -110,7 +110,7 @@ radix_tree_node_free(struct radix_tree_node *node)
* success, return zero, with preemption disabled. On error, return -ENOMEM
* with preemption not disabled.
*/
-int radix_tree_preload(int gfp_mask)
+int radix_tree_preload(unsigned int __nocast gfp_mask)
{
struct radix_tree_preload *rtp;
struct radix_tree_node *node;
diff --git a/lib/sort.c b/lib/sort.c
index b73dbb0e7c8..ddc4d35df28 100644
--- a/lib/sort.c
+++ b/lib/sort.c
@@ -6,15 +6,16 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/sort.h>
-void u32_swap(void *a, void *b, int size)
+static void u32_swap(void *a, void *b, int size)
{
u32 t = *(u32 *)a;
*(u32 *)a = *(u32 *)b;
*(u32 *)b = t;
}
-void generic_swap(void *a, void *b, int size)
+static void generic_swap(void *a, void *b, int size)
{
char t;
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
new file mode 100644
index 00000000000..906ad101eab
--- /dev/null
+++ b/lib/spinlock_debug.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ *
+ * This file contains the spinlock/rwlock implementations for
+ * DEBUG_SPINLOCK.
+ */
+
+#include <linux/config.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+static void spin_bug(spinlock_t *lock, const char *msg)
+{
+ static long print_once = 1;
+ struct task_struct *owner = NULL;
+
+ if (xchg(&print_once, 0)) {
+ if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT)
+ owner = lock->owner;
+ printk("BUG: spinlock %s on CPU#%d, %s/%d\n",
+ msg, smp_processor_id(), current->comm, current->pid);
+ printk(" lock: %p, .magic: %08x, .owner: %s/%d, .owner_cpu: %d\n",
+ lock, lock->magic,
+ owner ? owner->comm : "<none>",
+ owner ? owner->pid : -1,
+ lock->owner_cpu);
+ dump_stack();
+#ifdef CONFIG_SMP
+ /*
+ * We cannot continue on SMP:
+ */
+// panic("bad locking");
+#endif
+ }
+}
+
+#define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg)
+
+static inline void debug_spin_lock_before(spinlock_t *lock)
+{
+ SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
+ SPIN_BUG_ON(lock->owner == current, lock, "recursion");
+ SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
+ lock, "cpu recursion");
+}
+
+static inline void debug_spin_lock_after(spinlock_t *lock)
+{
+ lock->owner_cpu = raw_smp_processor_id();
+ lock->owner = current;
+}
+
+static inline void debug_spin_unlock(spinlock_t *lock)
+{
+ SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
+ SPIN_BUG_ON(!spin_is_locked(lock), lock, "already unlocked");
+ SPIN_BUG_ON(lock->owner != current, lock, "wrong owner");
+ SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
+ lock, "wrong CPU");
+ lock->owner = SPINLOCK_OWNER_INIT;
+ lock->owner_cpu = -1;
+}
+
+static void __spin_lock_debug(spinlock_t *lock)
+{
+ int print_once = 1;
+ u64 i;
+
+ for (;;) {
+ for (i = 0; i < loops_per_jiffy * HZ; i++) {
+ cpu_relax();
+ if (__raw_spin_trylock(&lock->raw_lock))
+ return;
+ }
+ /* lockup suspected: */
+ if (print_once) {
+ print_once = 0;
+ printk("BUG: spinlock lockup on CPU#%d, %s/%d, %p\n",
+ smp_processor_id(), current->comm, current->pid,
+ lock);
+ dump_stack();
+ }
+ }
+}
+
+void _raw_spin_lock(spinlock_t *lock)
+{
+ debug_spin_lock_before(lock);
+ if (unlikely(!__raw_spin_trylock(&lock->raw_lock)))
+ __spin_lock_debug(lock);
+ debug_spin_lock_after(lock);
+}
+
+int _raw_spin_trylock(spinlock_t *lock)
+{
+ int ret = __raw_spin_trylock(&lock->raw_lock);
+
+ if (ret)
+ debug_spin_lock_after(lock);
+#ifndef CONFIG_SMP
+ /*
+ * Must not happen on UP:
+ */
+ SPIN_BUG_ON(!ret, lock, "trylock failure on UP");
+#endif
+ return ret;
+}
+
+void _raw_spin_unlock(spinlock_t *lock)
+{
+ debug_spin_unlock(lock);
+ __raw_spin_unlock(&lock->raw_lock);
+}
+
+static void rwlock_bug(rwlock_t *lock, const char *msg)
+{
+ static long print_once = 1;
+
+ if (xchg(&print_once, 0)) {
+ printk("BUG: rwlock %s on CPU#%d, %s/%d, %p\n", msg,
+ smp_processor_id(), current->comm, current->pid, lock);
+ dump_stack();
+#ifdef CONFIG_SMP
+ /*
+ * We cannot continue on SMP:
+ */
+ panic("bad locking");
+#endif
+ }
+}
+
+#define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg)
+
+static void __read_lock_debug(rwlock_t *lock)
+{
+ int print_once = 1;
+ u64 i;
+
+ for (;;) {
+ for (i = 0; i < loops_per_jiffy * HZ; i++) {
+ cpu_relax();
+ if (__raw_read_trylock(&lock->raw_lock))
+ return;
+ }
+ /* lockup suspected: */
+ if (print_once) {
+ print_once = 0;
+ printk("BUG: read-lock lockup on CPU#%d, %s/%d, %p\n",
+ smp_processor_id(), current->comm, current->pid,
+ lock);
+ dump_stack();
+ }
+ }
+}
+
+void _raw_read_lock(rwlock_t *lock)
+{
+ RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
+ if (unlikely(!__raw_read_trylock(&lock->raw_lock)))
+ __read_lock_debug(lock);
+}
+
+int _raw_read_trylock(rwlock_t *lock)
+{
+ int ret = __raw_read_trylock(&lock->raw_lock);
+
+#ifndef CONFIG_SMP
+ /*
+ * Must not happen on UP:
+ */
+ RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
+#endif
+ return ret;
+}
+
+void _raw_read_unlock(rwlock_t *lock)
+{
+ RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
+ __raw_read_unlock(&lock->raw_lock);
+}
+
+static inline void debug_write_lock_before(rwlock_t *lock)
+{
+ RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
+ RWLOCK_BUG_ON(lock->owner == current, lock, "recursion");
+ RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
+ lock, "cpu recursion");
+}
+
+static inline void debug_write_lock_after(rwlock_t *lock)
+{
+ lock->owner_cpu = raw_smp_processor_id();
+ lock->owner = current;
+}
+
+static inline void debug_write_unlock(rwlock_t *lock)
+{
+ RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
+ RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner");
+ RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
+ lock, "wrong CPU");
+ lock->owner = SPINLOCK_OWNER_INIT;
+ lock->owner_cpu = -1;
+}
+
+static void __write_lock_debug(rwlock_t *lock)
+{
+ int print_once = 1;
+ u64 i;
+
+ for (;;) {
+ for (i = 0; i < loops_per_jiffy * HZ; i++) {
+ cpu_relax();
+ if (__raw_write_trylock(&lock->raw_lock))
+ return;
+ }
+ /* lockup suspected: */
+ if (print_once) {
+ print_once = 0;
+ printk("BUG: write-lock lockup on CPU#%d, %s/%d, %p\n",
+ smp_processor_id(), current->comm, current->pid,
+ lock);
+ dump_stack();
+ }
+ }
+}
+
+void _raw_write_lock(rwlock_t *lock)
+{
+ debug_write_lock_before(lock);
+ if (unlikely(!__raw_write_trylock(&lock->raw_lock)))
+ __write_lock_debug(lock);
+ debug_write_lock_after(lock);
+}
+
+int _raw_write_trylock(rwlock_t *lock)
+{
+ int ret = __raw_write_trylock(&lock->raw_lock);
+
+ if (ret)
+ debug_write_lock_after(lock);
+#ifndef CONFIG_SMP
+ /*
+ * Must not happen on UP:
+ */
+ RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
+#endif
+ return ret;
+}
+
+void _raw_write_unlock(rwlock_t *lock)
+{
+ debug_write_unlock(lock);
+ __raw_write_unlock(&lock->raw_lock);
+}