aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/list.h15
-rw-r--r--lib/Kconfig.debug9
-rw-r--r--lib/Makefile1
-rw-r--r--lib/list_debug.c77
4 files changed, 102 insertions, 0 deletions
diff --git a/include/linux/list.h b/include/linux/list.h
index 65a5b5ceda49..a9c90287c0ff 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -39,6 +39,7 @@ static inline void INIT_LIST_HEAD(struct list_head *list)
39 * This is only for internal list manipulation where we know 39 * This is only for internal list manipulation where we know
40 * the prev/next entries already! 40 * the prev/next entries already!
41 */ 41 */
42#ifndef CONFIG_DEBUG_LIST
42static inline void __list_add(struct list_head *new, 43static inline void __list_add(struct list_head *new,
43 struct list_head *prev, 44 struct list_head *prev,
44 struct list_head *next) 45 struct list_head *next)
@@ -48,6 +49,11 @@ static inline void __list_add(struct list_head *new,
48 new->prev = prev; 49 new->prev = prev;
49 prev->next = new; 50 prev->next = new;
50} 51}
52#else
53extern void __list_add(struct list_head *new,
54 struct list_head *prev,
55 struct list_head *next);
56#endif
51 57
52/** 58/**
53 * list_add - add a new entry 59 * list_add - add a new entry
@@ -57,10 +63,15 @@ static inline void __list_add(struct list_head *new,
57 * Insert a new entry after the specified head. 63 * Insert a new entry after the specified head.
58 * This is good for implementing stacks. 64 * This is good for implementing stacks.
59 */ 65 */
66#ifndef CONFIG_DEBUG_LIST
60static inline void list_add(struct list_head *new, struct list_head *head) 67static inline void list_add(struct list_head *new, struct list_head *head)
61{ 68{
62 __list_add(new, head, head->next); 69 __list_add(new, head, head->next);
63} 70}
71#else
72extern void list_add(struct list_head *new, struct list_head *head);
73#endif
74
64 75
65/** 76/**
66 * list_add_tail - add a new entry 77 * list_add_tail - add a new entry
@@ -153,12 +164,16 @@ static inline void __list_del(struct list_head * prev, struct list_head * next)
153 * Note: list_empty on entry does not return true after this, the entry is 164 * Note: list_empty on entry does not return true after this, the entry is
154 * in an undefined state. 165 * in an undefined state.
155 */ 166 */
167#ifndef CONFIG_DEBUG_LIST
156static inline void list_del(struct list_head *entry) 168static inline void list_del(struct list_head *entry)
157{ 169{
158 __list_del(entry->prev, entry->next); 170 __list_del(entry->prev, entry->next);
159 entry->next = LIST_POISON1; 171 entry->next = LIST_POISON1;
160 entry->prev = LIST_POISON2; 172 entry->prev = LIST_POISON2;
161} 173}
174#else
175extern void list_del(struct list_head *entry);
176#endif
162 177
163/** 178/**
164 * list_del_rcu - deletes entry from list without re-initialization 179 * list_del_rcu - deletes entry from list without re-initialization
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index b0f5ca72599f..f9ae75cc0145 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -320,6 +320,15 @@ config DEBUG_VM
320 320
321 If unsure, say N. 321 If unsure, say N.
322 322
323config DEBUG_LIST
324 bool "Debug linked list manipulation"
325 depends on DEBUG_KERNEL
326 help
327 Enable this to turn on extended checks in the linked-list
328 walking routines.
329
330 If unsure, say N.
331
323config FRAME_POINTER 332config FRAME_POINTER
324 bool "Compile the kernel with frame pointers" 333 bool "Compile the kernel with frame pointers"
325 depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32 || SUPERH) 334 depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32 || SUPERH)
diff --git a/lib/Makefile b/lib/Makefile
index ef1d37afbbb6..402762fead70 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -28,6 +28,7 @@ lib-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
28obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o 28obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
29obj-$(CONFIG_PLIST) += plist.o 29obj-$(CONFIG_PLIST) += plist.o
30obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o 30obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
31obj-$(CONFIG_DEBUG_LIST) += list_debug.o
31 32
32ifneq ($(CONFIG_HAVE_DEC_LOCK),y) 33ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
33 lib-y += dec_and_lock.o 34 lib-y += dec_and_lock.o
diff --git a/lib/list_debug.c b/lib/list_debug.c
new file mode 100644
index 000000000000..1aae85cef92c
--- /dev/null
+++ b/lib/list_debug.c
@@ -0,0 +1,77 @@
1/*
2 * Copyright 2006, Red Hat, Inc., Dave Jones
3 * Released under the General Public License (GPL).
4 *
5 * This file contains the linked list implementations for
6 * DEBUG_LIST.
7 */
8
9#include <linux/module.h>
10#include <linux/list.h>
11
12/*
13 * Insert a new entry between two known consecutive entries.
14 *
15 * This is only for internal list manipulation where we know
16 * the prev/next entries already!
17 */
18
19void __list_add(struct list_head *new,
20 struct list_head *prev,
21 struct list_head *next)
22{
23 if (unlikely(next->prev != prev)) {
24 printk(KERN_ERR "list_add corruption. next->prev should be %p, but was %p\n",
25 prev, next->prev);
26 BUG();
27 }
28 if (unlikely(prev->next != next)) {
29 printk(KERN_ERR "list_add corruption. prev->next should be %p, but was %p\n",
30 next, prev->next);
31 BUG();
32 }
33 next->prev = new;
34 new->next = next;
35 new->prev = prev;
36 prev->next = new;
37}
38EXPORT_SYMBOL(__list_add);
39
40/**
41 * list_add - add a new entry
42 * @new: new entry to be added
43 * @head: list head to add it after
44 *
45 * Insert a new entry after the specified head.
46 * This is good for implementing stacks.
47 */
48void list_add(struct list_head *new, struct list_head *head)
49{
50 __list_add(new, head, head->next);
51}
52EXPORT_SYMBOL(list_add);
53
54/**
55 * list_del - deletes entry from list.
56 * @entry: the element to delete from the list.
57 * Note: list_empty on entry does not return true after this, the entry is
58 * in an undefined state.
59 */
60void list_del(struct list_head *entry)
61{
62 if (unlikely(entry->prev->next != entry)) {
63 printk(KERN_ERR "list_del corruption. prev->next should be %p, but was %p\n",
64 entry, entry->prev->next);
65 BUG();
66 }
67 if (unlikely(entry->next->prev != entry)) {
68 printk(KERN_ERR "list_del corruption. next->prev should be %p, but was %p\n",
69 entry, entry->next->prev);
70 BUG();
71 }
72 __list_del(entry->prev, entry->next);
73 entry->next = LIST_POISON1;
74 entry->prev = LIST_POISON2;
75}
76EXPORT_SYMBOL(list_del);
77