diff options
-rw-r--r-- | include/linux/list.h | 15 | ||||
-rw-r--r-- | lib/Kconfig.debug | 9 | ||||
-rw-r--r-- | lib/Makefile | 1 | ||||
-rw-r--r-- | lib/list_debug.c | 77 |
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 | ||
42 | static inline void __list_add(struct list_head *new, | 43 | static 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 | ||
53 | extern 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 | ||
60 | static inline void list_add(struct list_head *new, struct list_head *head) | 67 | static 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 | ||
72 | extern 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 | ||
156 | static inline void list_del(struct list_head *entry) | 168 | static 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 | ||
175 | extern 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 | ||
323 | config 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 | |||
323 | config FRAME_POINTER | 332 | config 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 | |||
28 | obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o | 28 | obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o |
29 | obj-$(CONFIG_PLIST) += plist.o | 29 | obj-$(CONFIG_PLIST) += plist.o |
30 | obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o | 30 | obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o |
31 | obj-$(CONFIG_DEBUG_LIST) += list_debug.o | ||
31 | 32 | ||
32 | ifneq ($(CONFIG_HAVE_DEC_LOCK),y) | 33 | ifneq ($(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 | |||
19 | void __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 | } | ||
38 | EXPORT_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 | */ | ||
48 | void list_add(struct list_head *new, struct list_head *head) | ||
49 | { | ||
50 | __list_add(new, head, head->next); | ||
51 | } | ||
52 | EXPORT_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 | */ | ||
60 | void 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 | } | ||
76 | EXPORT_SYMBOL(list_del); | ||
77 | |||