1 #ifndef _LOCKHELP_H
2 #define _LOCKHELP_H
3 #include <linux/config.h>
4 
5 #include <linux/spinlock.h>
6 #include <asm/atomic.h>
7 #include <linux/interrupt.h>
8 #include <linux/smp.h>
9 
10 /* Header to do help in lock debugging. */
11 
12 #ifdef CONFIG_NETFILTER_DEBUG
13 struct spinlock_debug
14 {
15 	spinlock_t l;
16 	atomic_t locked_by;
17 };
18 
19 struct rwlock_debug
20 {
21 	rwlock_t l;
22 	long read_locked_map;
23 	long write_locked_map;
24 };
25 
26 #define DECLARE_LOCK(l) 						\
27 struct spinlock_debug l = { SPIN_LOCK_UNLOCKED, ATOMIC_INIT(-1) }
28 #define DECLARE_LOCK_EXTERN(l) 			\
29 extern struct spinlock_debug l
30 #define DECLARE_RWLOCK(l)				\
31 struct rwlock_debug l = { RW_LOCK_UNLOCKED, 0, 0 }
32 #define DECLARE_RWLOCK_EXTERN(l)		\
33 extern struct rwlock_debug l
34 
35 #define MUST_BE_LOCKED(l)						\
36 do { if (atomic_read(&(l)->locked_by) != smp_processor_id())		\
37 	printk("ASSERT %s:%u %s unlocked\n", __FILE__, __LINE__, #l);	\
38 } while(0)
39 
40 #define MUST_BE_UNLOCKED(l)						\
41 do { if (atomic_read(&(l)->locked_by) == smp_processor_id())		\
42 	printk("ASSERT %s:%u %s locked\n", __FILE__, __LINE__, #l);	\
43 } while(0)
44 
45 /* Write locked OK as well. */
46 #define MUST_BE_READ_LOCKED(l)						    \
47 do { if (!((l)->read_locked_map & (1UL << smp_processor_id()))		    \
48 	 && !((l)->write_locked_map & (1UL << smp_processor_id())))	    \
49 	printk("ASSERT %s:%u %s not readlocked\n", __FILE__, __LINE__, #l); \
50 } while(0)
51 
52 #define MUST_BE_WRITE_LOCKED(l)						     \
53 do { if (!((l)->write_locked_map & (1UL << smp_processor_id())))	     \
54 	printk("ASSERT %s:%u %s not writelocked\n", __FILE__, __LINE__, #l); \
55 } while(0)
56 
57 #define MUST_BE_READ_WRITE_UNLOCKED(l)					  \
58 do { if ((l)->read_locked_map & (1UL << smp_processor_id()))		  \
59 	printk("ASSERT %s:%u %s readlocked\n", __FILE__, __LINE__, #l);	  \
60  else if ((l)->write_locked_map & (1UL << smp_processor_id()))		  \
61 	 printk("ASSERT %s:%u %s writelocked\n", __FILE__, __LINE__, #l); \
62 } while(0)
63 
64 #define LOCK_BH(lk)						\
65 do {								\
66 	MUST_BE_UNLOCKED(lk);					\
67 	spin_lock_bh(&(lk)->l);					\
68 	atomic_set(&(lk)->locked_by, smp_processor_id());	\
69 } while(0)
70 
71 #define UNLOCK_BH(lk)				\
72 do {						\
73 	MUST_BE_LOCKED(lk);			\
74 	atomic_set(&(lk)->locked_by, -1);	\
75 	spin_unlock_bh(&(lk)->l);		\
76 } while(0)
77 
78 #define READ_LOCK(lk) 						\
79 do {								\
80 	MUST_BE_READ_WRITE_UNLOCKED(lk);			\
81 	read_lock_bh(&(lk)->l);					\
82 	set_bit(smp_processor_id(), &(lk)->read_locked_map);	\
83 } while(0)
84 
85 #define WRITE_LOCK(lk)							  \
86 do {									  \
87 	MUST_BE_READ_WRITE_UNLOCKED(lk);				  \
88 	write_lock_bh(&(lk)->l);					  \
89 	set_bit(smp_processor_id(), &(lk)->write_locked_map);		  \
90 } while(0)
91 
92 #define READ_UNLOCK(lk)							\
93 do {									\
94 	if (!((lk)->read_locked_map & (1UL << smp_processor_id())))	\
95 		printk("ASSERT: %s:%u %s not readlocked\n", 		\
96 		       __FILE__, __LINE__, #lk);			\
97 	clear_bit(smp_processor_id(), &(lk)->read_locked_map);		\
98 	read_unlock_bh(&(lk)->l);					\
99 } while(0)
100 
101 #define WRITE_UNLOCK(lk)					\
102 do {								\
103 	MUST_BE_WRITE_LOCKED(lk);				\
104 	clear_bit(smp_processor_id(), &(lk)->write_locked_map);	\
105 	write_unlock_bh(&(lk)->l);				\
106 } while(0)
107 
108 #else
109 #define DECLARE_LOCK(l) spinlock_t l = SPIN_LOCK_UNLOCKED
110 #define DECLARE_LOCK_EXTERN(l) extern spinlock_t l
111 #define DECLARE_RWLOCK(l) rwlock_t l = RW_LOCK_UNLOCKED
112 #define DECLARE_RWLOCK_EXTERN(l) extern rwlock_t l
113 
114 #define MUST_BE_LOCKED(l)
115 #define MUST_BE_UNLOCKED(l)
116 #define MUST_BE_READ_LOCKED(l)
117 #define MUST_BE_WRITE_LOCKED(l)
118 #define MUST_BE_READ_WRITE_UNLOCKED(l)
119 
120 #define LOCK_BH(l) spin_lock_bh(l)
121 #define UNLOCK_BH(l) spin_unlock_bh(l)
122 
123 #define READ_LOCK(l) read_lock_bh(l)
124 #define WRITE_LOCK(l) write_lock_bh(l)
125 #define READ_UNLOCK(l) read_unlock_bh(l)
126 #define WRITE_UNLOCK(l) write_unlock_bh(l)
127 #endif /*CONFIG_NETFILTER_DEBUG*/
128 
129 #endif /* _LOCKHELP_H */
130