diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-09-14 08:19:08 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-14 08:19:08 -0400 |
commit | 905ec87e93bc9e01b15c60035cd6a50c636cbaef (patch) | |
tree | 46fd7618d6511611ffc19eb0dd4d7bc6b90a41c2 /lib | |
parent | 1d6ae775d7a948c9575658eb41184fd2e506c0df (diff) | |
parent | 2f4ba45a75d6383b4a1201169a808ffea416ffa0 (diff) |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 8 | ||||
-rw-r--r-- | lib/Kconfig.debug | 8 | ||||
-rw-r--r-- | lib/Makefile | 4 | ||||
-rw-r--r-- | lib/crc16.c | 67 | ||||
-rw-r--r-- | lib/dec_and_lock.c | 3 | ||||
-rw-r--r-- | lib/kernel_lock.c | 3 | ||||
-rw-r--r-- | lib/radix-tree.c | 2 | ||||
-rw-r--r-- | lib/sort.c | 5 | ||||
-rw-r--r-- | lib/spinlock_debug.c | 257 |
9 files changed, 344 insertions, 13 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index e43197efeb9c..3de93357f5ab 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
@@ -12,6 +12,14 @@ config CRC_CCITT | |||
12 | the kernel tree does. Such modules that use library CRC-CCITT | 12 | the kernel tree does. Such modules that use library CRC-CCITT |
13 | functions require M here. | 13 | functions require M here. |
14 | 14 | ||
15 | config CRC16 | ||
16 | tristate "CRC16 functions" | ||
17 | help | ||
18 | This option is provided for the case where no in-kernel-tree | ||
19 | modules require CRC16 functions, but a module built outside | ||
20 | the kernel tree does. Such modules that use library CRC16 | ||
21 | functions require M here. | ||
22 | |||
15 | config CRC32 | 23 | config CRC32 |
16 | tristate "CRC32 functions" | 24 | tristate "CRC32 functions" |
17 | default y | 25 | default y |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 3754c9a8f5c8..016e89a44ac8 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -170,11 +170,11 @@ config DEBUG_FS | |||
170 | 170 | ||
171 | config FRAME_POINTER | 171 | config FRAME_POINTER |
172 | bool "Compile the kernel with frame pointers" | 172 | bool "Compile the kernel with frame pointers" |
173 | depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV || UML) | 173 | depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML) |
174 | default y if DEBUG_INFO && UML | 174 | default y if DEBUG_INFO && UML |
175 | help | 175 | help |
176 | If you say Y here the resulting kernel image will be slightly larger | 176 | If you say Y here the resulting kernel image will be slightly larger |
177 | and slower, but it will give very useful debugging information. | 177 | and slower, but it might give very useful debugging information |
178 | If you don't debug the kernel, you can say N, but we may not be able | 178 | on some architectures or you use external debuggers. |
179 | to solve problems without frame pointers. | 179 | If you don't debug the kernel, you can say N. |
180 | 180 | ||
diff --git a/lib/Makefile b/lib/Makefile index 3e2bd0df23bb..44a46750690a 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -16,6 +16,7 @@ CFLAGS_kobject.o += -DDEBUG | |||
16 | CFLAGS_kobject_uevent.o += -DDEBUG | 16 | CFLAGS_kobject_uevent.o += -DDEBUG |
17 | endif | 17 | endif |
18 | 18 | ||
19 | obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o | ||
19 | lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o | 20 | lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o |
20 | lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o | 21 | lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o |
21 | lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o | 22 | lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o |
@@ -23,11 +24,12 @@ lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o | |||
23 | obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o | 24 | obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o |
24 | obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o | 25 | obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o |
25 | 26 | ||
26 | ifneq ($(CONFIG_HAVE_DEC_LOCK),y) | 27 | ifneq ($(CONFIG_HAVE_DEC_LOCK),y) |
27 | lib-y += dec_and_lock.o | 28 | lib-y += dec_and_lock.o |
28 | endif | 29 | endif |
29 | 30 | ||
30 | obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o | 31 | obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o |
32 | obj-$(CONFIG_CRC16) += crc16.o | ||
31 | obj-$(CONFIG_CRC32) += crc32.o | 33 | obj-$(CONFIG_CRC32) += crc32.o |
32 | obj-$(CONFIG_LIBCRC32C) += libcrc32c.o | 34 | obj-$(CONFIG_LIBCRC32C) += libcrc32c.o |
33 | obj-$(CONFIG_GENERIC_IOMAP) += iomap.o | 35 | obj-$(CONFIG_GENERIC_IOMAP) += iomap.o |
diff --git a/lib/crc16.c b/lib/crc16.c new file mode 100644 index 000000000000..011fe573c666 --- /dev/null +++ b/lib/crc16.c | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * crc16.c | ||
3 | * | ||
4 | * This source code is licensed under the GNU General Public License, | ||
5 | * Version 2. See the file COPYING for more details. | ||
6 | */ | ||
7 | |||
8 | #include <linux/types.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/crc16.h> | ||
11 | |||
12 | /** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */ | ||
13 | u16 const crc16_table[256] = { | ||
14 | 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, | ||
15 | 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, | ||
16 | 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, | ||
17 | 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, | ||
18 | 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, | ||
19 | 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, | ||
20 | 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, | ||
21 | 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, | ||
22 | 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, | ||
23 | 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, | ||
24 | 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, | ||
25 | 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, | ||
26 | 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, | ||
27 | 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, | ||
28 | 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, | ||
29 | 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, | ||
30 | 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, | ||
31 | 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, | ||
32 | 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, | ||
33 | 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, | ||
34 | 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, | ||
35 | 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, | ||
36 | 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, | ||
37 | 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, | ||
38 | 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, | ||
39 | 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, | ||
40 | 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, | ||
41 | 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, | ||
42 | 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, | ||
43 | 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, | ||
44 | 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, | ||
45 | 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 | ||
46 | }; | ||
47 | EXPORT_SYMBOL(crc16_table); | ||
48 | |||
49 | /** | ||
50 | * Compute the CRC-16 for the data buffer | ||
51 | * | ||
52 | * @param crc previous CRC value | ||
53 | * @param buffer data pointer | ||
54 | * @param len number of bytes in the buffer | ||
55 | * @return the updated CRC value | ||
56 | */ | ||
57 | u16 crc16(u16 crc, u8 const *buffer, size_t len) | ||
58 | { | ||
59 | while (len--) | ||
60 | crc = crc16_byte(crc, *buffer++); | ||
61 | return crc; | ||
62 | } | ||
63 | EXPORT_SYMBOL(crc16); | ||
64 | |||
65 | MODULE_DESCRIPTION("CRC16 calculations"); | ||
66 | MODULE_LICENSE("GPL"); | ||
67 | |||
diff --git a/lib/dec_and_lock.c b/lib/dec_and_lock.c index 6658d81e1836..2377af057d09 100644 --- a/lib/dec_and_lock.c +++ b/lib/dec_and_lock.c | |||
@@ -25,8 +25,6 @@ | |||
25 | * this is trivially done efficiently using a load-locked | 25 | * this is trivially done efficiently using a load-locked |
26 | * store-conditional approach, for example. | 26 | * store-conditional approach, for example. |
27 | */ | 27 | */ |
28 | |||
29 | #ifndef ATOMIC_DEC_AND_LOCK | ||
30 | int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) | 28 | int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) |
31 | { | 29 | { |
32 | spin_lock(lock); | 30 | spin_lock(lock); |
@@ -37,4 +35,3 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) | |||
37 | } | 35 | } |
38 | 36 | ||
39 | EXPORT_SYMBOL(_atomic_dec_and_lock); | 37 | EXPORT_SYMBOL(_atomic_dec_and_lock); |
40 | #endif | ||
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c index bd2bc5d887b8..cb5490ec00f2 100644 --- a/lib/kernel_lock.c +++ b/lib/kernel_lock.c | |||
@@ -177,8 +177,7 @@ static inline void __lock_kernel(void) | |||
177 | 177 | ||
178 | static inline void __unlock_kernel(void) | 178 | static inline void __unlock_kernel(void) |
179 | { | 179 | { |
180 | _raw_spin_unlock(&kernel_flag); | 180 | spin_unlock(&kernel_flag); |
181 | preempt_enable(); | ||
182 | } | 181 | } |
183 | 182 | ||
184 | /* | 183 | /* |
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index b972dd29289d..6a8bc6e06431 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
@@ -110,7 +110,7 @@ radix_tree_node_free(struct radix_tree_node *node) | |||
110 | * success, return zero, with preemption disabled. On error, return -ENOMEM | 110 | * success, return zero, with preemption disabled. On error, return -ENOMEM |
111 | * with preemption not disabled. | 111 | * with preemption not disabled. |
112 | */ | 112 | */ |
113 | int radix_tree_preload(int gfp_mask) | 113 | int radix_tree_preload(unsigned int __nocast gfp_mask) |
114 | { | 114 | { |
115 | struct radix_tree_preload *rtp; | 115 | struct radix_tree_preload *rtp; |
116 | struct radix_tree_node *node; | 116 | struct radix_tree_node *node; |
diff --git a/lib/sort.c b/lib/sort.c index b73dbb0e7c83..ddc4d35df289 100644 --- a/lib/sort.c +++ b/lib/sort.c | |||
@@ -6,15 +6,16 @@ | |||
6 | 6 | ||
7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/sort.h> | ||
9 | 10 | ||
10 | void u32_swap(void *a, void *b, int size) | 11 | static void u32_swap(void *a, void *b, int size) |
11 | { | 12 | { |
12 | u32 t = *(u32 *)a; | 13 | u32 t = *(u32 *)a; |
13 | *(u32 *)a = *(u32 *)b; | 14 | *(u32 *)a = *(u32 *)b; |
14 | *(u32 *)b = t; | 15 | *(u32 *)b = t; |
15 | } | 16 | } |
16 | 17 | ||
17 | void generic_swap(void *a, void *b, int size) | 18 | static void generic_swap(void *a, void *b, int size) |
18 | { | 19 | { |
19 | char t; | 20 | char t; |
20 | 21 | ||
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c new file mode 100644 index 000000000000..906ad101eab3 --- /dev/null +++ b/lib/spinlock_debug.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * Copyright 2005, Red Hat, Inc., Ingo Molnar | ||
3 | * Released under the General Public License (GPL). | ||
4 | * | ||
5 | * This file contains the spinlock/rwlock implementations for | ||
6 | * DEBUG_SPINLOCK. | ||
7 | */ | ||
8 | |||
9 | #include <linux/config.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/delay.h> | ||
13 | |||
14 | static void spin_bug(spinlock_t *lock, const char *msg) | ||
15 | { | ||
16 | static long print_once = 1; | ||
17 | struct task_struct *owner = NULL; | ||
18 | |||
19 | if (xchg(&print_once, 0)) { | ||
20 | if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT) | ||
21 | owner = lock->owner; | ||
22 | printk("BUG: spinlock %s on CPU#%d, %s/%d\n", | ||
23 | msg, smp_processor_id(), current->comm, current->pid); | ||
24 | printk(" lock: %p, .magic: %08x, .owner: %s/%d, .owner_cpu: %d\n", | ||
25 | lock, lock->magic, | ||
26 | owner ? owner->comm : "<none>", | ||
27 | owner ? owner->pid : -1, | ||
28 | lock->owner_cpu); | ||
29 | dump_stack(); | ||
30 | #ifdef CONFIG_SMP | ||
31 | /* | ||
32 | * We cannot continue on SMP: | ||
33 | */ | ||
34 | // panic("bad locking"); | ||
35 | #endif | ||
36 | } | ||
37 | } | ||
38 | |||
39 | #define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg) | ||
40 | |||
41 | static inline void debug_spin_lock_before(spinlock_t *lock) | ||
42 | { | ||
43 | SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); | ||
44 | SPIN_BUG_ON(lock->owner == current, lock, "recursion"); | ||
45 | SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), | ||
46 | lock, "cpu recursion"); | ||
47 | } | ||
48 | |||
49 | static inline void debug_spin_lock_after(spinlock_t *lock) | ||
50 | { | ||
51 | lock->owner_cpu = raw_smp_processor_id(); | ||
52 | lock->owner = current; | ||
53 | } | ||
54 | |||
55 | static inline void debug_spin_unlock(spinlock_t *lock) | ||
56 | { | ||
57 | SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); | ||
58 | SPIN_BUG_ON(!spin_is_locked(lock), lock, "already unlocked"); | ||
59 | SPIN_BUG_ON(lock->owner != current, lock, "wrong owner"); | ||
60 | SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), | ||
61 | lock, "wrong CPU"); | ||
62 | lock->owner = SPINLOCK_OWNER_INIT; | ||
63 | lock->owner_cpu = -1; | ||
64 | } | ||
65 | |||
66 | static void __spin_lock_debug(spinlock_t *lock) | ||
67 | { | ||
68 | int print_once = 1; | ||
69 | u64 i; | ||
70 | |||
71 | for (;;) { | ||
72 | for (i = 0; i < loops_per_jiffy * HZ; i++) { | ||
73 | cpu_relax(); | ||
74 | if (__raw_spin_trylock(&lock->raw_lock)) | ||
75 | return; | ||
76 | } | ||
77 | /* lockup suspected: */ | ||
78 | if (print_once) { | ||
79 | print_once = 0; | ||
80 | printk("BUG: spinlock lockup on CPU#%d, %s/%d, %p\n", | ||
81 | smp_processor_id(), current->comm, current->pid, | ||
82 | lock); | ||
83 | dump_stack(); | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
88 | void _raw_spin_lock(spinlock_t *lock) | ||
89 | { | ||
90 | debug_spin_lock_before(lock); | ||
91 | if (unlikely(!__raw_spin_trylock(&lock->raw_lock))) | ||
92 | __spin_lock_debug(lock); | ||
93 | debug_spin_lock_after(lock); | ||
94 | } | ||
95 | |||
96 | int _raw_spin_trylock(spinlock_t *lock) | ||
97 | { | ||
98 | int ret = __raw_spin_trylock(&lock->raw_lock); | ||
99 | |||
100 | if (ret) | ||
101 | debug_spin_lock_after(lock); | ||
102 | #ifndef CONFIG_SMP | ||
103 | /* | ||
104 | * Must not happen on UP: | ||
105 | */ | ||
106 | SPIN_BUG_ON(!ret, lock, "trylock failure on UP"); | ||
107 | #endif | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | void _raw_spin_unlock(spinlock_t *lock) | ||
112 | { | ||
113 | debug_spin_unlock(lock); | ||
114 | __raw_spin_unlock(&lock->raw_lock); | ||
115 | } | ||
116 | |||
117 | static void rwlock_bug(rwlock_t *lock, const char *msg) | ||
118 | { | ||
119 | static long print_once = 1; | ||
120 | |||
121 | if (xchg(&print_once, 0)) { | ||
122 | printk("BUG: rwlock %s on CPU#%d, %s/%d, %p\n", msg, | ||
123 | smp_processor_id(), current->comm, current->pid, lock); | ||
124 | dump_stack(); | ||
125 | #ifdef CONFIG_SMP | ||
126 | /* | ||
127 | * We cannot continue on SMP: | ||
128 | */ | ||
129 | panic("bad locking"); | ||
130 | #endif | ||
131 | } | ||
132 | } | ||
133 | |||
134 | #define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg) | ||
135 | |||
136 | static void __read_lock_debug(rwlock_t *lock) | ||
137 | { | ||
138 | int print_once = 1; | ||
139 | u64 i; | ||
140 | |||
141 | for (;;) { | ||
142 | for (i = 0; i < loops_per_jiffy * HZ; i++) { | ||
143 | cpu_relax(); | ||
144 | if (__raw_read_trylock(&lock->raw_lock)) | ||
145 | return; | ||
146 | } | ||
147 | /* lockup suspected: */ | ||
148 | if (print_once) { | ||
149 | print_once = 0; | ||
150 | printk("BUG: read-lock lockup on CPU#%d, %s/%d, %p\n", | ||
151 | smp_processor_id(), current->comm, current->pid, | ||
152 | lock); | ||
153 | dump_stack(); | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | |||
158 | void _raw_read_lock(rwlock_t *lock) | ||
159 | { | ||
160 | RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | ||
161 | if (unlikely(!__raw_read_trylock(&lock->raw_lock))) | ||
162 | __read_lock_debug(lock); | ||
163 | } | ||
164 | |||
165 | int _raw_read_trylock(rwlock_t *lock) | ||
166 | { | ||
167 | int ret = __raw_read_trylock(&lock->raw_lock); | ||
168 | |||
169 | #ifndef CONFIG_SMP | ||
170 | /* | ||
171 | * Must not happen on UP: | ||
172 | */ | ||
173 | RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP"); | ||
174 | #endif | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | void _raw_read_unlock(rwlock_t *lock) | ||
179 | { | ||
180 | RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | ||
181 | __raw_read_unlock(&lock->raw_lock); | ||
182 | } | ||
183 | |||
184 | static inline void debug_write_lock_before(rwlock_t *lock) | ||
185 | { | ||
186 | RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | ||
187 | RWLOCK_BUG_ON(lock->owner == current, lock, "recursion"); | ||
188 | RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), | ||
189 | lock, "cpu recursion"); | ||
190 | } | ||
191 | |||
192 | static inline void debug_write_lock_after(rwlock_t *lock) | ||
193 | { | ||
194 | lock->owner_cpu = raw_smp_processor_id(); | ||
195 | lock->owner = current; | ||
196 | } | ||
197 | |||
198 | static inline void debug_write_unlock(rwlock_t *lock) | ||
199 | { | ||
200 | RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | ||
201 | RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner"); | ||
202 | RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), | ||
203 | lock, "wrong CPU"); | ||
204 | lock->owner = SPINLOCK_OWNER_INIT; | ||
205 | lock->owner_cpu = -1; | ||
206 | } | ||
207 | |||
208 | static void __write_lock_debug(rwlock_t *lock) | ||
209 | { | ||
210 | int print_once = 1; | ||
211 | u64 i; | ||
212 | |||
213 | for (;;) { | ||
214 | for (i = 0; i < loops_per_jiffy * HZ; i++) { | ||
215 | cpu_relax(); | ||
216 | if (__raw_write_trylock(&lock->raw_lock)) | ||
217 | return; | ||
218 | } | ||
219 | /* lockup suspected: */ | ||
220 | if (print_once) { | ||
221 | print_once = 0; | ||
222 | printk("BUG: write-lock lockup on CPU#%d, %s/%d, %p\n", | ||
223 | smp_processor_id(), current->comm, current->pid, | ||
224 | lock); | ||
225 | dump_stack(); | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | void _raw_write_lock(rwlock_t *lock) | ||
231 | { | ||
232 | debug_write_lock_before(lock); | ||
233 | if (unlikely(!__raw_write_trylock(&lock->raw_lock))) | ||
234 | __write_lock_debug(lock); | ||
235 | debug_write_lock_after(lock); | ||
236 | } | ||
237 | |||
238 | int _raw_write_trylock(rwlock_t *lock) | ||
239 | { | ||
240 | int ret = __raw_write_trylock(&lock->raw_lock); | ||
241 | |||
242 | if (ret) | ||
243 | debug_write_lock_after(lock); | ||
244 | #ifndef CONFIG_SMP | ||
245 | /* | ||
246 | * Must not happen on UP: | ||
247 | */ | ||
248 | RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP"); | ||
249 | #endif | ||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | void _raw_write_unlock(rwlock_t *lock) | ||
254 | { | ||
255 | debug_write_unlock(lock); | ||
256 | __raw_write_unlock(&lock->raw_lock); | ||
257 | } | ||