diff options
Diffstat (limited to 'arch/x86/include/asm/sync_bitops.h')
-rw-r--r-- | arch/x86/include/asm/sync_bitops.h | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/arch/x86/include/asm/sync_bitops.h b/arch/x86/include/asm/sync_bitops.h new file mode 100644 index 000000000000..b689bee71104 --- /dev/null +++ b/arch/x86/include/asm/sync_bitops.h | |||
@@ -0,0 +1,130 @@ | |||
1 | #ifndef ASM_X86__SYNC_BITOPS_H | ||
2 | #define ASM_X86__SYNC_BITOPS_H | ||
3 | |||
4 | /* | ||
5 | * Copyright 1992, Linus Torvalds. | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * These have to be done with inline assembly: that way the bit-setting | ||
10 | * is guaranteed to be atomic. All bit operations return 0 if the bit | ||
11 | * was cleared before the operation and != 0 if it was not. | ||
12 | * | ||
13 | * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). | ||
14 | */ | ||
15 | |||
16 | #define ADDR (*(volatile long *)addr) | ||
17 | |||
18 | /** | ||
19 | * sync_set_bit - Atomically set a bit in memory | ||
20 | * @nr: the bit to set | ||
21 | * @addr: the address to start counting from | ||
22 | * | ||
23 | * This function is atomic and may not be reordered. See __set_bit() | ||
24 | * if you do not require the atomic guarantees. | ||
25 | * | ||
26 | * Note that @nr may be almost arbitrarily large; this function is not | ||
27 | * restricted to acting on a single-word quantity. | ||
28 | */ | ||
29 | static inline void sync_set_bit(int nr, volatile unsigned long *addr) | ||
30 | { | ||
31 | asm volatile("lock; btsl %1,%0" | ||
32 | : "+m" (ADDR) | ||
33 | : "Ir" (nr) | ||
34 | : "memory"); | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * sync_clear_bit - Clears a bit in memory | ||
39 | * @nr: Bit to clear | ||
40 | * @addr: Address to start counting from | ||
41 | * | ||
42 | * sync_clear_bit() is atomic and may not be reordered. However, it does | ||
43 | * not contain a memory barrier, so if it is used for locking purposes, | ||
44 | * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() | ||
45 | * in order to ensure changes are visible on other processors. | ||
46 | */ | ||
47 | static inline void sync_clear_bit(int nr, volatile unsigned long *addr) | ||
48 | { | ||
49 | asm volatile("lock; btrl %1,%0" | ||
50 | : "+m" (ADDR) | ||
51 | : "Ir" (nr) | ||
52 | : "memory"); | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * sync_change_bit - Toggle a bit in memory | ||
57 | * @nr: Bit to change | ||
58 | * @addr: Address to start counting from | ||
59 | * | ||
60 | * sync_change_bit() is atomic and may not be reordered. | ||
61 | * Note that @nr may be almost arbitrarily large; this function is not | ||
62 | * restricted to acting on a single-word quantity. | ||
63 | */ | ||
64 | static inline void sync_change_bit(int nr, volatile unsigned long *addr) | ||
65 | { | ||
66 | asm volatile("lock; btcl %1,%0" | ||
67 | : "+m" (ADDR) | ||
68 | : "Ir" (nr) | ||
69 | : "memory"); | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * sync_test_and_set_bit - Set a bit and return its old value | ||
74 | * @nr: Bit to set | ||
75 | * @addr: Address to count from | ||
76 | * | ||
77 | * This operation is atomic and cannot be reordered. | ||
78 | * It also implies a memory barrier. | ||
79 | */ | ||
80 | static inline int sync_test_and_set_bit(int nr, volatile unsigned long *addr) | ||
81 | { | ||
82 | int oldbit; | ||
83 | |||
84 | asm volatile("lock; btsl %2,%1\n\tsbbl %0,%0" | ||
85 | : "=r" (oldbit), "+m" (ADDR) | ||
86 | : "Ir" (nr) : "memory"); | ||
87 | return oldbit; | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * sync_test_and_clear_bit - Clear a bit and return its old value | ||
92 | * @nr: Bit to clear | ||
93 | * @addr: Address to count from | ||
94 | * | ||
95 | * This operation is atomic and cannot be reordered. | ||
96 | * It also implies a memory barrier. | ||
97 | */ | ||
98 | static inline int sync_test_and_clear_bit(int nr, volatile unsigned long *addr) | ||
99 | { | ||
100 | int oldbit; | ||
101 | |||
102 | asm volatile("lock; btrl %2,%1\n\tsbbl %0,%0" | ||
103 | : "=r" (oldbit), "+m" (ADDR) | ||
104 | : "Ir" (nr) : "memory"); | ||
105 | return oldbit; | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * sync_test_and_change_bit - Change a bit and return its old value | ||
110 | * @nr: Bit to change | ||
111 | * @addr: Address to count from | ||
112 | * | ||
113 | * This operation is atomic and cannot be reordered. | ||
114 | * It also implies a memory barrier. | ||
115 | */ | ||
116 | static inline int sync_test_and_change_bit(int nr, volatile unsigned long *addr) | ||
117 | { | ||
118 | int oldbit; | ||
119 | |||
120 | asm volatile("lock; btcl %2,%1\n\tsbbl %0,%0" | ||
121 | : "=r" (oldbit), "+m" (ADDR) | ||
122 | : "Ir" (nr) : "memory"); | ||
123 | return oldbit; | ||
124 | } | ||
125 | |||
126 | #define sync_test_bit(nr, addr) test_bit(nr, addr) | ||
127 | |||
128 | #undef ADDR | ||
129 | |||
130 | #endif /* ASM_X86__SYNC_BITOPS_H */ | ||