aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2006-11-25 14:09:36 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-11-25 16:28:34 -0500
commitee3ce191e8eaa4cc15c51a28b34143b36404c4f5 (patch)
tree557c5ade9b92e91f095e4017d97ffe7afd83383f /include/linux
parent5e66b0b5f187c811419ff10cfb5668c028a64d57 (diff)
[PATCH] Enforce "unsigned long flags;" when spinlocking
Make it break or warn if you pass to spin_lock_irqsave() and friends something different from "unsigned long flags;". Suprisingly large amount of these was caught by recent commit c53421b18f205c5f97c604ae55c6a921f034b0f6 and others. Idea is largely from FRV typechecking. Suggestions from Andrew Morton. All stupid typos in first version fixed. Passes allmodconfig on i386, x86_64, alpha, arm as well as my usual config. Note #1: checking with sparse is still needed, because a driver can save and pass around flags or something. So far patch is very intrusive. Note #2: techically, we should break only if sizeof(flags) < sizeof(unsigned long), however, the more pain for getting suspicious code into kernel, the better. Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/irqflags.h37
-rw-r--r--include/linux/spinlock.h53
2 files changed, 76 insertions, 14 deletions
diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h
index 412e025bc5c7..4fe740bf4eae 100644
--- a/include/linux/irqflags.h
+++ b/include/linux/irqflags.h
@@ -11,6 +11,12 @@
11#ifndef _LINUX_TRACE_IRQFLAGS_H 11#ifndef _LINUX_TRACE_IRQFLAGS_H
12#define _LINUX_TRACE_IRQFLAGS_H 12#define _LINUX_TRACE_IRQFLAGS_H
13 13
14#define BUILD_CHECK_IRQ_FLAGS(flags) \
15 do { \
16 BUILD_BUG_ON(sizeof(flags) != sizeof(unsigned long)); \
17 typecheck(unsigned long, flags); \
18 } while (0)
19
14#ifdef CONFIG_TRACE_IRQFLAGS 20#ifdef CONFIG_TRACE_IRQFLAGS
15 extern void trace_hardirqs_on(void); 21 extern void trace_hardirqs_on(void);
16 extern void trace_hardirqs_off(void); 22 extern void trace_hardirqs_off(void);
@@ -50,10 +56,15 @@
50#define local_irq_disable() \ 56#define local_irq_disable() \
51 do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0) 57 do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
52#define local_irq_save(flags) \ 58#define local_irq_save(flags) \
53 do { raw_local_irq_save(flags); trace_hardirqs_off(); } while (0) 59 do { \
60 BUILD_CHECK_IRQ_FLAGS(flags); \
61 raw_local_irq_save(flags); \
62 trace_hardirqs_off(); \
63 } while (0)
54 64
55#define local_irq_restore(flags) \ 65#define local_irq_restore(flags) \
56 do { \ 66 do { \
67 BUILD_CHECK_IRQ_FLAGS(flags); \
57 if (raw_irqs_disabled_flags(flags)) { \ 68 if (raw_irqs_disabled_flags(flags)) { \
58 raw_local_irq_restore(flags); \ 69 raw_local_irq_restore(flags); \
59 trace_hardirqs_off(); \ 70 trace_hardirqs_off(); \
@@ -69,8 +80,16 @@
69 */ 80 */
70# define raw_local_irq_disable() local_irq_disable() 81# define raw_local_irq_disable() local_irq_disable()
71# define raw_local_irq_enable() local_irq_enable() 82# define raw_local_irq_enable() local_irq_enable()
72# define raw_local_irq_save(flags) local_irq_save(flags) 83# define raw_local_irq_save(flags) \
73# define raw_local_irq_restore(flags) local_irq_restore(flags) 84 do { \
85 BUILD_CHECK_IRQ_FLAGS(flags); \
86 local_irq_save(flags); \
87 } while (0)
88# define raw_local_irq_restore(flags) \
89 do { \
90 BUILD_CHECK_IRQ_FLAGS(flags); \
91 local_irq_restore(flags); \
92 } while (0)
74#endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */ 93#endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */
75 94
76#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT 95#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
@@ -80,7 +99,11 @@
80 raw_safe_halt(); \ 99 raw_safe_halt(); \
81 } while (0) 100 } while (0)
82 101
83#define local_save_flags(flags) raw_local_save_flags(flags) 102#define local_save_flags(flags) \
103 do { \
104 BUILD_CHECK_IRQ_FLAGS(flags); \
105 raw_local_save_flags(flags); \
106 } while (0)
84 107
85#define irqs_disabled() \ 108#define irqs_disabled() \
86({ \ 109({ \
@@ -90,7 +113,11 @@
90 raw_irqs_disabled_flags(flags); \ 113 raw_irqs_disabled_flags(flags); \
91}) 114})
92 115
93#define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags) 116#define irqs_disabled_flags(flags) \
117({ \
118 BUILD_CHECK_IRQ_FLAGS(flags); \
119 raw_irqs_disabled_flags(flags); \
120})
94#endif /* CONFIG_X86 */ 121#endif /* CONFIG_X86 */
95 122
96#endif 123#endif
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index b800d2d68b32..54ad37089c49 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -52,6 +52,7 @@
52#include <linux/thread_info.h> 52#include <linux/thread_info.h>
53#include <linux/kernel.h> 53#include <linux/kernel.h>
54#include <linux/stringify.h> 54#include <linux/stringify.h>
55#include <linux/irqflags.h>
55 56
56#include <asm/system.h> 57#include <asm/system.h>
57 58
@@ -183,13 +184,37 @@ do { \
183#define read_lock(lock) _read_lock(lock) 184#define read_lock(lock) _read_lock(lock)
184 185
185#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) 186#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
186#define spin_lock_irqsave(lock, flags) flags = _spin_lock_irqsave(lock) 187#define spin_lock_irqsave(lock, flags) \
187#define read_lock_irqsave(lock, flags) flags = _read_lock_irqsave(lock) 188 do { \
188#define write_lock_irqsave(lock, flags) flags = _write_lock_irqsave(lock) 189 BUILD_CHECK_IRQ_FLAGS(flags); \
190 flags = _spin_lock_irqsave(lock); \
191 } while (0)
192#define read_lock_irqsave(lock, flags) \
193 do { \
194 BUILD_CHECK_IRQ_FLAGS(flags); \
195 flags = _read_lock_irqsave(lock); \
196 } while (0)
197#define write_lock_irqsave(lock, flags) \
198 do { \
199 BUILD_CHECK_IRQ_FLAGS(flags); \
200 flags = _write_lock_irqsave(lock); \
201 } while (0)
189#else 202#else
190#define spin_lock_irqsave(lock, flags) _spin_lock_irqsave(lock, flags) 203#define spin_lock_irqsave(lock, flags) \
191#define read_lock_irqsave(lock, flags) _read_lock_irqsave(lock, flags) 204 do { \
192#define write_lock_irqsave(lock, flags) _write_lock_irqsave(lock, flags) 205 BUILD_CHECK_IRQ_FLAGS(flags); \
206 _spin_lock_irqsave(lock, flags); \
207 } while (0)
208#define read_lock_irqsave(lock, flags) \
209 do { \
210 BUILD_CHECK_IRQ_FLAGS(flags); \
211 _read_lock_irqsave(lock, flags); \
212 } while (0)
213#define write_lock_irqsave(lock, flags) \
214 do { \
215 BUILD_CHECK_IRQ_FLAGS(flags); \
216 _write_lock_irqsave(lock, flags); \
217 } while (0)
193#endif 218#endif
194 219
195#define spin_lock_irq(lock) _spin_lock_irq(lock) 220#define spin_lock_irq(lock) _spin_lock_irq(lock)
@@ -225,15 +250,24 @@ do { \
225#endif 250#endif
226 251
227#define spin_unlock_irqrestore(lock, flags) \ 252#define spin_unlock_irqrestore(lock, flags) \
228 _spin_unlock_irqrestore(lock, flags) 253 do { \
254 BUILD_CHECK_IRQ_FLAGS(flags); \
255 _spin_unlock_irqrestore(lock, flags); \
256 } while (0)
229#define spin_unlock_bh(lock) _spin_unlock_bh(lock) 257#define spin_unlock_bh(lock) _spin_unlock_bh(lock)
230 258
231#define read_unlock_irqrestore(lock, flags) \ 259#define read_unlock_irqrestore(lock, flags) \
232 _read_unlock_irqrestore(lock, flags) 260 do { \
261 BUILD_CHECK_IRQ_FLAGS(flags); \
262 _read_unlock_irqrestore(lock, flags); \
263 } while (0)
233#define read_unlock_bh(lock) _read_unlock_bh(lock) 264#define read_unlock_bh(lock) _read_unlock_bh(lock)
234 265
235#define write_unlock_irqrestore(lock, flags) \ 266#define write_unlock_irqrestore(lock, flags) \
236 _write_unlock_irqrestore(lock, flags) 267 do { \
268 BUILD_CHECK_IRQ_FLAGS(flags); \
269 _write_unlock_irqrestore(lock, flags); \
270 } while (0)
237#define write_unlock_bh(lock) _write_unlock_bh(lock) 271#define write_unlock_bh(lock) _write_unlock_bh(lock)
238 272
239#define spin_trylock_bh(lock) __cond_lock(lock, _spin_trylock_bh(lock)) 273#define spin_trylock_bh(lock) __cond_lock(lock, _spin_trylock_bh(lock))
@@ -247,6 +281,7 @@ do { \
247 281
248#define spin_trylock_irqsave(lock, flags) \ 282#define spin_trylock_irqsave(lock, flags) \
249({ \ 283({ \
284 BUILD_CHECK_IRQ_FLAGS(flags); \
250 local_irq_save(flags); \ 285 local_irq_save(flags); \
251 spin_trylock(lock) ? \ 286 spin_trylock(lock) ? \
252 1 : ({ local_irq_restore(flags); 0; }); \ 287 1 : ({ local_irq_restore(flags); 0; }); \