public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: will@kernel.org, boqun.feng@gmail.com
Cc: linux-kernel@vger.kernel.org, x86@kernel.org,
	mark.rutland@arm.com, elver@google.com, keescook@chromium.org,
	hch@infradead.org, torvalds@linux-foundation.org,
	axboe@kernel.dk
Subject: [PATCH v2 10/9] atomic: Document the atomic_{}_overflow() functions
Date: Mon, 13 Dec 2021 13:15:36 +0100	[thread overview]
Message-ID: <Ybc5aMFodXvDkT4f@hirez.programming.kicks-ass.net> (raw)
In-Reply-To: <20211210161618.645249719@infradead.org>


They're damn special, they're very likely to confuse people, write a
few words in a vain attempt to twart some of that confusion.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 Documentation/atomic_t.txt                     |   36 +++++++++++++++++
 include/linux/atomic/atomic-arch-fallback.h    |   52 ++++++++++++++++++++++++-
 scripts/atomic/fallbacks/dec_and_test_overflow |   10 ++++
 scripts/atomic/fallbacks/dec_overflow          |    9 ++++
 scripts/atomic/fallbacks/inc_overflow          |    9 ++++
 5 files changed, 115 insertions(+), 1 deletion(-)

--- a/Documentation/atomic_t.txt
+++ b/Documentation/atomic_t.txt
@@ -45,6 +45,14 @@ The 'full' API consists of (atomic64_ an
   atomic_sub_and_test(), atomic_dec_and_test()
 
 
+Reference count with overflow (as used by refcount_t):
+
+  atomic_inc_overflow(), atomic_dec_overflow()
+  atomic_dec_and_test_overflow()
+
+  ATOMIC_OVERFLOW_OFFSET
+
+
 Misc:
 
   atomic_inc_and_test(), atomic_add_negative()
@@ -157,6 +165,34 @@ atomic variable) can be fully ordered an
 visible.
 
 
+Overflow ops:
+
+The atomic_{}_overflow() ops are similar to their !_overflow() bretheren with
+two notable exceptions:
+
+ - they take a label as their final argument to to jump to when the atomic op
+   overflows;
+
+ - the actual value can be offset from 0 in order to allow architectures
+   to play games with condition flags in order to generate better code. This
+   offset is ATOMIC_OVERFLOW_OFFSET.
+
+The canonical overflow conditions are (ATOMIC_OVERFLOW_OFFSET == 0):
+
+  inc: zero or negative on the value pre increment
+  dec: zero or negative on the value post decrement
+  dec_and_test: negative on the value post decrement
+
+This gives an effective range of [0, INT_MIN] for the actual value. When an
+architecture uses ATOMIC_OVERFLOW_OFFSET == 1 (x86), the effective range
+becomes [-1, INT_MIN], or [0, INT_MIN+1] after correction.
+
+These semantics match the reference count use-case (for which they were
+created). Specifically incrementing from zero is a failure because zero means
+the object is freed (IOW use-after-free). Decrementing to zero is a failure
+because it goes undetected (see dec_and_test) and the object would leak.
+
+
 ORDERING  (go read memory-barriers.txt first)
 --------
 
--- a/include/linux/atomic/atomic-arch-fallback.h
+++ b/include/linux/atomic/atomic-arch-fallback.h
@@ -1251,6 +1251,14 @@ arch_atomic_dec_if_positive(atomic_t *v)
 #endif
 
 #ifndef arch_atomic_inc_overflow
