From fb041bb7c0a918b95c6889fc965cdc4a75b4c0ca Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 21 Nov 2019 11:59:00 +0000 Subject: locking/refcount: Consolidate implementations of refcount_t The generic implementation of refcount_t should be good enough for everybody, so remove ARCH_HAS_REFCOUNT and REFCOUNT_FULL entirely, leaving the generic implementation enabled unconditionally. Signed-off-by: Will Deacon Reviewed-by: Ard Biesheuvel Acked-by: Kees Cook Tested-by: Hanjun Guo Cc: Ard Biesheuvel Cc: Elena Reshetova Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: https://lkml.kernel.org/r/20191121115902.2551-9-will@kernel.org Signed-off-by: Ingo Molnar --- include/linux/refcount.h | 158 +++++++++++++++++------------------------------ 1 file changed, 58 insertions(+), 100 deletions(-) (limited to 'include/linux/refcount.h') diff --git a/include/linux/refcount.h b/include/linux/refcount.h index 757d4630115c..0ac50cf62d06 100644 --- a/include/linux/refcount.h +++ b/include/linux/refcount.h @@ -1,64 +1,4 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _LINUX_REFCOUNT_H -#define _LINUX_REFCOUNT_H - -#include -#include -#include -#include - -struct mutex; - -/** - * struct refcount_t - variant of atomic_t specialized for reference counts - * @refs: atomic_t counter field - * - * The counter saturates at REFCOUNT_SATURATED and will not move once - * there. This avoids wrapping the counter and causing 'spurious' - * use-after-free bugs. - */ -typedef struct refcount_struct { - atomic_t refs; -} refcount_t; - -#define REFCOUNT_INIT(n) { .refs = ATOMIC_INIT(n), } -#define REFCOUNT_MAX INT_MAX -#define REFCOUNT_SATURATED (INT_MIN / 2) - -enum refcount_saturation_type { - REFCOUNT_ADD_NOT_ZERO_OVF, - REFCOUNT_ADD_OVF, - REFCOUNT_ADD_UAF, - REFCOUNT_SUB_UAF, - REFCOUNT_DEC_LEAK, -}; - -void refcount_warn_saturate(refcount_t *r, enum refcount_saturation_type t); - -/** - * refcount_set - set a refcount's value - * @r: the refcount - * @n: value to which the refcount will be set - */ -static inline void refcount_set(refcount_t *r, int n) -{ - atomic_set(&r->refs, n); -} - -/** - * refcount_read - get a refcount's value - * @r: the refcount - * - * Return: the refcount's value - */ -static inline unsigned int refcount_read(const refcount_t *r) -{ - return atomic_read(&r->refs); -} - -#ifdef CONFIG_REFCOUNT_FULL -#include - /* * Variant of atomic_t specialized for reference counts. * @@ -136,6 +76,64 @@ static inline unsigned int refcount_read(const refcount_t *r) * */ +#ifndef _LINUX_REFCOUNT_H +#define _LINUX_REFCOUNT_H + +#include +#include +#include +#include +#include + +struct mutex; + +/** + * struct refcount_t - variant of atomic_t specialized for reference counts + * @refs: atomic_t counter field + * + * The counter saturates at REFCOUNT_SATURATED and will not move once + * there. This avoids wrapping the counter and causing 'spurious' + * use-after-free bugs. + */ +typedef struct refcount_struct { + atomic_t refs; +} refcount_t; + +#define REFCOUNT_INIT(n) { .refs = ATOMIC_INIT(n), } +#define REFCOUNT_MAX INT_MAX +#define REFCOUNT_SATURATED (INT_MIN / 2) + +enum refcount_saturation_type { + REFCOUNT_ADD_NOT_ZERO_OVF, + REFCOUNT_ADD_OVF, + REFCOUNT_ADD_UAF, + REFCOUNT_SUB_UAF, + REFCOUNT_DEC_LEAK, +}; + +void refcount_warn_saturate(refcount_t *r, enum refcount_saturation_type t); + +/** + * refcount_set - set a refcount's value + * @r: the refcount + * @n: value to which the refcount will be set + */ +static inline void refcount_set(refcount_t *r, int n) +{ + atomic_set(&r->refs, n); +} + +/** + * refcount_read - get a refcount's value + * @r: the refcount + * + * Return: the refcount's value + */ +static inline unsigned int refcount_read(const refcount_t *r) +{ + return atomic_read(&r->refs); +} + /** * refcount_add_not_zero - add a value to a refcount unless it is 0 * @i: the value to add to the refcount @@ -298,46 +296,6 @@ static inline void refcount_dec(refcount_t *r) if (unlikely(atomic_fetch_sub_release(1, &r->refs) <= 1)) refcount_warn_saturate(r, REFCOUNT_DEC_LEAK); } -#else /* CONFIG_REFCOUNT_FULL */ -# ifdef CONFIG_ARCH_HAS_REFCOUNT -# include -# else -static inline __must_check bool refcount_add_not_zero(int i, refcount_t *r) -{ - return atomic_add_unless(&r->refs, i, 0); -} - -static inline void refcount_add(int i, refcount_t *r) -{ - atomic_add(i, &r->refs); -} - -static inline __must_check bool refcount_inc_not_zero(refcount_t *r) -{ - return atomic_add_unless(&r->refs, 1, 0); -} - -static inline void refcount_inc(refcount_t *r) -{ - atomic_inc(&r->refs); -} - -static inline __must_check bool refcount_sub_and_test(int i, refcount_t *r) -{ - return atomic_sub_and_test(i, &r->refs); -} - -static inline __must_check bool refcount_dec_and_test(refcount_t *r) -{ - return atomic_dec_and_test(&r->refs); -} - -static inline void refcount_dec(refcount_t *r) -{ - atomic_dec(&r->refs); -} -# endif /* !CONFIG_ARCH_HAS_REFCOUNT */ -#endif /* !CONFIG_REFCOUNT_FULL */ extern __must_check bool refcount_dec_if_one(refcount_t *r); extern __must_check bool refcount_dec_not_one(refcount_t *r); -- cgit