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