2011-07-26 16:09:08 -07:00
|
|
|
/* Atomic operations usable in machine independent code */
|
2010-11-11 14:05:08 -08:00
|
|
|
#ifndef _LINUX_ATOMIC_H
|
|
|
|
|
#define _LINUX_ATOMIC_H
|
2018-06-21 13:13:07 +01:00
|
|
|
#include <linux/types.h>
|
|
|
|
|
|
2010-11-11 14:05:08 -08:00
|
|
|
#include <asm/atomic.h>
|
locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations
Whilst porting the generic qrwlock code over to arm64, it became
apparent that any portable locking code needs finer-grained control of
the memory-ordering guarantees provided by our atomic routines.
In particular: xchg, cmpxchg, {add,sub}_return are often used in
situations where full barrier semantics (currently the only option
available) are not required. For example, when a reader increments a
reader count to obtain a lock, checking the old value to see if a writer
was present, only acquire semantics are strictly needed.
This patch introduces three new ordering semantics for these operations:
- *_relaxed: No ordering guarantees. This is similar to what we have
already for the non-return atomics (e.g. atomic_add).
- *_acquire: ACQUIRE semantics, similar to smp_load_acquire.
- *_release: RELEASE semantics, similar to smp_store_release.
In memory-ordering speak, this means that the acquire/release semantics
are RCpc as opposed to RCsc. Consequently a RELEASE followed by an
ACQUIRE does not imply a full barrier, as already documented in
memory-barriers.txt.
Currently, all the new macros are conditionally mapped to the full-mb
variants, however if the *_relaxed version is provided by the
architecture, then the acquire/release variants are constructed by
supplementing the relaxed routine with an explicit barrier.
Signed-off-by: Will Deacon <will.deacon@arm.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>
Cc: Waiman.Long@hp.com
Cc: paulmck@linux.vnet.ibm.com
Link: http://lkml.kernel.org/r/1438880084-18856-2-git-send-email-will.deacon@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-08-06 17:54:37 +01:00
|
|
|
#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.
|
2015-12-15 22:24:14 +08:00
|
|
|
*
|
|
|
|
|
* 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
|
locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations
Whilst porting the generic qrwlock code over to arm64, it became
apparent that any portable locking code needs finer-grained control of
the memory-ordering guarantees provided by our atomic routines.
In particular: xchg, cmpxchg, {add,sub}_return are often used in
situations where full barrier semantics (currently the only option
available) are not required. For example, when a reader increments a
reader count to obtain a lock, checking the old value to see if a writer
was present, only acquire semantics are strictly needed.
This patch introduces three new ordering semantics for these operations:
- *_relaxed: No ordering guarantees. This is similar to what we have
already for the non-return atomics (e.g. atomic_add).
- *_acquire: ACQUIRE semantics, similar to smp_load_acquire.
- *_release: RELEASE semantics, similar to smp_store_release.
In memory-ordering speak, this means that the acquire/release semantics
are RCpc as opposed to RCsc. Consequently a RELEASE followed by an
ACQUIRE does not imply a full barrier, as already documented in
memory-barriers.txt.
Currently, all the new macros are conditionally mapped to the full-mb
variants, however if the *_relaxed version is provided by the
architecture, then the acquire/release variants are constructed by
supplementing the relaxed routine with an explicit barrier.
Signed-off-by: Will Deacon <will.deacon@arm.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>
Cc: Waiman.Long@hp.com
Cc: paulmck@linux.vnet.ibm.com
Link: http://lkml.kernel.org/r/1438880084-18856-2-git-send-email-will.deacon@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-08-06 17:54:37 +01:00
|
|
|
*/
|
2015-12-15 22:24:14 +08:00
|
|
|
#ifndef __atomic_op_acquire
|
locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations
Whilst porting the generic qrwlock code over to arm64, it became
apparent that any portable locking code needs finer-grained control of
the memory-ordering guarantees provided by our atomic routines.
In particular: xchg, cmpxchg, {add,sub}_return are often used in
situations where full barrier semantics (currently the only option
available) are not required. For example, when a reader increments a
reader count to obtain a lock, checking the old value to see if a writer
was present, only acquire semantics are strictly needed.
This patch introduces three new ordering semantics for these operations:
- *_relaxed: No ordering guarantees. This is similar to what we have
already for the non-return atomics (e.g. atomic_add).
- *_acquire: ACQUIRE semantics, similar to smp_load_acquire.
- *_release: RELEASE semantics, similar to smp_store_release.
In memory-ordering speak, this means that the acquire/release semantics
are RCpc as opposed to RCsc. Consequently a RELEASE followed by an
ACQUIRE does not imply a full barrier, as already documented in
memory-barriers.txt.
Currently, all the new macros are conditionally mapped to the full-mb
variants, however if the *_relaxed version is provided by the
architecture, then the acquire/release variants are constructed by
supplementing the relaxed routine with an explicit barrier.
Signed-off-by: Will Deacon <will.deacon@arm.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>
Cc: Waiman.Long@hp.com
Cc: paulmck@linux.vnet.ibm.com
Link: http://lkml.kernel.org/r/1438880084-18856-2-git-send-email-will.deacon@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-08-06 17:54:37 +01:00
|
|
|
#define __atomic_op_acquire(op, args...) \
|
|
|
|
|
({ \
|
|
|
|
|
typeof(op##_relaxed(args)) __ret = op##_relaxed(args); \
|
|
|
|
|
smp_mb__after_atomic(); \
|
|
|
|
|
__ret; \
|
|
|
|
|
})
|
2015-12-15 22:24:14 +08:00
|
|
|
#endif
|
locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations
Whilst porting the generic qrwlock code over to arm64, it became
apparent that any portable locking code needs finer-grained control of
the memory-ordering guarantees provided by our atomic routines.
In particular: xchg, cmpxchg, {add,sub}_return are often used in
situations where full barrier semantics (currently the only option
available) are not required. For example, when a reader increments a
reader count to obtain a lock, checking the old value to see if a writer
was present, only acquire semantics are strictly needed.
This patch introduces three new ordering semantics for these operations:
- *_relaxed: No ordering guarantees. This is similar to what we have
already for the non-return atomics (e.g. atomic_add).
- *_acquire: ACQUIRE semantics, similar to smp_load_acquire.
- *_release: RELEASE semantics, similar to smp_store_release.
In memory-ordering speak, this means that the acquire/release semantics
are RCpc as opposed to RCsc. Consequently a RELEASE followed by an
ACQUIRE does not imply a full barrier, as already documented in
memory-barriers.txt.
Currently, all the new macros are conditionally mapped to the full-mb
variants, however if the *_relaxed version is provided by the
architecture, then the acquire/release variants are constructed by
supplementing the relaxed routine with an explicit barrier.
Signed-off-by: Will Deacon <will.deacon@arm.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>
Cc: Waiman.Long@hp.com
Cc: paulmck@linux.vnet.ibm.com
Link: http://lkml.kernel.org/r/1438880084-18856-2-git-send-email-will.deacon@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-08-06 17:54:37 +01:00
|
|
|
|
2015-12-15 22:24:14 +08:00
|
|
|
#ifndef __atomic_op_release
|
locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations
Whilst porting the generic qrwlock code over to arm64, it became
apparent that any portable locking code needs finer-grained control of
the memory-ordering guarantees provided by our atomic routines.
In particular: xchg, cmpxchg, {add,sub}_return are often used in
situations where full barrier semantics (currently the only option
available) are not required. For example, when a reader increments a
reader count to obtain a lock, checking the old value to see if a writer
was present, only acquire semantics are strictly needed.
This patch introduces three new ordering semantics for these operations:
- *_relaxed: No ordering guarantees. This is similar to what we have
already for the non-return atomics (e.g. atomic_add).
- *_acquire: ACQUIRE semantics, similar to smp_load_acquire.
- *_release: RELEASE semantics, similar to smp_store_release.
In memory-ordering speak, this means that the acquire/release semantics
are RCpc as opposed to RCsc. Consequently a RELEASE followed by an
ACQUIRE does not imply a full barrier, as already documented in
memory-barriers.txt.
Currently, all the new macros are conditionally mapped to the full-mb
variants, however if the *_relaxed version is provided by the
architecture, then the acquire/release variants are constructed by
supplementing the relaxed routine with an explicit barrier.
Signed-off-by: Will Deacon <will.deacon@arm.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>
Cc: Waiman.Long@hp.com
Cc: paulmck@linux.vnet.ibm.com
Link: http://lkml.kernel.org/r/1438880084-18856-2-git-send-email-will.deacon@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-08-06 17:54:37 +01:00
|
|
|
#define __atomic_op_release(op, args...) \
|
|
|
|
|
({ \
|
|
|
|
|
smp_mb__before_atomic(); \
|
|
|
|
|
op##_relaxed(args); \
|
|
|
|
|
})
|
2015-12-15 22:24:14 +08:00
|
|
|
#endif
|
locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations
Whilst porting the generic qrwlock code over to arm64, it became
apparent that any portable locking code needs finer-grained control of
the memory-ordering guarantees provided by our atomic routines.
In particular: xchg, cmpxchg, {add,sub}_return are often used in
situations where full barrier semantics (currently the only option
available) are not required. For example, when a reader increments a
reader count to obtain a lock, checking the old value to see if a writer
was present, only acquire semantics are strictly needed.
This patch introduces three new ordering semantics for these operations:
- *_relaxed: No ordering guarantees. This is similar to what we have
already for the non-return atomics (e.g. atomic_add).
- *_acquire: ACQUIRE semantics, similar to smp_load_acquire.
- *_release: RELEASE semantics, similar to smp_store_release.
In memory-ordering speak, this means that the acquire/release semantics
are RCpc as opposed to RCsc. Consequently a RELEASE followed by an
ACQUIRE does not imply a full barrier, as already documented in
memory-barriers.txt.
Currently, all the new macros are conditionally mapped to the full-mb
variants, however if the *_relaxed version is provided by the
architecture, then the acquire/release variants are constructed by
supplementing the relaxed routine with an explicit barrier.
Signed-off-by: Will Deacon <will.deacon@arm.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>
Cc: Waiman.Long@hp.com
Cc: paulmck@linux.vnet.ibm.com
Link: http://lkml.kernel.org/r/1438880084-18856-2-git-send-email-will.deacon@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-08-06 17:54:37 +01:00
|
|
|
|
2015-12-15 22:24:14 +08:00
|
|
|
#ifndef __atomic_op_fence
|
locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations
Whilst porting the generic qrwlock code over to arm64, it became
apparent that any portable locking code needs finer-grained control of
the memory-ordering guarantees provided by our atomic routines.
In particular: xchg, cmpxchg, {add,sub}_return are often used in
situations where full barrier semantics (currently the only option
available) are not required. For example, when a reader increments a
reader count to obtain a lock, checking the old value to see if a writer
was present, only acquire semantics are strictly needed.
This patch introduces three new ordering semantics for these operations:
- *_relaxed: No ordering guarantees. This is similar to what we have
already for the non-return atomics (e.g. atomic_add).
- *_acquire: ACQUIRE semantics, similar to smp_load_acquire.
- *_release: RELEASE semantics, similar to smp_store_release.
In memory-ordering speak, this means that the acquire/release semantics
are RCpc as opposed to RCsc. Consequently a RELEASE followed by an
ACQUIRE does not imply a full barrier, as already documented in
memory-barriers.txt.
Currently, all the new macros are conditionally mapped to the full-mb
variants, however if the *_relaxed version is provided by the
architecture, then the acquire/release variants are constructed by
supplementing the relaxed routine with an explicit barrier.
Signed-off-by: Will Deacon <will.deacon@arm.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>
Cc: Waiman.Long@hp.com
Cc: paulmck@linux.vnet.ibm.com
Link: http://lkml.kernel.org/r/1438880084-18856-2-git-send-email-will.deacon@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-08-06 17:54:37 +01:00
|
|
|
#define __atomic_op_fence(op, args...) \
|
|
|
|
|
({ \
|
|
|
|
|
typeof(op##_relaxed(args)) __ret; \
|
|
|
|
|
smp_mb__before_atomic(); \
|
|
|
|
|
__ret = op##_relaxed(args); \
|
|
|
|
|
smp_mb__after_atomic(); \
|
|
|
|
|
__ret; \
|
|
|
|
|
})
|
2015-12-15 22:24:14 +08:00
|
|
|
#endif
|
locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations
Whilst porting the generic qrwlock code over to arm64, it became
apparent that any portable locking code needs finer-grained control of
the memory-ordering guarantees provided by our atomic routines.
In particular: xchg, cmpxchg, {add,sub}_return are often used in
situations where full barrier semantics (currently the only option
available) are not required. For example, when a reader increments a
reader count to obtain a lock, checking the old value to see if a writer
was present, only acquire semantics are strictly needed.
This patch introduces three new ordering semantics for these operations:
- *_relaxed: No ordering guarantees. This is similar to what we have
already for the non-return atomics (e.g. atomic_add).
- *_acquire: ACQUIRE semantics, similar to smp_load_acquire.
- *_release: RELEASE semantics, similar to smp_store_release.
In memory-ordering speak, this means that the acquire/release semantics
are RCpc as opposed to RCsc. Consequently a RELEASE followed by an
ACQUIRE does not imply a full barrier, as already documented in
memory-barriers.txt.
Currently, all the new macros are conditionally mapped to the full-mb
variants, however if the *_relaxed version is provided by the
architecture, then the acquire/release variants are constructed by
supplementing the relaxed routine with an explicit barrier.
Signed-off-by: Will Deacon <will.deacon@arm.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>
Cc: Waiman.Long@hp.com
Cc: paulmck@linux.vnet.ibm.com
Link: http://lkml.kernel.org/r/1438880084-18856-2-git-send-email-will.deacon@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-08-06 17:54:37 +01:00
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
|
|
2015-09-30 13:03:11 -07:00
|
|
|
/* 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 */
|
|
|
|
|
|
locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations
Whilst porting the generic qrwlock code over to arm64, it became
apparent that any portable locking code needs finer-grained control of
the memory-ordering guarantees provided by our atomic routines.
In particular: xchg, cmpxchg, {add,sub}_return are often used in
situations where full barrier semantics (currently the only option
available) are not required. For example, when a reader increments a
reader count to obtain a lock, checking the old value to see if a writer
was present, only acquire semantics are strictly needed.
This patch introduces three new ordering semantics for these operations:
- *_relaxed: No ordering guarantees. This is similar to what we have
already for the non-return atomics (e.g. atomic_add).
- *_acquire: ACQUIRE semantics, similar to smp_load_acquire.
- *_release: RELEASE semantics, similar to smp_store_release.
In memory-ordering speak, this means that the acquire/release semantics
are RCpc as opposed to RCsc. Consequently a RELEASE followed by an
ACQUIRE does not imply a full barrier, as already documented in
memory-barriers.txt.
Currently, all the new macros are conditionally mapped to the full-mb
variants, however if the *_relaxed version is provided by the
architecture, then the acquire/release variants are constructed by
supplementing the relaxed routine with an explicit barrier.
Signed-off-by: Will Deacon <will.deacon@arm.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>
Cc: Waiman.Long@hp.com
Cc: paulmck@linux.vnet.ibm.com
Link: http://lkml.kernel.org/r/1438880084-18856-2-git-send-email-will.deacon@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-08-06 17:54:37 +01:00
|
|
|
/* 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 */
|
|
|
|
|
|
2015-09-30 13:03:11 -07:00
|
|
|
/* 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 */
|
|
|
|
|
|
locking/atomic: Implement atomic{,64,_long}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
Now that all the architectures have implemented support for these new
atomic primitives add on the generic infrastructure to expose and use
it.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Frederic Weisbecker <fweisbec@gmail.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: Will Deacon <will.deacon@arm.com>
Cc: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-04-18 00:54:38 +02:00
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
|
|
2016-06-28 14:56:51 -07:00
|
|
|
/* 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 */
|
|
|
|
|
|
locking/atomic: Implement atomic{,64,_long}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
Now that all the architectures have implemented support for these new
atomic primitives add on the generic infrastructure to expose and use
it.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Frederic Weisbecker <fweisbec@gmail.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: Will Deacon <will.deacon@arm.com>
Cc: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-04-18 00:54:38 +02:00
|
|
|
/* 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 */
|
|
|
|
|
|
2016-06-28 14:56:51 -07:00
|
|
|
/* 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 */
|
|
|
|
|
|
locking/atomic: Implement atomic{,64,_long}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
Now that all the architectures have implemented support for these new
atomic primitives add on the generic infrastructure to expose and use
it.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Frederic Weisbecker <fweisbec@gmail.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: Will Deacon <will.deacon@arm.com>
Cc: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-04-18 00:54:38 +02:00
|
|
|
/* 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 */
|
|
|
|
|
|
|
|
|
|
|
locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations
Whilst porting the generic qrwlock code over to arm64, it became
apparent that any portable locking code needs finer-grained control of
the memory-ordering guarantees provided by our atomic routines.
In particular: xchg, cmpxchg, {add,sub}_return are often used in
situations where full barrier semantics (currently the only option
available) are not required. For example, when a reader increments a
reader count to obtain a lock, checking the old value to see if a writer
was present, only acquire semantics are strictly needed.
This patch introduces three new ordering semantics for these operations:
- *_relaxed: No ordering guarantees. This is similar to what we have
already for the non-return atomics (e.g. atomic_add).
- *_acquire: ACQUIRE semantics, similar to smp_load_acquire.
- *_release: RELEASE semantics, similar to smp_store_release.
In memory-ordering speak, this means that the acquire/release semantics
are RCpc as opposed to RCsc. Consequently a RELEASE followed by an
ACQUIRE does not imply a full barrier, as already documented in
memory-barriers.txt.
Currently, all the new macros are conditionally mapped to the full-mb
variants, however if the *_relaxed version is provided by the
architecture, then the acquire/release variants are constructed by
supplementing the relaxed routine with an explicit barrier.
Signed-off-by: Will Deacon <will.deacon@arm.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>
Cc: Waiman.Long@hp.com
Cc: paulmck@linux.vnet.ibm.com
Link: http://lkml.kernel.org/r/1438880084-18856-2-git-send-email-will.deacon@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-08-06 17:54:37 +01:00
|
|
|
/* 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 */
|
|
|
|
|
|
BACKPORT: locking/refcount: Create unchecked atomic_t implementation
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>
2017-02-10 16:27:52 +01:00
|
|
|
#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 */
|
|
|
|
|
|
locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations
Whilst porting the generic qrwlock code over to arm64, it became
apparent that any portable locking code needs finer-grained control of
the memory-ordering guarantees provided by our atomic routines.
In particular: xchg, cmpxchg, {add,sub}_return are often used in
situations where full barrier semantics (currently the only option
available) are not required. For example, when a reader increments a
reader count to obtain a lock, checking the old value to see if a writer
was present, only acquire semantics are strictly needed.
This patch introduces three new ordering semantics for these operations:
- *_relaxed: No ordering guarantees. This is similar to what we have
already for the non-return atomics (e.g. atomic_add).
- *_acquire: ACQUIRE semantics, similar to smp_load_acquire.
- *_release: RELEASE semantics, similar to smp_store_release.
In memory-ordering speak, this means that the acquire/release semantics
are RCpc as opposed to RCsc. Consequently a RELEASE followed by an
ACQUIRE does not imply a full barrier, as already documented in
memory-barriers.txt.
Currently, all the new macros are conditionally mapped to the full-mb
variants, however if the *_relaxed version is provided by the
architecture, then the acquire/release variants are constructed by
supplementing the relaxed routine with an explicit barrier.
Signed-off-by: Will Deacon <will.deacon@arm.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>
Cc: Waiman.Long@hp.com
Cc: paulmck@linux.vnet.ibm.com
Link: http://lkml.kernel.org/r/1438880084-18856-2-git-send-email-will.deacon@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-08-06 17:54:37 +01:00
|
|
|
/* 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 */
|
2010-11-11 14:05:08 -08:00
|
|
|
|
2018-06-21 13:13:09 +01:00
|
|
|
/**
|
|
|
|
|
* atomic_fetch_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, if @v was not already @u.
|
|
|
|
|
* Returns the original value of @v.
|
|
|
|
|
*/
|
|
|
|
|
#ifndef atomic_fetch_add_unless
|
|
|
|
|
static inline int atomic_fetch_add_unless(atomic_t *v, int a, int u)
|
|
|
|
|
{
|
|
|
|
|
int c = atomic_read(v);
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
if (unlikely(c == u))
|
|
|
|
|
break;
|
|
|
|
|
} while (!atomic_try_cmpxchg(v, &c, c + a));
|
|
|
|
|
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-07-26 16:09:07 -07:00
|
|
|
/**
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
2018-06-21 13:13:07 +01:00
|
|
|
* Atomically adds @a to @v, if @v was not already @u.
|
|
|
|
|
* Returns true if the addition was done.
|
2011-07-26 16:09:07 -07:00
|
|
|
*/
|
2018-06-21 13:13:07 +01:00
|
|
|
static inline bool atomic_add_unless(atomic_t *v, int a, int u)
|
2011-07-26 16:09:07 -07:00
|
|
|
{
|
BACKPORT: atomics/treewide: Rename __atomic_add_unless() => atomic_fetch_add_unless()
While __atomic_add_unless() was originally intended as a building-block
for atomic_add_unless(), it's now used in a number of places around the
kernel. It's the only common atomic operation named __atomic*(), rather
than atomic_*(), and for consistency it would be better named
atomic_fetch_add_unless().
This lack of consistency is slightly confusing, and gets in the way of
scripting atomics. Given that, let's clean things up and promote it to
an official part of the atomics API, in the form of
atomic_fetch_add_unless().
This patch converts definitions and invocations over to the new name,
including the instrumented version, using the following script:
----
git grep -w __atomic_add_unless | while read line; do
sed -i '{s/\<__atomic_add_unless\>/atomic_fetch_add_unless/}' "${line%%:*}";
done
git grep -w __arch_atomic_add_unless | while read line; do
sed -i '{s/\<__arch_atomic_add_unless\>/arch_atomic_fetch_add_unless/}' "${line%%:*}";
done
----
Note that we do not have atomic{64,_long}_fetch_add_unless(), which will
be introduced by later patches.
There should be no functional change as a result of this patch.
Change-Id: I3b917f02eac8e872d4b26d84299d1c351ca95315
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Will Deacon <will.deacon@arm.com>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Palmer Dabbelt <palmer@sifive.com>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/lkml/20180621121321.4761-2-mark.rutland@arm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Sorayukii <sorayukii69@gmail.com>
2018-06-21 13:13:04 +01:00
|
|
|
return atomic_fetch_add_unless(v, a, u) != u;
|
2011-07-26 16:09:07 -07:00
|
|
|
}
|
|
|
|
|
|
2011-07-26 16:09:06 -07:00
|
|
|
/**
|
|
|
|
|
* atomic_inc_not_zero - increment unless the number is zero
|
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
|
*
|
2018-06-21 13:13:07 +01:00
|
|
|
* Atomically increments @v by 1, if @v is non-zero.
|
|
|
|
|
* Returns true if the increment was done.
|
2011-07-26 16:09:06 -07:00
|
|
|
*/
|
2012-02-29 21:09:53 +00:00
|
|
|
#ifndef atomic_inc_not_zero
|
2011-07-26 16:09:06 -07:00
|
|
|
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
|
2012-02-29 21:09:53 +00:00
|
|
|
#endif
|
2011-07-26 16:09:06 -07:00
|
|
|
|
2015-04-24 01:12:32 +02:00
|
|
|
#ifndef atomic_andnot
|
|
|
|
|
static inline void atomic_andnot(int i, atomic_t *v)
|
|
|
|
|
{
|
|
|
|
|
atomic_and(~i, v);
|
|
|
|
|
}
|
locking/atomic: Implement atomic{,64,_long}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
Now that all the architectures have implemented support for these new
atomic primitives add on the generic infrastructure to expose and use
it.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Frederic Weisbecker <fweisbec@gmail.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: Will Deacon <will.deacon@arm.com>
Cc: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-04-18 00:54:38 +02:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2015-04-24 01:12:32 +02:00
|
|
|
#endif
|
|
|
|
|
|
2010-11-11 14:05:08 -08:00
|
|
|
/**
|
|
|
|
|
* 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
|
|
|
|
|
|
2011-06-20 10:52:57 -04:00
|
|
|
#ifndef atomic_inc_unless_negative
|
2018-06-21 13:13:07 +01:00
|
|
|
static inline bool atomic_inc_unless_negative(atomic_t *p)
|
2011-06-20 10:52:57 -04:00
|
|
|
{
|
|
|
|
|
int v, v1;
|
|
|
|
|
for (v = 0; v >= 0; v = v1) {
|
|
|
|
|
v1 = atomic_cmpxchg(p, v, v + 1);
|
|
|
|
|
if (likely(v1 == v))
|
2018-06-21 13:13:07 +01:00
|
|
|
return true;
|
2011-06-20 10:52:57 -04:00
|
|
|
}
|
2018-06-21 13:13:07 +01:00
|
|
|
return false;
|
2011-06-20 10:52:57 -04:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef atomic_dec_unless_positive
|
2018-06-21 13:13:07 +01:00
|
|
|
static inline bool atomic_dec_unless_positive(atomic_t *p)
|
2011-06-20 10:52:57 -04:00
|
|
|
{
|
|
|
|
|
int v, v1;
|
|
|
|
|
for (v = 0; v <= 0; v = v1) {
|
|
|
|
|
v1 = atomic_cmpxchg(p, v, v - 1);
|
|
|
|
|
if (likely(v1 == v))
|
2018-06-21 13:13:07 +01:00
|
|
|
return true;
|
2011-06-20 10:52:57 -04:00
|
|
|
}
|
2018-06-21 13:13:07 +01:00
|
|
|
return false;
|
2011-06-20 10:52:57 -04:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-10-08 16:32:18 -07:00
|
|
|
/*
|
|
|
|
|
* 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
|
|
|
|
|
|
2018-04-26 11:34:15 +01:00
|
|
|
#define atomic_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c))
|
2017-10-12 13:20:48 +01:00
|
|
|
#define atomic_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
|
|
|
|
|
|
2018-04-26 11:34:15 +01:00
|
|
|
#define atomic_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c))
|
2017-10-12 13:20:48 +01:00
|
|
|
#define atomic_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
|
|
|
|
|
|
2011-07-26 16:09:08 -07:00
|
|
|
#ifdef CONFIG_GENERIC_ATOMIC64
|
|
|
|
|
#include <asm-generic/atomic64.h>
|
|
|
|
|
#endif
|
2015-04-24 01:12:32 +02:00
|
|
|
|
2016-04-18 00:52:13 +02:00
|
|
|
#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 */
|
|
|
|
|
|
locking/atomic: Implement atomic{,64,_long}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
Now that all the architectures have implemented support for these new
atomic primitives add on the generic infrastructure to expose and use
it.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Frederic Weisbecker <fweisbec@gmail.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: Will Deacon <will.deacon@arm.com>
Cc: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-04-18 00:54:38 +02:00
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
|
|
2016-06-28 14:56:51 -07:00
|
|
|
/* 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 */
|
|
|
|
|
|
locking/atomic: Implement atomic{,64,_long}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
Now that all the architectures have implemented support for these new
atomic primitives add on the generic infrastructure to expose and use
it.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Frederic Weisbecker <fweisbec@gmail.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: Will Deacon <will.deacon@arm.com>
Cc: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-04-18 00:54:38 +02:00
|
|
|
/* 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 */
|
|
|
|
|
|
2016-06-28 14:56:51 -07:00
|
|
|
/* 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 */
|
|
|
|
|
|
locking/atomic: Implement atomic{,64,_long}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
Now that all the architectures have implemented support for these new
atomic primitives add on the generic infrastructure to expose and use
it.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Frederic Weisbecker <fweisbec@gmail.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: Will Deacon <will.deacon@arm.com>
Cc: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-04-18 00:54:38 +02:00
|
|
|
/* 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 */
|
|
|
|
|
|
|
|
|
|
|
2016-04-18 00:52:13 +02:00
|
|
|
/* 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 */
|
|
|
|
|
|
BACKPORT: locking/refcount: Create unchecked atomic_t implementation
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>
2017-02-10 16:27:52 +01:00
|
|
|
#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 */
|
|
|
|
|
|
2018-06-21 13:13:17 +01:00
|
|
|
/**
|
|
|
|
|
* atomic64_fetch_add_unless - add unless the number is already a given value
|
|
|
|
|
* @v: pointer of type atomic64_t
|
|
|
|
|
* @a: the amount to add to v...
|
|
|
|
|
* @u: ...unless v is equal to u.
|
|
|
|
|
*
|
|
|
|
|
* Atomically adds @a to @v, if @v was not already @u.
|
|
|
|
|
* Returns the original value of @v.
|
|
|
|
|
*/
|
|
|
|
|
#ifndef atomic64_fetch_add_unless
|
|
|
|
|
static inline long long atomic64_fetch_add_unless(atomic64_t *v, long long a,
|
|
|
|
|
long long u)
|
|
|
|
|
{
|
|
|
|
|
long long c = atomic64_read(v);
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
if (unlikely(c == u))
|
|
|
|
|
break;
|
|
|
|
|
} while (!atomic64_try_cmpxchg(v, &c, c + a));
|
|
|
|
|
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-06-21 13:13:10 +01:00
|
|
|
/**
|
|
|
|
|
* atomic64_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, if @v was not already @u.
|
|
|
|
|
* Returns true if the addition was done.
|
|
|
|
|
*/
|
|
|
|
|
static inline bool atomic64_add_unless(atomic64_t *v, long long a, long long u)
|
|
|
|
|
{
|
|
|
|
|
return atomic64_fetch_add_unless(v, a, u) != u;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-21 13:13:08 +01:00
|
|
|
/**
|
|
|
|
|
* atomic64_inc_not_zero - increment unless the number is zero
|
|
|
|
|
* @v: pointer of type atomic64_t
|
|
|
|
|
*
|
|
|
|
|
* Atomically increments @v by 1, if @v is non-zero.
|
|
|
|
|
* Returns true if the increment was done.
|
|
|
|
|
*/
|
|
|
|
|
#ifndef atomic64_inc_not_zero
|
|
|
|
|
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-04-24 01:12:32 +02:00
|
|
|
#ifndef atomic64_andnot
|
|
|
|
|
static inline void atomic64_andnot(long long i, atomic64_t *v)
|
|
|
|
|
{
|
|
|
|
|
atomic64_and(~i, v);
|
|
|
|
|
}
|
locking/atomic: Implement atomic{,64,_long}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
Now that all the architectures have implemented support for these new
atomic primitives add on the generic infrastructure to expose and use
it.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Frederic Weisbecker <fweisbec@gmail.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: Will Deacon <will.deacon@arm.com>
Cc: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-04-18 00:54:38 +02:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2015-04-24 01:12:32 +02:00
|
|
|
#endif
|
|
|
|
|
|
2018-04-26 11:34:15 +01:00
|
|
|
#define atomic64_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c))
|
2017-10-12 13:20:48 +01:00
|
|
|
#define atomic64_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
|
|
|
|
|
|
2015-09-18 15:04:59 +02:00
|
|
|
#include <asm-generic/atomic-long.h>
|
|
|
|
|
|
2010-11-11 14:05:08 -08:00
|
|
|
#endif /* _LINUX_ATOMIC_H */
|