From 84d0c4d7eca5a558115f6417889459d676c3ebec Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Sat, 28 Oct 2023 05:36:15 +0000 Subject: [PATCH] Add atomic_dec_not_last_64 Signed-off-by: Mateusz Guzik --- include/os/freebsd/spl/sys/atomic.h | 17 +++++++++++++++++ include/os/linux/spl/sys/atomic.h | 1 + lib/libspl/atomic.c | 18 ++++++++++++++++++ lib/libspl/include/atomic.h | 1 + 4 files changed, 37 insertions(+) diff --git a/include/os/freebsd/spl/sys/atomic.h b/include/os/freebsd/spl/sys/atomic.h index 40a67704fd..2dbb372ca2 100644 --- a/include/os/freebsd/spl/sys/atomic.h +++ b/include/os/freebsd/spl/sys/atomic.h @@ -149,6 +149,23 @@ atomic_cas_64(volatile uint64_t *target, uint64_t cmp, uint64_t newval) #endif #endif +static inline int +atomic_dec_not_last_64(volatile uint64_t *target) +{ + uint64_t val, oldval; + + val = *target; + for (;;) { + if (val <= 1) { + return (0); + } + oldval = atomic_cas_64(target, val, val - 1); + if (oldval == val) + return (1); + val = oldval; + } +} + static __inline void atomic_inc_64(volatile uint64_t *target) { diff --git a/include/os/linux/spl/sys/atomic.h b/include/os/linux/spl/sys/atomic.h index 8f7fa5aeda..141ea94841 100644 --- a/include/os/linux/spl/sys/atomic.h +++ b/include/os/linux/spl/sys/atomic.h @@ -62,6 +62,7 @@ #define atomic_swap_64(v, x) atomic64_xchg((atomic64_t *)(v), x) #define atomic_load_64(v) atomic64_read((atomic64_t *)(v)) #define atomic_store_64(v, x) atomic64_set((atomic64_t *)(v), x) +#define atomic_dec_not_last_64(v) atomic64_dec_if_positive((atomic64_t *)(v)) #ifdef _LP64 static __inline__ void * diff --git a/lib/libspl/atomic.c b/lib/libspl/atomic.c index 8cc350710b..a37feb25a2 100644 --- a/lib/libspl/atomic.c +++ b/lib/libspl/atomic.c @@ -62,6 +62,24 @@ ATOMIC_DEC(uchar, uchar_t) ATOMIC_DEC(ushort, ushort_t) ATOMIC_DEC(uint, uint_t) ATOMIC_DEC(ulong, ulong_t) + +int +atomic_dec_not_last_64(volatile uint64_t *target) +{ + uint64_t val, oldval; + + val = *target; + for (;;) { + if (val <= 1) { + return (0); + } + oldval = atomic_cas_64(target, val, val - 1); + if (oldval == val) + return (1); + val = oldval; + } +} + /* END CSTYLED */ diff --git a/lib/libspl/include/atomic.h b/lib/libspl/include/atomic.h index 4ebdbbda98..c234cecadc 100644 --- a/lib/libspl/include/atomic.h +++ b/lib/libspl/include/atomic.h @@ -155,6 +155,7 @@ extern uint_t atomic_dec_uint_nv(volatile uint_t *); extern ulong_t atomic_dec_ulong_nv(volatile ulong_t *); #if defined(_INT64_TYPE) extern uint64_t atomic_dec_64_nv(volatile uint64_t *); +extern int atomic_dec_not_last_64(volatile uint64_t *); #endif /*