blob: f28a24b51dc7c17a7fc5f370fdf8340aa370becb [file] [log] [blame]
H. Peter Anvin1965aae2008-10-22 22:26:29 -07001#ifndef _ASM_X86_SYNC_BITOPS_H
2#define _ASM_X86_SYNC_BITOPS_H
Chris Wright027a8c72006-09-25 23:32:23 -07003
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
Joe Perches26b7fcc2008-03-23 01:03:38 -070016#define ADDR (*(volatile long *)addr)
Chris Wright027a8c72006-09-25 23:32:23 -070017
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 *
Chris Wright027a8c72006-09-25 23:32:23 -070026 * Note that @nr may be almost arbitrarily large; this function is not
27 * restricted to acting on a single-word quantity.
28 */
H. Peter Anvin9b710502013-07-16 15:20:14 -070029static inline void sync_set_bit(long nr, volatile unsigned long *addr)
Chris Wright027a8c72006-09-25 23:32:23 -070030{
H. Peter Anvin9b710502013-07-16 15:20:14 -070031 asm volatile("lock; bts %1,%0"
Joe Perches26b7fcc2008-03-23 01:03:38 -070032 : "+m" (ADDR)
33 : "Ir" (nr)
34 : "memory");
Chris Wright027a8c72006-09-25 23:32:23 -070035}
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,
Peter Zijlstrad00a5692014-03-13 19:00:35 +010044 * you should call smp_mb__before_atomic() and/or smp_mb__after_atomic()
Chris Wright027a8c72006-09-25 23:32:23 -070045 * in order to ensure changes are visible on other processors.
46 */
H. Peter Anvin9b710502013-07-16 15:20:14 -070047static inline void sync_clear_bit(long nr, volatile unsigned long *addr)
Chris Wright027a8c72006-09-25 23:32:23 -070048{
H. Peter Anvin9b710502013-07-16 15:20:14 -070049 asm volatile("lock; btr %1,%0"
Joe Perches26b7fcc2008-03-23 01:03:38 -070050 : "+m" (ADDR)
51 : "Ir" (nr)
52 : "memory");
Chris Wright027a8c72006-09-25 23:32:23 -070053}
54
55/**
56 * sync_change_bit - Toggle a bit in memory
57 * @nr: Bit to change
58 * @addr: Address to start counting from
59 *
Matti Linnanvuori7800c0c2008-03-16 02:47:35 -070060 * sync_change_bit() is atomic and may not be reordered.
Chris Wright027a8c72006-09-25 23:32:23 -070061 * Note that @nr may be almost arbitrarily large; this function is not
62 * restricted to acting on a single-word quantity.
63 */
H. Peter Anvin9b710502013-07-16 15:20:14 -070064static inline void sync_change_bit(long nr, volatile unsigned long *addr)
Chris Wright027a8c72006-09-25 23:32:23 -070065{
H. Peter Anvin9b710502013-07-16 15:20:14 -070066 asm volatile("lock; btc %1,%0"
Joe Perches26b7fcc2008-03-23 01:03:38 -070067 : "+m" (ADDR)
68 : "Ir" (nr)
69 : "memory");
Chris Wright027a8c72006-09-25 23:32:23 -070070}
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.
Chris Wright027a8c72006-09-25 23:32:23 -070078 * It also implies a memory barrier.
79 */
H. Peter Anvin9b710502013-07-16 15:20:14 -070080static inline int sync_test_and_set_bit(long nr, volatile unsigned long *addr)
Chris Wright027a8c72006-09-25 23:32:23 -070081{
82 int oldbit;
83
H. Peter Anvin9b710502013-07-16 15:20:14 -070084 asm volatile("lock; bts %2,%1\n\tsbbl %0,%0"
Joe Perches26b7fcc2008-03-23 01:03:38 -070085 : "=r" (oldbit), "+m" (ADDR)
86 : "Ir" (nr) : "memory");
Chris Wright027a8c72006-09-25 23:32:23 -070087 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.
Chris Wright027a8c72006-09-25 23:32:23 -070096 * It also implies a memory barrier.
97 */
H. Peter Anvin9b710502013-07-16 15:20:14 -070098static inline int sync_test_and_clear_bit(long nr, volatile unsigned long *addr)
Chris Wright027a8c72006-09-25 23:32:23 -070099{
100 int oldbit;
101
H. Peter Anvin9b710502013-07-16 15:20:14 -0700102 asm volatile("lock; btr %2,%1\n\tsbbl %0,%0"
Joe Perches26b7fcc2008-03-23 01:03:38 -0700103 : "=r" (oldbit), "+m" (ADDR)
104 : "Ir" (nr) : "memory");
Chris Wright027a8c72006-09-25 23:32:23 -0700105 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 */
H. Peter Anvin9b710502013-07-16 15:20:14 -0700116static inline int sync_test_and_change_bit(long nr, volatile unsigned long *addr)
Chris Wright027a8c72006-09-25 23:32:23 -0700117{
118 int oldbit;
119
H. Peter Anvin9b710502013-07-16 15:20:14 -0700120 asm volatile("lock; btc %2,%1\n\tsbbl %0,%0"
Joe Perches26b7fcc2008-03-23 01:03:38 -0700121 : "=r" (oldbit), "+m" (ADDR)
122 : "Ir" (nr) : "memory");
Chris Wright027a8c72006-09-25 23:32:23 -0700123 return oldbit;
124}
125
Jeremy Fitzhardingeaa040b22008-03-22 13:27:38 -0700126#define sync_test_bit(nr, addr) test_bit(nr, addr)
Chris Wright027a8c72006-09-25 23:32:23 -0700127
128#undef ADDR
129
H. Peter Anvin1965aae2008-10-22 22:26:29 -0700130#endif /* _ASM_X86_SYNC_BITOPS_H */