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