Merge branch 'for-2638/i2c/mv64xx' into for-linus/i2c-2638
[pandora-kernel.git] / include / linux / bit_spinlock.h
1 #ifndef __LINUX_BIT_SPINLOCK_H
2 #define __LINUX_BIT_SPINLOCK_H
3
4 #include <linux/kernel.h>
5 #include <linux/preempt.h>
6 #include <asm/atomic.h>
7
8 /*
9  *  bit-based spin_lock()
10  *
11  * Don't use this unless you really need to: spin_lock() and spin_unlock()
12  * are significantly faster.
13  */
14 static inline void bit_spin_lock(int bitnum, unsigned long *addr)
15 {
16         /*
17          * Assuming the lock is uncontended, this never enters
18          * the body of the outer loop. If it is contended, then
19          * within the inner loop a non-atomic test is used to
20          * busywait with less bus contention for a good time to
21          * attempt to acquire the lock bit.
22          */
23         preempt_disable();
24 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
25         while (unlikely(test_and_set_bit_lock(bitnum, addr))) {
26                 while (test_bit(bitnum, addr)) {
27                         preempt_enable();
28                         cpu_relax();
29                         preempt_disable();
30                 }
31         }
32 #endif
33         __acquire(bitlock);
34 }
35
36 /*
37  * Return true if it was acquired
38  */
39 static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
40 {
41         preempt_disable();
42 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
43         if (unlikely(test_and_set_bit_lock(bitnum, addr))) {
44                 preempt_enable();
45                 return 0;
46         }
47 #endif
48         __acquire(bitlock);
49         return 1;
50 }
51
52 /*
53  *  bit-based spin_unlock()
54  */
55 static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
56 {
57 #ifdef CONFIG_DEBUG_SPINLOCK
58         BUG_ON(!test_bit(bitnum, addr));
59 #endif
60 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
61         clear_bit_unlock(bitnum, addr);
62 #endif
63         preempt_enable();
64         __release(bitlock);
65 }
66
67 /*
68  *  bit-based spin_unlock()
69  *  non-atomic version, which can be used eg. if the bit lock itself is
70  *  protecting the rest of the flags in the word.
71  */
72 static inline void __bit_spin_unlock(int bitnum, unsigned long *addr)
73 {
74 #ifdef CONFIG_DEBUG_SPINLOCK
75         BUG_ON(!test_bit(bitnum, addr));
76 #endif
77 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
78         __clear_bit_unlock(bitnum, addr);
79 #endif
80         preempt_enable();
81         __release(bitlock);
82 }
83
84 /*
85  * Return true if the lock is held.
86  */
87 static inline int bit_spin_is_locked(int bitnum, unsigned long *addr)
88 {
89 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
90         return test_bit(bitnum, addr);
91 #elif defined CONFIG_PREEMPT
92         return preempt_count();
93 #else
94         return 1;
95 #endif
96 }
97
98 #endif /* __LINUX_BIT_SPINLOCK_H */
99