2
2
#ifndef _ASM_GENERIC_BITOPS_LOCK_H_
3
3
#define _ASM_GENERIC_BITOPS_LOCK_H_
4
4
5
+ #include <linux/atomic.h>
6
+ #include <linux/compiler.h>
7
+ #include <asm/barrier.h>
8
+
5
9
/**
6
10
* test_and_set_bit_lock - Set a bit and return its old value, for lock
7
11
* @nr: Bit to set
11
15
* the returned value is 0.
12
16
* It can be used to implement bit locks.
13
17
*/
14
- #define test_and_set_bit_lock (nr , addr ) test_and_set_bit(nr, addr)
18
+ static inline int test_and_set_bit_lock (unsigned int nr ,
19
+ volatile unsigned long * p )
20
+ {
21
+ long old ;
22
+ unsigned long mask = BIT_MASK (nr );
23
+
24
+ p += BIT_WORD (nr );
25
+ if (READ_ONCE (* p ) & mask )
26
+ return 1 ;
27
+
28
+ old = atomic_long_fetch_or_acquire (mask , (atomic_long_t * )p );
29
+ return !!(old & mask );
30
+ }
31
+
15
32
16
33
/**
17
34
* clear_bit_unlock - Clear a bit in memory, for unlock
20
37
*
21
38
* This operation is atomic and provides release barrier semantics.
22
39
*/
23
- #define clear_bit_unlock (nr , addr ) \
24
- do { \
25
- smp_mb__before_atomic(); \
26
- clear_bit(nr, addr); \
27
- } while (0)
40
+ static inline void clear_bit_unlock (unsigned int nr , volatile unsigned long * p )
41
+ {
42
+ p += BIT_WORD ( nr );
43
+ atomic_long_fetch_andnot_release ( BIT_MASK ( nr ), ( atomic_long_t * ) p );
44
+ }
28
45
29
46
/**
30
47
* __clear_bit_unlock - Clear a bit in memory, for unlock
@@ -37,11 +54,38 @@ do { \
37
54
*
38
55
* See for example x86's implementation.
39
56
*/
40
- #define __clear_bit_unlock (nr , addr ) \
41
- do { \
42
- smp_mb__before_atomic(); \
43
- clear_bit(nr, addr); \
44
- } while (0)
57
+ static inline void __clear_bit_unlock (unsigned int nr ,
58
+ volatile unsigned long * p )
59
+ {
60
+ unsigned long old ;
45
61
46
- #endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */
62
+ p += BIT_WORD (nr );
63
+ old = READ_ONCE (* p );
64
+ old &= ~BIT_MASK (nr );
65
+ atomic_long_set_release ((atomic_long_t * )p , old );
66
+ }
67
+
68
+ /**
69
+ * clear_bit_unlock_is_negative_byte - Clear a bit in memory and test if bottom
70
+ * byte is negative, for unlock.
71
+ * @nr: the bit to clear
72
+ * @addr: the address to start counting from
73
+ *
74
+ * This is a bit of a one-trick-pony for the filemap code, which clears
75
+ * PG_locked and tests PG_waiters,
76
+ */
77
+ #ifndef clear_bit_unlock_is_negative_byte
78
+ static inline bool clear_bit_unlock_is_negative_byte (unsigned int nr ,
79
+ volatile unsigned long * p )
80
+ {
81
+ long old ;
82
+ unsigned long mask = BIT_MASK (nr );
83
+
84
+ p += BIT_WORD (nr );
85
+ old = atomic_long_fetch_andnot_release (mask , (atomic_long_t * )p );
86
+ return !!(old & BIT (7 ));
87
+ }
88
+ #define clear_bit_unlock_is_negative_byte clear_bit_unlock_is_negative_byte
89
+ #endif
47
90
91
+ #endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */
0 commit comments