aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Sébastien Pédron <dumbbell@FreeBSD.org>2023-01-15 14:56:48 +0000
committerJean-Sébastien Pédron <dumbbell@FreeBSD.org>2023-02-16 11:55:13 +0000
commitb2bea8bf56a8f8de612b6fdb0d14fdebe4414af6 (patch)
tree1d6fdc1c8204d325eba566ce5b57f201ef2ac24b
parentcc32cc0f8e965b5c3d0a7ac6595ae97997a76d1b (diff)
downloadsrc-b2bea8bf56a8f8de612b6fdb0d14fdebe4414af6.tar.gz
src-b2bea8bf56a8f8de612b6fdb0d14fdebe4414af6.zip
linuxkpi: Fix `atomic_long_sub()` overflow
By (ab)using `atomic_long_add_return()`, `atomic_long_sub()` was making the atomic long overflow. Indeed the underlying FreeBSD atomic is based on an unsigned long. Reviewed by: manu Approved by: manu Differential Revision: https://reviews.freebsd.org/D38090 (cherry picked from commit 9491ea7c68221ca7bc5e369ebb57660886ef1b13)
-rw-r--r--sys/compat/linuxkpi/common/include/asm/atomic-long.h8
1 files changed, 7 insertions, 1 deletions
diff --git a/sys/compat/linuxkpi/common/include/asm/atomic-long.h b/sys/compat/linuxkpi/common/include/asm/atomic-long.h
index f8bd9edfccf9..aeec6edd707d 100644
--- a/sys/compat/linuxkpi/common/include/asm/atomic-long.h
+++ b/sys/compat/linuxkpi/common/include/asm/atomic-long.h
@@ -41,7 +41,7 @@ typedef struct {
} atomic_long_t;
#define atomic_long_add(i, v) atomic_long_add_return((i), (v))
-#define atomic_long_sub(i, v) atomic_long_add_return(-(i), (v))
+#define atomic_long_sub(i, v) atomic_long_sub_return((i), (v))
#define atomic_long_inc_return(v) atomic_long_add_return(1, (v))
#define atomic_long_inc_not_zero(v) atomic_long_add_unless((v), 1, 0)
@@ -51,6 +51,12 @@ atomic_long_add_return(long i, atomic_long_t *v)
return i + atomic_fetchadd_long(&v->counter, i);
}
+static inline long
+atomic_long_sub_return(long i, atomic_long_t *v)
+{
+ return atomic_fetchadd_long(&v->counter, -i) - i;
+}
+
static inline void
atomic_long_set(atomic_long_t *v, long i)
{