+/**
+ * arch_atomic_inc_overflow - increment with overflow exception
+ * @_v: pointer of type atomic_t
+ * @_label: label to goto on overflow
+ *
+ * Atomically increments @_v and goto @_label when the old
+ * value (+ATOMIC_OVERFLOW_OFFSET) is negative.
+ */
 #define arch_atomic_inc_overflow(_v, _label)				\
 do {									\
 	int __old = arch_atomic_fetch_inc(_v);			\
@@ -1260,6 +1268,14 @@ do {									\
 #endif
 
 #ifndef arch_atomic_dec_overflow
+/**
+ * arch_atomic_dec_overflow - decrement with overflow exception
+ * @_v: pointer of type atomic_t
+ * @_label: label to goto on overflow
+ *
+ * Atomically decrements @_v and goto @_label when the
+ * result (+ATOMIC_OVERFLOW_OFFSET) is negative.
+ */
 #define arch_atomic_dec_overflow(_v, _label)				\
 do {									\
 	int __new = arch_atomic_dec_return(_v);			\
@@ -1269,6 +1285,15 @@ do {									\
 #endif
 
 #ifndef arch_atomic_dec_and_test_overflow
+/**
+ * arch_atomic_dec_and_test_overflow - decrement and test if zero with overflow exception
+ * @_v: pointer of type atomic_t
+ * @_label: label to goto on overflow
+ *
+ * Atomically decrements @_v and returns true if the result
+ * (+ATOMIC_OVERFLOW_OFFSET) is zero or goto @_label when the
+ * result (+ATOMIC_OVERFLOW_OFFSET) is negative.
+ */
 #define arch_atomic_dec_and_test_overflow(_v, _label)		\
 ({									\
 	bool __ret = false;						\
@@ -2389,6 +2414,14 @@ arch_atomic64_dec_if_positive(atomic64_t
 #endif
 
 #ifndef arch_atomic64_inc_overflow
+/**
+ * arch_atomic64_inc_overflow - increment with overflow exception
+ * @_v: pointer of type atomic64_t
+ * @_label: label to goto on overflow
+ *
+ * Atomically increments @_v and goto @_label when the old
+ * value (+ATOMIC64_OVERFLOW_OFFSET) is negative.
+ */
 #define arch_atomic64_inc_overflow(_v, _label)				\
 do {									\
 	s64 __old = arch_atomic64_fetch_inc(_v);			\
@@ -2398,6 +2431,14 @@ do {									\
 #endif
 
 #ifndef arch_atomic64_dec_overflow
+/**
+ * arch_atomic64_dec_overflow - decrement with overflow exception
+ * @_v: pointer of type atomic64_t
+ * @_label: label to goto on overflow
+ *
+ * Atomically decrements @_v and goto @_label when the
+ * result (+ATOMIC64_OVERFLOW_OFFSET) is negative.
+ */
 #define arch_atomic64_dec_overflow(_v, _label)				\
 do {									\
 	s64 __new = arch_atomic64_dec_return(_v);			\
@@ -2407,6 +2448,15 @@ do {									\
 #endif
 
 #ifndef arch_atomic64_dec_and_test_overflow
+/**
+ * arch_atomic64_dec_and_test_overflow - decrement and test if zero with overflow exception
+ * @_v: pointer of type atomic64_t
+ * @_label: label to goto on overflow
+ *
+ * Atomically decrements @_v and returns true if the result
+ * (+ATOMIC64_OVERFLOW_OFFSET) is zero or goto @_label when the
+ * result (+ATOMIC64_OVERFLOW_OFFSET) is negative.
+ */
 #define arch_atomic64_dec_and_test_overflow(_v, _label)		\
 ({									\
 	bool __ret = false;						\
@@ -2420,4 +2470,4 @@ do {									\
 #endif
 
 #endif /* _LINUX_ATOMIC_FALLBACK_H */
-// e4c677b23b3fd5e8dc4bce9d6c055103666cfc4a
+// ccccab23ad71e0523949b969f68b40fe6812fc15
--- a/scripts/atomic/fallbacks/dec_and_test_overflow
+++ b/scripts/atomic/fallbacks/dec_and_test_overflow
@@ -1,4 +1,14 @@
+ATOMIC=`echo ${atomic} | tr '[:lower:]' '[:upper:]'`
 cat << EOF
+/**
+ * arch_${atomic}_dec_and_test_overflow - decrement and test if zero with overflow exception
+ * @_v: pointer of type ${atomic}_t
+ * @_label: label to goto on overflow
+ *
+ * Atomically decrements @_v and returns true if the result
+ * (+${ATOMIC}_OVERFLOW_OFFSET) is zero or goto @_label when the
+ * result (+${ATOMIC}_OVERFLOW_OFFSET) is negative.
+ */
 #define arch_${atomic}_dec_and_test_overflow(_v, _label)		\\
 ({									\\
 	bool __ret = false;						\\
--- a/scripts/atomic/fallbacks/dec_overflow
+++ b/scripts/atomic/fallbacks/dec_overflow
@@ -1,4 +1,13 @@
+ATOMIC=`echo ${atomic} | tr '[:lower:]' '[:upper:]'`
 cat << EOF
+/**
+ * arch_${atomic}_dec_overflow - decrement with overflow exception
+ * @_v: pointer of type ${atomic}_t
+ * @_label: label to goto on overflow
+ *
+ * Atomically decrements @_v and goto @_label when the
+ * result (+${ATOMIC}_OVERFLOW_OFFSET) is negative.
+ */
 #define arch_${atomic}_dec_overflow(_v, _label)				\\
 do {									\\
 	${int} __new = arch_${atomic}_dec_return(_v);			\\
--- a/scripts/atomic/fallbacks/inc_overflow
+++ b/scripts/atomic/fallbacks/inc_overflow
@@ -1,4 +1,13 @@
+ATOMIC=`echo ${atomic} | tr '[:lower:]' '[:upper:]'`
 cat << EOF
+/**
+ * arch_${atomic}_inc_overflow - increment with overflow exception
+ * @_v: pointer of type ${atomic}_t
+ * @_label: label to goto on overflow
+ *
+ * Atomically increments @_v and goto @_label when the old
+ * value (+${ATOMIC}_OVERFLOW_OFFSET) is negative.
+ */
 #define arch_${atomic}_inc_overflow(_v, _label)				\\
 do {									\\
 	${int} __old = arch_${atomic}_fetch_inc(_v);			\\

  parent reply	other threads:[~2021-12-13 12:16 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-10 16:16 [PATCH v2 0/9] refcount: Improve code-gen Peter Zijlstra
2021-12-10 16:16 ` [PATCH v2 1/9] atomic: Prepare scripts for macro ops Peter Zijlstra
2021-12-10 17:27   ` Mark Rutland
2021-12-10 17:43   ` Marco Elver
2021-12-10 16:16 ` [PATCH v2 2/9] atomic: Add xchg.tbl Peter Zijlstra
2021-12-13  9:50   ` Mark Rutland
2021-12-10 16:16 ` [PATCH v2 3/9] atomic: Introduce atomic_{inc,dec,dec_and_test}_overflow() Peter Zijlstra
2021-12-13 10:06   ` Mark Rutland
2021-12-13 10:57     ` Peter Zijlstra
2021-12-13 10:59     ` Peter Zijlstra
2021-12-13 11:09       ` Mark Rutland
2021-12-10 16:16 ` [PATCH v2 4/9] refcount: Use atomic_*_overflow() Peter Zijlstra
2021-12-13 10:35   ` Mark Rutland
2021-12-10 16:16 ` [PATCH v2 5/9] atomic,x86: Implement atomic_dec_and_test_overflow() Peter Zijlstra
2021-12-13 11:04   ` Mark Rutland
2021-12-10 16:16 ` [PATCH v2 6/9] refcount: Fix refcount_dec_not_one() Peter Zijlstra
2021-12-10 16:16 ` [PATCH v2 7/9] refcount: Prepare for atomic_*_overflow() offsets Peter Zijlstra
2021-12-10 16:16 ` [PATCH v2 8/9] atomic,x86: Alternative atomic_*_overflow() scheme Peter Zijlstra
2021-12-10 16:53   ` Linus Torvalds
2021-12-10 17:27     ` Linus Torvalds
2021-12-17  3:38     ` Herbert Xu
2021-12-13 16:43   ` Peter Zijlstra
2021-12-13 17:29     ` Marco Elver
2021-12-13 18:11     ` Linus Torvalds
2021-12-13 18:18       ` Marco Elver
2021-12-13 18:24         ` Linus Torvalds
2021-12-13 19:35           ` Marco Elver
2021-12-13 18:21       ` Linus Torvalds
2021-12-10 16:16 ` [PATCH v2 9/9] refcount: Optimize __refcount_add_not_zero(.i=1) Peter Zijlstra
2021-12-10 19:37 ` [PATCH v2 0/9] refcount: Improve code-gen Peter Zijlstra
2021-12-13 12:15 ` Peter Zijlstra [this message]
2021-12-13 12:20 ` Peter Zijlstra
2021-12-13 14:42   ` Marco Elver
2021-12-13 16:11     ` Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Ybc5aMFodXvDkT4f@hirez.programming.kicks-ass.net \
    --to=peterz@infradead.org \
    --cc=axboe@kernel.dk \
    --cc=boqun.feng@gmail.com \
    --cc=elver@google.com \
    --cc=hch@infradead.org \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=torvalds@linux-foundation.org \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox