Many subsystems will not use refcount_t unless there is a way to build the kernel so that there is no regression in speed compared to atomic_t. This adds CONFIG_REFCOUNT_FULL to enable the full refcount_t implementation which has the validation but is slightly slower. When not enabled, refcount_t uses the basic unchecked atomic_t routines, which results in no code changes compared to just using atomic_t directly. Signed-off-by: Kees Cook <keescook@chromium.org> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Christoph Hellwig <hch@infradead.org> Cc: David S. Miller <davem@davemloft.net> Cc: David Windsor <dwindsor@gmail.com> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Elena Reshetova <elena.reshetova@intel.com> Cc: Eric Biggers <ebiggers3@gmail.com> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Hans Liljestrand <ishkamiel@gmail.com> Cc: James Bottomley <James.Bottomley@hansenpartnership.com> Cc: Jann Horn <jannh@google.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Manfred Spraul <manfred@colorfullife.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rik van Riel <riel@redhat.com> Cc: Serge E. Hallyn <serge@hallyn.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: arozansk@redhat.com Cc: axboe@kernel.dk Cc: linux-arch <linux-arch@vger.kernel.org> Link: http://lkml.kernel.org/r/20170621200026.GA115679@beast Signed-off-by: Ingo Molnar <mingo@kernel.org> UPSTREAM: locking/refcounts: Add missing kernel.h header to have UINT_MAX defined Fix header dependency. Suggested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/1487855374-21993-1-git-send-email-elena.reshetova@intel.com Signed-off-by: Ingo Molnar <mingo@kernel.org> UPSTREAM: locking/refcount: Add refcount_t API kernel-doc comments Signed-off-by: David Windsor <dwindsor@gmail.com> Acked-by: Peter Zijlstra <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: elena.reshetova@intel.com Cc: kernel-hardening@lists.openwall.com Link: http://lkml.kernel.org/r/1489160052-20293-1-git-send-email-dwindsor@gmail.com Signed-off-by: Ingo Molnar <mingo@kernel.org> UPSTREAM: locking/refcounts: Change WARN() to WARN_ONCE() Linus noticed that the new refcount.h APIs used WARN(), which would turn into a dmesg DoS if it triggers frequently on some buggy driver. So make sure we only warn once. These warnings are never supposed to happen, so it's typically not a problem to lose subsequent warnings. Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Elena Reshetova <elena.reshetova@intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/CA+55aFzbYUTZ=oqZ2YgDjY0C2_n6ODhTfqj6V+m5xWmDxsuB0w@mail.gmail.com Signed-off-by: Ingo Molnar <mingo@kernel.org> UPSTREAM: locking/refcounts: Use atomic_try_cmpxchg() Generates better code (GCC-6.2.1): text filename 1576 defconfig-build/lib/refcount.o.pre 1488 defconfig-build/lib/refcount.o.post Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-kernel@vger.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org> UPSTREAM: refcount: change EXPORT_SYMBOL markings Now that kref is using the refcount apis, the _GPL markings are getting exported to places that it previously wasn't. Now kref.h is GPLv2 licensed, so any non-GPL code using it better be talking to some lawyers, but changing api markings isn't considered "nice", so let's fix this up. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> UPSTREAM: locking/refcounts: Out-of-line everything Linus asked to please make this real C code. And since size then isn't an issue what so ever anymore, remove the debug knob and make all WARN()s unconditional. Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: dwindsor@gmail.com Cc: elena.reshetova@intel.com Cc: gregkh@linuxfoundation.org Cc: ishkamiel@gmail.com Cc: keescook@chromium.org Signed-off-by: Ingo Molnar <mingo@kernel.org> UPSTREAM: locking/refcount: Remove the half-implemented refcount_sub() API CONFIG_REFCOUNT_FULL=y (correctly) does not provide a refcount_sub(), which should not be part of proper refcount design patterns. Remove the erroneous extern and the later !CONFIG_REFCOUNT_FULL accidental implementation. Signed-off-by: Kees Cook <keescook@chromium.org> Cc: Elena Reshetova <elena.reshetova@intel.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Fixes: 29dee3c03abc ("locking/refcounts: Out-of-line everything") Link: http://lkml.kernel.org/r/20170701180129.GA17405@beast Signed-off-by: Ingo Molnar <mingo@kernel.org> UPSTREAM: locking/refcounts, x86/asm: Implement fast refcount overflow protection This implements refcount_t overflow protection on x86 without a noticeable performance impact, though without the fuller checking of REFCOUNT_FULL. This is done by duplicating the existing atomic_t refcount implementation but with normally a single instruction added to detect if the refcount has gone negative (e.g. wrapped past INT_MAX or below zero). When detected, the handler saturates the refcount_t to INT_MIN / 2. With this overflow protection, the erroneous reference release that would follow a wrap back to zero is blocked from happening, avoiding the class of refcount-overflow use-after-free vulnerabilities entirely. Only the overflow case of refcounting can be perfectly protected, since it can be detected and stopped before the reference is freed and left to be abused by an attacker. There isn't a way to block early decrements, and while REFCOUNT_FULL stops increment-from-zero cases (which would be the state _after_ an early decrement and stops potential double-free conditions), this fast implementation does not, since it would require the more expensive cmpxchg loops. Since the overflow case is much more common (e.g. missing a "put" during an error path), this protection provides real-world protection. For example, the two public refcount overflow use-after-free exploits published in 2016 would have been rendered unexploitable: http://perception-point.io/2016/01/14/analysis-and-exploitation-of-a-linux-kernel-vulnerability-cve-2016-0728/ http://cyseclabs.com/page?n=02012016 This implementation does, however, notice an unchecked decrement to zero (i.e. caller used refcount_dec() instead of refcount_dec_and_test() and it resulted in a zero). Decrements under zero are noticed (since they will have resulted in a negative value), though this only indicates that a use-after-free may have already happened. Such notifications are likely avoidable by an attacker that has already exploited a use-after-free vulnerability, but it's better to have them reported than allow such conditions to remain universally silent. On first overflow detection, the refcount value is reset to INT_MIN / 2 (which serves as a saturation value) and a report and stack trace are produced. When operations detect only negative value results (such as changing an already saturated value), saturation still happens but no notification is performed (since the value was already saturated). On the matter of races, since the entire range beyond INT_MAX but before 0 is negative, every operation at INT_MIN / 2 will trap, leaving no overflow-only race condition. As for performance, this implementation adds a single "js" instruction to the regular execution flow of a copy of the standard atomic_t refcount operations. (The non-"and_test" refcount_dec() function, which is uncommon in regular refcount design patterns, has an additional "jz" instruction to detect reaching exactly zero.) Since this is a forward jump, it is by default the non-predicted path, which will be reinforced by dynamic branch prediction. The result is this protection having virtually no measurable change in performance over standard atomic_t operations. The error path, located in .text.unlikely, saves the refcount location and then uses UD0 to fire a refcount exception handler, which resets the refcount, handles reporting, and returns to regular execution. This keeps the changes to .text size minimal, avoiding return jumps and open-coded calls to the error reporting routine. Example assembly comparison: refcount_inc() before: .text: ffffffff81546149: f0 ff 45 f4 lock incl -0xc(%rbp) refcount_inc() after: .text: ffffffff81546149: f0 ff 45 f4 lock incl -0xc(%rbp) ffffffff8154614d: 0f 88 80 d5 17 00 js ffffffff816c36d3 ... .text.unlikely: ffffffff816c36d3: 48 8d 4d f4 lea -0xc(%rbp),%rcx ffffffff816c36d7: 0f ff (bad) These are the cycle counts comparing a loop of refcount_inc() from 1 to INT_MAX and back down to 0 (via refcount_dec_and_test()), between unprotected refcount_t (atomic_t), fully protected REFCOUNT_FULL (refcount_t-full), and this overflow-protected refcount (refcount_t-fast): 2147483646 refcount_inc()s and 2147483647 refcount_dec_and_test()s: cycles protections atomic_t 82249267387 none refcount_t-fast 82211446892 overflow, untested dec-to-zero refcount_t-full 144814735193 overflow, untested dec-to-zero, inc-from-zero This code is a modified version of the x86 PAX_REFCOUNT atomic_t overflow defense from the last public patch of PaX/grsecurity, based on my understanding of the code. Changes or omissions from the original code are mine and don't reflect the original grsecurity/PaX code. Thanks to PaX Team for various suggestions for improvement for repurposing this code to be a refcount-only protection. Signed-off-by: Kees Cook <keescook@chromium.org> Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Christoph Hellwig <hch@infradead.org> Cc: David S. Miller <davem@davemloft.net> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Elena Reshetova <elena.reshetova@intel.com> Cc: Eric Biggers <ebiggers3@gmail.com> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Greg KH <gregkh@linuxfoundation.org> Cc: Hans Liljestrand <ishkamiel@gmail.com> Cc: James Bottomley <James.Bottomley@hansenpartnership.com> Cc: Jann Horn <jannh@google.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Manfred Spraul <manfred@colorfullife.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rik van Riel <riel@redhat.com> Cc: Serge E. Hallyn <serge@hallyn.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: arozansk@redhat.com Cc: axboe@kernel.dk Cc: kernel-hardening@lists.openwall.com Cc: linux-arch <linux-arch@vger.kernel.org> Link: http://lkml.kernel.org/r/20170815161924.GA133115@beast Signed-off-by: Ingo Molnar <mingo@kernel.org> UPSTREAM: locking/refcounts: Implement refcount_dec_and_lock_irqsave() There are in-tree users of refcount_dec_and_lock() which must acquire the spin lock with interrupts disabled. To workaround the lack of an irqsave variant of refcount_dec_and_lock() they use local_irq_save() at the call site. This causes extra code and creates in some places unneeded long interrupt disabled times. These places need also extra treatment for PREEMPT_RT due to the disconnect of the irq disabling and the lock function. Implement the missing irqsave variant of the function. Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r20180612161621.22645-4-bigeasy@linutronix.de [bigeasy: s@atomic_dec_and_lock@refcount_dec_and_lock@g] UPSTREAM: locking/refcounts: Include fewer headers in <linux/refcount.h> Debloat <linux/refcount.h>'s dependencies: - <linux/kernel.h> is not needed, but <linux/compiler.h> is. - <linux/mutex.h> is not needed, only a forward declaration of "struct mutex". - <linux/spinlock.h> is not needed, <linux/spinlock_types.h> is enough. Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Will Deacon <will.deacon@arm.com> Link: https://lkml.kernel.org/lkml/20180331220036.GA7676@avx2 Signed-off-by: Ingo Molnar <mingo@kernel.org> UPSTREAM: locking/refcount: Always allow checked forms In many cases, it would be useful to be able to use the full sanity-checked refcount helpers regardless of CONFIG_REFCOUNT_FULL, as this would help to avoid duplicate warnings where callers try to sanity-check refcount manipulation. This patch refactors things such that the full refcount helpers were always built, as refcount_${op}_checked(), such that they can be used regardless of CONFIG_REFCOUNT_FULL. This will allow code which *always* wants a checked refcount to opt-in, avoiding the need to duplicate the logic for warnings. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Reviewed-by: David Sterba <dsterba@suse.com> Acked-by: Kees Cook <keescook@chromium.org> Acked-by: Will Deacon <will.deacon@arm.com> Cc: Boqun Feng <boqun.feng@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20180711093607.1644-1-mark.rutland@arm.com Signed-off-by: Ingo Molnar <mingo@kernel.org> UPSTREAM: locking/atomic: Introduce atomic_try_cmpxchg() Add a new cmpxchg interface: bool try_cmpxchg(u{8,16,32,64} *ptr, u{8,16,32,64} *val, u{8,16,32,64} new); Where the boolean returns the result of the compare; and thus if the exchange happened; and in case of failure, the new value of *ptr is returned in *val. This allows simplification/improvement of loops like: for (;;) { new = val $op $imm; old = cmpxchg(ptr, val, new); if (old == val) break; val = old; } into: do { } while (!try_cmpxchg(ptr, &val, val $op $imm)); while also generating better code (GCC6 and onwards). Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-kernel@vger.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org> UPSTREAM: locking/atomic: Fix atomic_try_cmpxchg() semantics Dmitry noted that the new atomic_try_cmpxchg() primitive is broken when the old pointer doesn't point to the local stack. He writes: "Consider a classical lock-free stack push: node->next = atomic_read(&head); do { } while (!atomic_try_cmpxchg(&head, &node->next, node)); This code is broken with the current implementation, the problem is with unconditional update of *__po. In case of success it writes the same value back into *__po, but in case of cmpxchg success we might have lose ownership of some memory locations and potentially over what __po has pointed to. The same holds for the re-read of *__po. " He also points out that this makes it surprisingly different from the similar C/C++ atomic operation. After investigating the code-gen differences caused by this patch; and a number of alternatives (Linus dislikes this interface lots), we arrived at these results (size x86_64-defconfig/vmlinux): GCC-6.3.0: 10735757 cmpxchg 10726413 try_cmpxchg 10730509 try_cmpxchg + patch 10730445 try_cmpxchg-linus GCC-7 (20170327): 10709514 cmpxchg 10704266 try_cmpxchg 10704266 try_cmpxchg + patch 10704394 try_cmpxchg-linus From this we see that the patch has the advantage of better code-gen on GCC-7 and keeps the interface roughly consistent with the C language variant. Reported-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-kernel@vger.kernel.org Fixes: a9ebf306f52c ("locking/atomic: Introduce atomic_try_cmpxchg()") Signed-off-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Sorayukii <sorayukii69@gmail.com>
1078 lines
30 KiB
C
1078 lines
30 KiB
C
/* Atomic operations usable in machine independent code */
|
|
#ifndef _LINUX_ATOMIC_H
|
|
#define _LINUX_ATOMIC_H
|
|
#include <asm/atomic.h>
|
|
#include <asm/barrier.h>
|
|
|
|
/*
|
|
* Relaxed variants of xchg, cmpxchg and some atomic operations.
|
|
*
|
|
* We support four variants:
|
|
*
|
|
* - Fully ordered: The default implementation, no suffix required.
|
|
* - Acquire: Provides ACQUIRE semantics, _acquire suffix.
|
|
* - Release: Provides RELEASE semantics, _release suffix.
|
|
* - Relaxed: No ordering guarantees, _relaxed suffix.
|
|
*
|
|
* For compound atomics performing both a load and a store, ACQUIRE
|
|
* semantics apply only to the load and RELEASE semantics only to the
|
|
* store portion of the operation. Note that a failed cmpxchg_acquire
|
|
* does -not- imply any memory ordering constraints.
|
|
*
|
|
* See Documentation/memory-barriers.txt for ACQUIRE/RELEASE definitions.
|
|
*/
|
|
|
|
#ifndef atomic_read_acquire
|
|
#define atomic_read_acquire(v) smp_load_acquire(&(v)->counter)
|
|
#endif
|
|
|
|
#ifndef atomic_set_release
|
|
#define atomic_set_release(v, i) smp_store_release(&(v)->counter, (i))
|
|
#endif
|
|
|
|
/*
|
|
* The idea here is to build acquire/release variants by adding explicit
|
|
* barriers on top of the relaxed variant. In the case where the relaxed
|
|
* variant is already fully ordered, no additional barriers are needed.
|
|
*
|
|
* Besides, if an arch has a special barrier for acquire/release, it could
|
|
* implement its own __atomic_op_* and use the same framework for building
|
|
* variants
|
|
*/
|
|
#ifndef __atomic_op_acquire
|
|
#define __atomic_op_acquire(op, args...) \
|
|
({ \
|
|
typeof(op##_relaxed(args)) __ret = op##_relaxed(args); \
|
|
smp_mb__after_atomic(); \
|
|
__ret; \
|
|
})
|
|
#endif
|
|
|
|
#ifndef __atomic_op_release
|
|
#define __atomic_op_release(op, args...) \
|
|
({ \
|
|
smp_mb__before_atomic(); \
|
|
op##_relaxed(args); \
|
|
})
|
|
#endif
|
|
|
|
#ifndef __atomic_op_fence
|
|
#define __atomic_op_fence(op, args...) \
|
|
({ \
|
|
typeof(op##_relaxed(args)) __ret; \
|
|
smp_mb__before_atomic(); \
|
|
__ret = op##_relaxed(args); \
|
|
smp_mb__after_atomic(); \
|
|
__ret; \
|
|
})
|
|
#endif
|
|
|
|
/* atomic_add_return_relaxed */
|
|
#ifndef atomic_add_return_relaxed
|
|
#define atomic_add_return_relaxed atomic_add_return
|
|
#define atomic_add_return_acquire atomic_add_return
|
|
#define atomic_add_return_release atomic_add_return
|
|
|
|
#else /* atomic_add_return_relaxed */
|
|
|
|
#ifndef atomic_add_return_acquire
|
|
#define atomic_add_return_acquire(...) \
|
|
__atomic_op_acquire(atomic_add_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_add_return_release
|
|
#define atomic_add_return_release(...) \
|
|
__atomic_op_release(atomic_add_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_add_return
|
|
#define atomic_add_return(...) \
|
|
__atomic_op_fence(atomic_add_return, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_add_return_relaxed */
|
|
|
|
/* atomic_inc_return_relaxed */
|
|
#ifndef atomic_inc_return_relaxed
|
|
#define atomic_inc_return_relaxed atomic_inc_return
|
|
#define atomic_inc_return_acquire atomic_inc_return
|
|
#define atomic_inc_return_release atomic_inc_return
|
|
|
|
#else /* atomic_inc_return_relaxed */
|
|
|
|
#ifndef atomic_inc_return_acquire
|
|
#define atomic_inc_return_acquire(...) \
|
|
__atomic_op_acquire(atomic_inc_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_inc_return_release
|
|
#define atomic_inc_return_release(...) \
|
|
__atomic_op_release(atomic_inc_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_inc_return
|
|
#define atomic_inc_return(...) \
|
|
__atomic_op_fence(atomic_inc_return, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_inc_return_relaxed */
|
|
|
|
/* atomic_sub_return_relaxed */
|
|
#ifndef atomic_sub_return_relaxed
|
|
#define atomic_sub_return_relaxed atomic_sub_return
|
|
#define atomic_sub_return_acquire atomic_sub_return
|
|
#define atomic_sub_return_release atomic_sub_return
|
|
|
|
#else /* atomic_sub_return_relaxed */
|
|
|
|
#ifndef atomic_sub_return_acquire
|
|
#define atomic_sub_return_acquire(...) \
|
|
__atomic_op_acquire(atomic_sub_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_sub_return_release
|
|
#define atomic_sub_return_release(...) \
|
|
__atomic_op_release(atomic_sub_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_sub_return
|
|
#define atomic_sub_return(...) \
|
|
__atomic_op_fence(atomic_sub_return, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_sub_return_relaxed */
|
|
|
|
/* atomic_dec_return_relaxed */
|
|
#ifndef atomic_dec_return_relaxed
|
|
#define atomic_dec_return_relaxed atomic_dec_return
|
|
#define atomic_dec_return_acquire atomic_dec_return
|
|
#define atomic_dec_return_release atomic_dec_return
|
|
|
|
#else /* atomic_dec_return_relaxed */
|
|
|
|
#ifndef atomic_dec_return_acquire
|
|
#define atomic_dec_return_acquire(...) \
|
|
__atomic_op_acquire(atomic_dec_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_dec_return_release
|
|
#define atomic_dec_return_release(...) \
|
|
__atomic_op_release(atomic_dec_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_dec_return
|
|
#define atomic_dec_return(...) \
|
|
__atomic_op_fence(atomic_dec_return, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_dec_return_relaxed */
|
|
|
|
|
|
/* atomic_fetch_add_relaxed */
|
|
#ifndef atomic_fetch_add_relaxed
|
|
#define atomic_fetch_add_relaxed atomic_fetch_add
|
|
#define atomic_fetch_add_acquire atomic_fetch_add
|
|
#define atomic_fetch_add_release atomic_fetch_add
|
|
|
|
#else /* atomic_fetch_add_relaxed */
|
|
|
|
#ifndef atomic_fetch_add_acquire
|
|
#define atomic_fetch_add_acquire(...) \
|
|
__atomic_op_acquire(atomic_fetch_add, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_add_release
|
|
#define atomic_fetch_add_release(...) \
|
|
__atomic_op_release(atomic_fetch_add, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_add
|
|
#define atomic_fetch_add(...) \
|
|
__atomic_op_fence(atomic_fetch_add, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_fetch_add_relaxed */
|
|
|
|
/* atomic_fetch_inc_relaxed */
|
|
#ifndef atomic_fetch_inc_relaxed
|
|
|
|
#ifndef atomic_fetch_inc
|
|
#define atomic_fetch_inc(v) atomic_fetch_add(1, (v))
|
|
#define atomic_fetch_inc_relaxed(v) atomic_fetch_add_relaxed(1, (v))
|
|
#define atomic_fetch_inc_acquire(v) atomic_fetch_add_acquire(1, (v))
|
|
#define atomic_fetch_inc_release(v) atomic_fetch_add_release(1, (v))
|
|
#else /* atomic_fetch_inc */
|
|
#define atomic_fetch_inc_relaxed atomic_fetch_inc
|
|
#define atomic_fetch_inc_acquire atomic_fetch_inc
|
|
#define atomic_fetch_inc_release atomic_fetch_inc
|
|
#endif /* atomic_fetch_inc */
|
|
|
|
#else /* atomic_fetch_inc_relaxed */
|
|
|
|
#ifndef atomic_fetch_inc_acquire
|
|
#define atomic_fetch_inc_acquire(...) \
|
|
__atomic_op_acquire(atomic_fetch_inc, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_inc_release
|
|
#define atomic_fetch_inc_release(...) \
|
|
__atomic_op_release(atomic_fetch_inc, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_inc
|
|
#define atomic_fetch_inc(...) \
|
|
__atomic_op_fence(atomic_fetch_inc, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_fetch_inc_relaxed */
|
|
|
|
/* atomic_fetch_sub_relaxed */
|
|
#ifndef atomic_fetch_sub_relaxed
|
|
#define atomic_fetch_sub_relaxed atomic_fetch_sub
|
|
#define atomic_fetch_sub_acquire atomic_fetch_sub
|
|
#define atomic_fetch_sub_release atomic_fetch_sub
|
|
|
|
#else /* atomic_fetch_sub_relaxed */
|
|
|
|
#ifndef atomic_fetch_sub_acquire
|
|
#define atomic_fetch_sub_acquire(...) \
|
|
__atomic_op_acquire(atomic_fetch_sub, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_sub_release
|
|
#define atomic_fetch_sub_release(...) \
|
|
__atomic_op_release(atomic_fetch_sub, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_sub
|
|
#define atomic_fetch_sub(...) \
|
|
__atomic_op_fence(atomic_fetch_sub, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_fetch_sub_relaxed */
|
|
|
|
/* atomic_fetch_dec_relaxed */
|
|
#ifndef atomic_fetch_dec_relaxed
|
|
|
|
#ifndef atomic_fetch_dec
|
|
#define atomic_fetch_dec(v) atomic_fetch_sub(1, (v))
|
|
#define atomic_fetch_dec_relaxed(v) atomic_fetch_sub_relaxed(1, (v))
|
|
#define atomic_fetch_dec_acquire(v) atomic_fetch_sub_acquire(1, (v))
|
|
#define atomic_fetch_dec_release(v) atomic_fetch_sub_release(1, (v))
|
|
#else /* atomic_fetch_dec */
|
|
#define atomic_fetch_dec_relaxed atomic_fetch_dec
|
|
#define atomic_fetch_dec_acquire atomic_fetch_dec
|
|
#define atomic_fetch_dec_release atomic_fetch_dec
|
|
#endif /* atomic_fetch_dec */
|
|
|
|
#else /* atomic_fetch_dec_relaxed */
|
|
|
|
#ifndef atomic_fetch_dec_acquire
|
|
#define atomic_fetch_dec_acquire(...) \
|
|
__atomic_op_acquire(atomic_fetch_dec, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_dec_release
|
|
#define atomic_fetch_dec_release(...) \
|
|
__atomic_op_release(atomic_fetch_dec, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_dec
|
|
#define atomic_fetch_dec(...) \
|
|
__atomic_op_fence(atomic_fetch_dec, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_fetch_dec_relaxed */
|
|
|
|
/* atomic_fetch_or_relaxed */
|
|
#ifndef atomic_fetch_or_relaxed
|
|
#define atomic_fetch_or_relaxed atomic_fetch_or
|
|
#define atomic_fetch_or_acquire atomic_fetch_or
|
|
#define atomic_fetch_or_release atomic_fetch_or
|
|
|
|
#else /* atomic_fetch_or_relaxed */
|
|
|
|
#ifndef atomic_fetch_or_acquire
|
|
#define atomic_fetch_or_acquire(...) \
|
|
__atomic_op_acquire(atomic_fetch_or, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_or_release
|
|
#define atomic_fetch_or_release(...) \
|
|
__atomic_op_release(atomic_fetch_or, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_or
|
|
#define atomic_fetch_or(...) \
|
|
__atomic_op_fence(atomic_fetch_or, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_fetch_or_relaxed */
|
|
|
|
/* atomic_fetch_and_relaxed */
|
|
#ifndef atomic_fetch_and_relaxed
|
|
#define atomic_fetch_and_relaxed atomic_fetch_and
|
|
#define atomic_fetch_and_acquire atomic_fetch_and
|
|
#define atomic_fetch_and_release atomic_fetch_and
|
|
|
|
#else /* atomic_fetch_and_relaxed */
|
|
|
|
#ifndef atomic_fetch_and_acquire
|
|
#define atomic_fetch_and_acquire(...) \
|
|
__atomic_op_acquire(atomic_fetch_and, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_and_release
|
|
#define atomic_fetch_and_release(...) \
|
|
__atomic_op_release(atomic_fetch_and, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_and
|
|
#define atomic_fetch_and(...) \
|
|
__atomic_op_fence(atomic_fetch_and, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_fetch_and_relaxed */
|
|
|
|
#ifdef atomic_andnot
|
|
/* atomic_fetch_andnot_relaxed */
|
|
#ifndef atomic_fetch_andnot_relaxed
|
|
#define atomic_fetch_andnot_relaxed atomic_fetch_andnot
|
|
#define atomic_fetch_andnot_acquire atomic_fetch_andnot
|
|
#define atomic_fetch_andnot_release atomic_fetch_andnot
|
|
|
|
#else /* atomic_fetch_andnot_relaxed */
|
|
|
|
#ifndef atomic_fetch_andnot_acquire
|
|
#define atomic_fetch_andnot_acquire(...) \
|
|
__atomic_op_acquire(atomic_fetch_andnot, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_andnot_release
|
|
#define atomic_fetch_andnot_release(...) \
|
|
__atomic_op_release(atomic_fetch_andnot, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_andnot
|
|
#define atomic_fetch_andnot(...) \
|
|
__atomic_op_fence(atomic_fetch_andnot, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_fetch_andnot_relaxed */
|
|
#endif /* atomic_andnot */
|
|
|
|
/* atomic_fetch_xor_relaxed */
|
|
#ifndef atomic_fetch_xor_relaxed
|
|
#define atomic_fetch_xor_relaxed atomic_fetch_xor
|
|
#define atomic_fetch_xor_acquire atomic_fetch_xor
|
|
#define atomic_fetch_xor_release atomic_fetch_xor
|
|
|
|
#else /* atomic_fetch_xor_relaxed */
|
|
|
|
#ifndef atomic_fetch_xor_acquire
|
|
#define atomic_fetch_xor_acquire(...) \
|
|
__atomic_op_acquire(atomic_fetch_xor, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_xor_release
|
|
#define atomic_fetch_xor_release(...) \
|
|
__atomic_op_release(atomic_fetch_xor, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_fetch_xor
|
|
#define atomic_fetch_xor(...) \
|
|
__atomic_op_fence(atomic_fetch_xor, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_fetch_xor_relaxed */
|
|
|
|
|
|
/* atomic_xchg_relaxed */
|
|
#ifndef atomic_xchg_relaxed
|
|
#define atomic_xchg_relaxed atomic_xchg
|
|
#define atomic_xchg_acquire atomic_xchg
|
|
#define atomic_xchg_release atomic_xchg
|
|
|
|
#else /* atomic_xchg_relaxed */
|
|
|
|
#ifndef atomic_xchg_acquire
|
|
#define atomic_xchg_acquire(...) \
|
|
__atomic_op_acquire(atomic_xchg, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_xchg_release
|
|
#define atomic_xchg_release(...) \
|
|
__atomic_op_release(atomic_xchg, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_xchg
|
|
#define atomic_xchg(...) \
|
|
__atomic_op_fence(atomic_xchg, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_xchg_relaxed */
|
|
|
|
/* atomic_cmpxchg_relaxed */
|
|
#ifndef atomic_cmpxchg_relaxed
|
|
#define atomic_cmpxchg_relaxed atomic_cmpxchg
|
|
#define atomic_cmpxchg_acquire atomic_cmpxchg
|
|
#define atomic_cmpxchg_release atomic_cmpxchg
|
|
|
|
#else /* atomic_cmpxchg_relaxed */
|
|
|
|
#ifndef atomic_cmpxchg_acquire
|
|
#define atomic_cmpxchg_acquire(...) \
|
|
__atomic_op_acquire(atomic_cmpxchg, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_cmpxchg_release
|
|
#define atomic_cmpxchg_release(...) \
|
|
__atomic_op_release(atomic_cmpxchg, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic_cmpxchg
|
|
#define atomic_cmpxchg(...) \
|
|
__atomic_op_fence(atomic_cmpxchg, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic_cmpxchg_relaxed */
|
|
|
|
#ifndef atomic_try_cmpxchg
|
|
|
|
#define __atomic_try_cmpxchg(type, _p, _po, _n) \
|
|
({ \
|
|
typeof(_po) __po = (_po); \
|
|
typeof(*(_po)) __r, __o = *__po; \
|
|
__r = atomic_cmpxchg##type((_p), __o, (_n)); \
|
|
if (unlikely(__r != __o)) \
|
|
*__po = __r; \
|
|
likely(__r == __o); \
|
|
})
|
|
|
|
#define atomic_try_cmpxchg(_p, _po, _n) __atomic_try_cmpxchg(, _p, _po, _n)
|
|
#define atomic_try_cmpxchg_relaxed(_p, _po, _n) __atomic_try_cmpxchg(_relaxed, _p, _po, _n)
|
|
#define atomic_try_cmpxchg_acquire(_p, _po, _n) __atomic_try_cmpxchg(_acquire, _p, _po, _n)
|
|
#define atomic_try_cmpxchg_release(_p, _po, _n) __atomic_try_cmpxchg(_release, _p, _po, _n)
|
|
|
|
#else /* atomic_try_cmpxchg */
|
|
#define atomic_try_cmpxchg_relaxed atomic_try_cmpxchg
|
|
#define atomic_try_cmpxchg_acquire atomic_try_cmpxchg
|
|
#define atomic_try_cmpxchg_release atomic_try_cmpxchg
|
|
#endif /* atomic_try_cmpxchg */
|
|
|
|
/* cmpxchg_relaxed */
|
|
#ifndef cmpxchg_relaxed
|
|
#define cmpxchg_relaxed cmpxchg
|
|
#define cmpxchg_acquire cmpxchg
|
|
#define cmpxchg_release cmpxchg
|
|
|
|
#else /* cmpxchg_relaxed */
|
|
|
|
#ifndef cmpxchg_acquire
|
|
#define cmpxchg_acquire(...) \
|
|
__atomic_op_acquire(cmpxchg, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef cmpxchg_release
|
|
#define cmpxchg_release(...) \
|
|
__atomic_op_release(cmpxchg, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef cmpxchg
|
|
#define cmpxchg(...) \
|
|
__atomic_op_fence(cmpxchg, __VA_ARGS__)
|
|
#endif
|
|
#endif /* cmpxchg_relaxed */
|
|
|
|
/* cmpxchg64_relaxed */
|
|
#ifndef cmpxchg64_relaxed
|
|
#define cmpxchg64_relaxed cmpxchg64
|
|
#define cmpxchg64_acquire cmpxchg64
|
|
#define cmpxchg64_release cmpxchg64
|
|
|
|
#else /* cmpxchg64_relaxed */
|
|
|
|
#ifndef cmpxchg64_acquire
|
|
#define cmpxchg64_acquire(...) \
|
|
__atomic_op_acquire(cmpxchg64, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef cmpxchg64_release
|
|
#define cmpxchg64_release(...) \
|
|
__atomic_op_release(cmpxchg64, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef cmpxchg64
|
|
#define cmpxchg64(...) \
|
|
__atomic_op_fence(cmpxchg64, __VA_ARGS__)
|
|
#endif
|
|
#endif /* cmpxchg64_relaxed */
|
|
|
|
/* xchg_relaxed */
|
|
#ifndef xchg_relaxed
|
|
#define xchg_relaxed xchg
|
|
#define xchg_acquire xchg
|
|
#define xchg_release xchg
|
|
|
|
#else /* xchg_relaxed */
|
|
|
|
#ifndef xchg_acquire
|
|
#define xchg_acquire(...) __atomic_op_acquire(xchg, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef xchg_release
|
|
#define xchg_release(...) __atomic_op_release(xchg, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef xchg
|
|
#define xchg(...) __atomic_op_fence(xchg, __VA_ARGS__)
|
|
#endif
|
|
#endif /* xchg_relaxed */
|
|
|
|
/**
|
|
* atomic_add_unless - add unless the number is already a given value
|
|
* @v: pointer of type atomic_t
|
|
* @a: the amount to add to v...
|
|
* @u: ...unless v is equal to u.
|
|
*
|
|
* Atomically adds @a to @v, so long as @v was not already @u.
|
|
* Returns non-zero if @v was not @u, and zero otherwise.
|
|
*/
|
|
static inline int atomic_add_unless(atomic_t *v, int a, int u)
|
|
{
|
|
return __atomic_add_unless(v, a, u) != u;
|
|
}
|
|
|
|
/**
|
|
* atomic_inc_not_zero - increment unless the number is zero
|
|
* @v: pointer of type atomic_t
|
|
*
|
|
* Atomically increments @v by 1, so long as @v is non-zero.
|
|
* Returns non-zero if @v was non-zero, and zero otherwise.
|
|
*/
|
|
#ifndef atomic_inc_not_zero
|
|
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
|
|
#endif
|
|
|
|
#ifndef atomic_andnot
|
|
static inline void atomic_andnot(int i, atomic_t *v)
|
|
{
|
|
atomic_and(~i, v);
|
|
}
|
|
|
|
static inline int atomic_fetch_andnot(int i, atomic_t *v)
|
|
{
|
|
return atomic_fetch_and(~i, v);
|
|
}
|
|
|
|
static inline int atomic_fetch_andnot_relaxed(int i, atomic_t *v)
|
|
{
|
|
return atomic_fetch_and_relaxed(~i, v);
|
|
}
|
|
|
|
static inline int atomic_fetch_andnot_acquire(int i, atomic_t *v)
|
|
{
|
|
return atomic_fetch_and_acquire(~i, v);
|
|
}
|
|
|
|
static inline int atomic_fetch_andnot_release(int i, atomic_t *v)
|
|
{
|
|
return atomic_fetch_and_release(~i, v);
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* atomic_inc_not_zero_hint - increment if not null
|
|
* @v: pointer of type atomic_t
|
|
* @hint: probable value of the atomic before the increment
|
|
*
|
|
* This version of atomic_inc_not_zero() gives a hint of probable
|
|
* value of the atomic. This helps processor to not read the memory
|
|
* before doing the atomic read/modify/write cycle, lowering
|
|
* number of bus transactions on some arches.
|
|
*
|
|
* Returns: 0 if increment was not done, 1 otherwise.
|
|
*/
|
|
#ifndef atomic_inc_not_zero_hint
|
|
static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint)
|
|
{
|
|
int val, c = hint;
|
|
|
|
/* sanity test, should be removed by compiler if hint is a constant */
|
|
if (!hint)
|
|
return atomic_inc_not_zero(v);
|
|
|
|
do {
|
|
val = atomic_cmpxchg(v, c, c + 1);
|
|
if (val == c)
|
|
return 1;
|
|
c = val;
|
|
} while (c);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifndef atomic_inc_unless_negative
|
|
static inline int atomic_inc_unless_negative(atomic_t *p)
|
|
{
|
|
int v, v1;
|
|
for (v = 0; v >= 0; v = v1) {
|
|
v1 = atomic_cmpxchg(p, v, v + 1);
|
|
if (likely(v1 == v))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifndef atomic_dec_unless_positive
|
|
static inline int atomic_dec_unless_positive(atomic_t *p)
|
|
{
|
|
int v, v1;
|
|
for (v = 0; v <= 0; v = v1) {
|
|
v1 = atomic_cmpxchg(p, v, v - 1);
|
|
if (likely(v1 == v))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* atomic_dec_if_positive - decrement by 1 if old value positive
|
|
* @v: pointer of type atomic_t
|
|
*
|
|
* The function returns the old value of *v minus 1, even if
|
|
* the atomic variable, v, was not decremented.
|
|
*/
|
|
#ifndef atomic_dec_if_positive
|
|
static inline int atomic_dec_if_positive(atomic_t *v)
|
|
{
|
|
int c, old, dec;
|
|
c = atomic_read(v);
|
|
for (;;) {
|
|
dec = c - 1;
|
|
if (unlikely(dec < 0))
|
|
break;
|
|
old = atomic_cmpxchg((v), c, dec);
|
|
if (likely(old == c))
|
|
break;
|
|
c = old;
|
|
}
|
|
return dec;
|
|
}
|
|
#endif
|
|
|
|
#define atomic_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
|
|
|
|
#ifdef CONFIG_GENERIC_ATOMIC64
|
|
#include <asm-generic/atomic64.h>
|
|
#endif
|
|
|
|
#ifndef atomic64_read_acquire
|
|
#define atomic64_read_acquire(v) smp_load_acquire(&(v)->counter)
|
|
#endif
|
|
|
|
#ifndef atomic64_set_release
|
|
#define atomic64_set_release(v, i) smp_store_release(&(v)->counter, (i))
|
|
#endif
|
|
|
|
/* atomic64_add_return_relaxed */
|
|
#ifndef atomic64_add_return_relaxed
|
|
#define atomic64_add_return_relaxed atomic64_add_return
|
|
#define atomic64_add_return_acquire atomic64_add_return
|
|
#define atomic64_add_return_release atomic64_add_return
|
|
|
|
#else /* atomic64_add_return_relaxed */
|
|
|
|
#ifndef atomic64_add_return_acquire
|
|
#define atomic64_add_return_acquire(...) \
|
|
__atomic_op_acquire(atomic64_add_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_add_return_release
|
|
#define atomic64_add_return_release(...) \
|
|
__atomic_op_release(atomic64_add_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_add_return
|
|
#define atomic64_add_return(...) \
|
|
__atomic_op_fence(atomic64_add_return, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_add_return_relaxed */
|
|
|
|
/* atomic64_inc_return_relaxed */
|
|
#ifndef atomic64_inc_return_relaxed
|
|
#define atomic64_inc_return_relaxed atomic64_inc_return
|
|
#define atomic64_inc_return_acquire atomic64_inc_return
|
|
#define atomic64_inc_return_release atomic64_inc_return
|
|
|
|
#else /* atomic64_inc_return_relaxed */
|
|
|
|
#ifndef atomic64_inc_return_acquire
|
|
#define atomic64_inc_return_acquire(...) \
|
|
__atomic_op_acquire(atomic64_inc_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_inc_return_release
|
|
#define atomic64_inc_return_release(...) \
|
|
__atomic_op_release(atomic64_inc_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_inc_return
|
|
#define atomic64_inc_return(...) \
|
|
__atomic_op_fence(atomic64_inc_return, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_inc_return_relaxed */
|
|
|
|
|
|
/* atomic64_sub_return_relaxed */
|
|
#ifndef atomic64_sub_return_relaxed
|
|
#define atomic64_sub_return_relaxed atomic64_sub_return
|
|
#define atomic64_sub_return_acquire atomic64_sub_return
|
|
#define atomic64_sub_return_release atomic64_sub_return
|
|
|
|
#else /* atomic64_sub_return_relaxed */
|
|
|
|
#ifndef atomic64_sub_return_acquire
|
|
#define atomic64_sub_return_acquire(...) \
|
|
__atomic_op_acquire(atomic64_sub_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_sub_return_release
|
|
#define atomic64_sub_return_release(...) \
|
|
__atomic_op_release(atomic64_sub_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_sub_return
|
|
#define atomic64_sub_return(...) \
|
|
__atomic_op_fence(atomic64_sub_return, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_sub_return_relaxed */
|
|
|
|
/* atomic64_dec_return_relaxed */
|
|
#ifndef atomic64_dec_return_relaxed
|
|
#define atomic64_dec_return_relaxed atomic64_dec_return
|
|
#define atomic64_dec_return_acquire atomic64_dec_return
|
|
#define atomic64_dec_return_release atomic64_dec_return
|
|
|
|
#else /* atomic64_dec_return_relaxed */
|
|
|
|
#ifndef atomic64_dec_return_acquire
|
|
#define atomic64_dec_return_acquire(...) \
|
|
__atomic_op_acquire(atomic64_dec_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_dec_return_release
|
|
#define atomic64_dec_return_release(...) \
|
|
__atomic_op_release(atomic64_dec_return, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_dec_return
|
|
#define atomic64_dec_return(...) \
|
|
__atomic_op_fence(atomic64_dec_return, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_dec_return_relaxed */
|
|
|
|
|
|
/* atomic64_fetch_add_relaxed */
|
|
#ifndef atomic64_fetch_add_relaxed
|
|
#define atomic64_fetch_add_relaxed atomic64_fetch_add
|
|
#define atomic64_fetch_add_acquire atomic64_fetch_add
|
|
#define atomic64_fetch_add_release atomic64_fetch_add
|
|
|
|
#else /* atomic64_fetch_add_relaxed */
|
|
|
|
#ifndef atomic64_fetch_add_acquire
|
|
#define atomic64_fetch_add_acquire(...) \
|
|
__atomic_op_acquire(atomic64_fetch_add, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_add_release
|
|
#define atomic64_fetch_add_release(...) \
|
|
__atomic_op_release(atomic64_fetch_add, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_add
|
|
#define atomic64_fetch_add(...) \
|
|
__atomic_op_fence(atomic64_fetch_add, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_fetch_add_relaxed */
|
|
|
|
/* atomic64_fetch_inc_relaxed */
|
|
#ifndef atomic64_fetch_inc_relaxed
|
|
|
|
#ifndef atomic64_fetch_inc
|
|
#define atomic64_fetch_inc(v) atomic64_fetch_add(1, (v))
|
|
#define atomic64_fetch_inc_relaxed(v) atomic64_fetch_add_relaxed(1, (v))
|
|
#define atomic64_fetch_inc_acquire(v) atomic64_fetch_add_acquire(1, (v))
|
|
#define atomic64_fetch_inc_release(v) atomic64_fetch_add_release(1, (v))
|
|
#else /* atomic64_fetch_inc */
|
|
#define atomic64_fetch_inc_relaxed atomic64_fetch_inc
|
|
#define atomic64_fetch_inc_acquire atomic64_fetch_inc
|
|
#define atomic64_fetch_inc_release atomic64_fetch_inc
|
|
#endif /* atomic64_fetch_inc */
|
|
|
|
#else /* atomic64_fetch_inc_relaxed */
|
|
|
|
#ifndef atomic64_fetch_inc_acquire
|
|
#define atomic64_fetch_inc_acquire(...) \
|
|
__atomic_op_acquire(atomic64_fetch_inc, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_inc_release
|
|
#define atomic64_fetch_inc_release(...) \
|
|
__atomic_op_release(atomic64_fetch_inc, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_inc
|
|
#define atomic64_fetch_inc(...) \
|
|
__atomic_op_fence(atomic64_fetch_inc, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_fetch_inc_relaxed */
|
|
|
|
/* atomic64_fetch_sub_relaxed */
|
|
#ifndef atomic64_fetch_sub_relaxed
|
|
#define atomic64_fetch_sub_relaxed atomic64_fetch_sub
|
|
#define atomic64_fetch_sub_acquire atomic64_fetch_sub
|
|
#define atomic64_fetch_sub_release atomic64_fetch_sub
|
|
|
|
#else /* atomic64_fetch_sub_relaxed */
|
|
|
|
#ifndef atomic64_fetch_sub_acquire
|
|
#define atomic64_fetch_sub_acquire(...) \
|
|
__atomic_op_acquire(atomic64_fetch_sub, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_sub_release
|
|
#define atomic64_fetch_sub_release(...) \
|
|
__atomic_op_release(atomic64_fetch_sub, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_sub
|
|
#define atomic64_fetch_sub(...) \
|
|
__atomic_op_fence(atomic64_fetch_sub, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_fetch_sub_relaxed */
|
|
|
|
/* atomic64_fetch_dec_relaxed */
|
|
#ifndef atomic64_fetch_dec_relaxed
|
|
|
|
#ifndef atomic64_fetch_dec
|
|
#define atomic64_fetch_dec(v) atomic64_fetch_sub(1, (v))
|
|
#define atomic64_fetch_dec_relaxed(v) atomic64_fetch_sub_relaxed(1, (v))
|
|
#define atomic64_fetch_dec_acquire(v) atomic64_fetch_sub_acquire(1, (v))
|
|
#define atomic64_fetch_dec_release(v) atomic64_fetch_sub_release(1, (v))
|
|
#else /* atomic64_fetch_dec */
|
|
#define atomic64_fetch_dec_relaxed atomic64_fetch_dec
|
|
#define atomic64_fetch_dec_acquire atomic64_fetch_dec
|
|
#define atomic64_fetch_dec_release atomic64_fetch_dec
|
|
#endif /* atomic64_fetch_dec */
|
|
|
|
#else /* atomic64_fetch_dec_relaxed */
|
|
|
|
#ifndef atomic64_fetch_dec_acquire
|
|
#define atomic64_fetch_dec_acquire(...) \
|
|
__atomic_op_acquire(atomic64_fetch_dec, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_dec_release
|
|
#define atomic64_fetch_dec_release(...) \
|
|
__atomic_op_release(atomic64_fetch_dec, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_dec
|
|
#define atomic64_fetch_dec(...) \
|
|
__atomic_op_fence(atomic64_fetch_dec, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_fetch_dec_relaxed */
|
|
|
|
/* atomic64_fetch_or_relaxed */
|
|
#ifndef atomic64_fetch_or_relaxed
|
|
#define atomic64_fetch_or_relaxed atomic64_fetch_or
|
|
#define atomic64_fetch_or_acquire atomic64_fetch_or
|
|
#define atomic64_fetch_or_release atomic64_fetch_or
|
|
|
|
#else /* atomic64_fetch_or_relaxed */
|
|
|
|
#ifndef atomic64_fetch_or_acquire
|
|
#define atomic64_fetch_or_acquire(...) \
|
|
__atomic_op_acquire(atomic64_fetch_or, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_or_release
|
|
#define atomic64_fetch_or_release(...) \
|
|
__atomic_op_release(atomic64_fetch_or, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_or
|
|
#define atomic64_fetch_or(...) \
|
|
__atomic_op_fence(atomic64_fetch_or, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_fetch_or_relaxed */
|
|
|
|
/* atomic64_fetch_and_relaxed */
|
|
#ifndef atomic64_fetch_and_relaxed
|
|
#define atomic64_fetch_and_relaxed atomic64_fetch_and
|
|
#define atomic64_fetch_and_acquire atomic64_fetch_and
|
|
#define atomic64_fetch_and_release atomic64_fetch_and
|
|
|
|
#else /* atomic64_fetch_and_relaxed */
|
|
|
|
#ifndef atomic64_fetch_and_acquire
|
|
#define atomic64_fetch_and_acquire(...) \
|
|
__atomic_op_acquire(atomic64_fetch_and, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_and_release
|
|
#define atomic64_fetch_and_release(...) \
|
|
__atomic_op_release(atomic64_fetch_and, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_and
|
|
#define atomic64_fetch_and(...) \
|
|
__atomic_op_fence(atomic64_fetch_and, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_fetch_and_relaxed */
|
|
|
|
#ifdef atomic64_andnot
|
|
/* atomic64_fetch_andnot_relaxed */
|
|
#ifndef atomic64_fetch_andnot_relaxed
|
|
#define atomic64_fetch_andnot_relaxed atomic64_fetch_andnot
|
|
#define atomic64_fetch_andnot_acquire atomic64_fetch_andnot
|
|
#define atomic64_fetch_andnot_release atomic64_fetch_andnot
|
|
|
|
#else /* atomic64_fetch_andnot_relaxed */
|
|
|
|
#ifndef atomic64_fetch_andnot_acquire
|
|
#define atomic64_fetch_andnot_acquire(...) \
|
|
__atomic_op_acquire(atomic64_fetch_andnot, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_andnot_release
|
|
#define atomic64_fetch_andnot_release(...) \
|
|
__atomic_op_release(atomic64_fetch_andnot, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_andnot
|
|
#define atomic64_fetch_andnot(...) \
|
|
__atomic_op_fence(atomic64_fetch_andnot, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_fetch_andnot_relaxed */
|
|
#endif /* atomic64_andnot */
|
|
|
|
/* atomic64_fetch_xor_relaxed */
|
|
#ifndef atomic64_fetch_xor_relaxed
|
|
#define atomic64_fetch_xor_relaxed atomic64_fetch_xor
|
|
#define atomic64_fetch_xor_acquire atomic64_fetch_xor
|
|
#define atomic64_fetch_xor_release atomic64_fetch_xor
|
|
|
|
#else /* atomic64_fetch_xor_relaxed */
|
|
|
|
#ifndef atomic64_fetch_xor_acquire
|
|
#define atomic64_fetch_xor_acquire(...) \
|
|
__atomic_op_acquire(atomic64_fetch_xor, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_xor_release
|
|
#define atomic64_fetch_xor_release(...) \
|
|
__atomic_op_release(atomic64_fetch_xor, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_fetch_xor
|
|
#define atomic64_fetch_xor(...) \
|
|
__atomic_op_fence(atomic64_fetch_xor, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_fetch_xor_relaxed */
|
|
|
|
|
|
/* atomic64_xchg_relaxed */
|
|
#ifndef atomic64_xchg_relaxed
|
|
#define atomic64_xchg_relaxed atomic64_xchg
|
|
#define atomic64_xchg_acquire atomic64_xchg
|
|
#define atomic64_xchg_release atomic64_xchg
|
|
|
|
#else /* atomic64_xchg_relaxed */
|
|
|
|
#ifndef atomic64_xchg_acquire
|
|
#define atomic64_xchg_acquire(...) \
|
|
__atomic_op_acquire(atomic64_xchg, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_xchg_release
|
|
#define atomic64_xchg_release(...) \
|
|
__atomic_op_release(atomic64_xchg, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_xchg
|
|
#define atomic64_xchg(...) \
|
|
__atomic_op_fence(atomic64_xchg, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_xchg_relaxed */
|
|
|
|
/* atomic64_cmpxchg_relaxed */
|
|
#ifndef atomic64_cmpxchg_relaxed
|
|
#define atomic64_cmpxchg_relaxed atomic64_cmpxchg
|
|
#define atomic64_cmpxchg_acquire atomic64_cmpxchg
|
|
#define atomic64_cmpxchg_release atomic64_cmpxchg
|
|
|
|
#else /* atomic64_cmpxchg_relaxed */
|
|
|
|
#ifndef atomic64_cmpxchg_acquire
|
|
#define atomic64_cmpxchg_acquire(...) \
|
|
__atomic_op_acquire(atomic64_cmpxchg, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_cmpxchg_release
|
|
#define atomic64_cmpxchg_release(...) \
|
|
__atomic_op_release(atomic64_cmpxchg, __VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef atomic64_cmpxchg
|
|
#define atomic64_cmpxchg(...) \
|
|
__atomic_op_fence(atomic64_cmpxchg, __VA_ARGS__)
|
|
#endif
|
|
#endif /* atomic64_cmpxchg_relaxed */
|
|
|
|
#ifndef atomic64_try_cmpxchg
|
|
|
|
#define __atomic64_try_cmpxchg(type, _p, _po, _n) \
|
|
({ \
|
|
typeof(_po) __po = (_po); \
|
|
typeof(*(_po)) __r, __o = *__po; \
|
|
__r = atomic64_cmpxchg##type((_p), __o, (_n)); \
|
|
if (unlikely(__r != __o)) \
|
|
*__po = __r; \
|
|
likely(__r == __o); \
|
|
})
|
|
|
|
#define atomic64_try_cmpxchg(_p, _po, _n) __atomic64_try_cmpxchg(, _p, _po, _n)
|
|
#define atomic64_try_cmpxchg_relaxed(_p, _po, _n) __atomic64_try_cmpxchg(_relaxed, _p, _po, _n)
|
|
#define atomic64_try_cmpxchg_acquire(_p, _po, _n) __atomic64_try_cmpxchg(_acquire, _p, _po, _n)
|
|
#define atomic64_try_cmpxchg_release(_p, _po, _n) __atomic64_try_cmpxchg(_release, _p, _po, _n)
|
|
|
|
#else /* atomic64_try_cmpxchg */
|
|
#define atomic64_try_cmpxchg_relaxed atomic64_try_cmpxchg
|
|
#define atomic64_try_cmpxchg_acquire atomic64_try_cmpxchg
|
|
#define atomic64_try_cmpxchg_release atomic64_try_cmpxchg
|
|
#endif /* atomic64_try_cmpxchg */
|
|
|
|
#ifndef atomic64_andnot
|
|
static inline void atomic64_andnot(long long i, atomic64_t *v)
|
|
{
|
|
atomic64_and(~i, v);
|
|
}
|
|
|
|
static inline long long atomic64_fetch_andnot(long long i, atomic64_t *v)
|
|
{
|
|
return atomic64_fetch_and(~i, v);
|
|
}
|
|
|
|
static inline long long atomic64_fetch_andnot_relaxed(long long i, atomic64_t *v)
|
|
{
|
|
return atomic64_fetch_and_relaxed(~i, v);
|
|
}
|
|
|
|
static inline long long atomic64_fetch_andnot_acquire(long long i, atomic64_t *v)
|
|
{
|
|
return atomic64_fetch_and_acquire(~i, v);
|
|
}
|
|
|
|
static inline long long atomic64_fetch_andnot_release(long long i, atomic64_t *v)
|
|
{
|
|
return atomic64_fetch_and_release(~i, v);
|
|
}
|
|
#endif
|
|
|
|
#define atomic64_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
|
|
|
|
#include <asm-generic/atomic-long.h>
|
|
|
|
#endif /* _LINUX_ATOMIC_H */
|