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 13struct spinlock_debug 14{ 15 spinlock_t l; 16 atomic_t locked_by; 17}; 18 19struct rwlock_debug 20{ 21 rwlock_t l; 22 long read_locked_map; 23 long write_locked_map; 24}; 25 26#define DECLARE_LOCK(l) \ 27struct spinlock_debug l = { SPIN_LOCK_UNLOCKED, ATOMIC_INIT(-1) } 28#define DECLARE_LOCK_EXTERN(l) \ 29extern struct spinlock_debug l 30#define DECLARE_RWLOCK(l) \ 31struct rwlock_debug l = { RW_LOCK_UNLOCKED, 0, 0 } 32#define DECLARE_RWLOCK_EXTERN(l) \ 33extern struct rwlock_debug l 34 35#define MUST_BE_LOCKED(l) \ 36do { 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) \ 41do { 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) \ 47do { if (!((l)->read_locked_map & (1 << smp_processor_id())) \ 48 && !((l)->write_locked_map & (1 << 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) \ 53do { if (!((l)->write_locked_map & (1 << 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) \ 58do { if ((l)->read_locked_map & (1 << smp_processor_id())) \ 59 printk("ASSERT %s:%u %s readlocked\n", __FILE__, __LINE__, #l); \ 60 else if ((l)->write_locked_map & (1 << smp_processor_id())) \ 61 printk("ASSERT %s:%u %s writelocked\n", __FILE__, __LINE__, #l); \ 62} while(0) 63 64#define LOCK_BH(lk) \ 65do { \ 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) \ 72do { \ 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) \ 79do { \ 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) \ 86do { \ 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) \ 93do { \ 94 if (!((lk)->read_locked_map & (1 << 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) \ 102do { \ 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