All of lore.kernel.org
 help / color / mirror / Atom feed
From: Will Deacon <will.deacon@arm.com>
To: linux-kernel@vger.kernel.org
Cc: peterz@infradead.org, mingo@kernel.org,
	linux-arm-kernel@lists.infradead.org,
	yamada.masahiro@socionext.com, Will Deacon <will.deacon@arm.com>
Subject: [RFC PATCH v2 10/12] asm-generic/bitops/lock.h: Rewrite using atomic_fetch_*
Date: Mon, 26 Feb 2018 15:04:58 +0000	[thread overview]
Message-ID: <1519657500-15094-11-git-send-email-will.deacon@arm.com> (raw)
In-Reply-To: <1519657500-15094-1-git-send-email-will.deacon@arm.com>

The lock bitops can be implemented more efficiently using the atomic_fetch_*
ops, which provide finer-grained control over the memory ordering semantics
than the bitops.

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 include/asm-generic/bitops/lock.h | 68 ++++++++++++++++++++++++++++++++-------
 1 file changed, 56 insertions(+), 12 deletions(-)

diff --git a/include/asm-generic/bitops/lock.h b/include/asm-generic/bitops/lock.h
index 67ab280ad134..3ae021368f48 100644
--- a/include/asm-generic/bitops/lock.h
+++ b/include/asm-generic/bitops/lock.h
@@ -2,6 +2,10 @@
 #ifndef _ASM_GENERIC_BITOPS_LOCK_H_
 #define _ASM_GENERIC_BITOPS_LOCK_H_
 
+#include <linux/atomic.h>
+#include <linux/compiler.h>
+#include <asm/barrier.h>
+
 /**
  * test_and_set_bit_lock - Set a bit and return its old value, for lock
  * @nr: Bit to set
@@ -11,7 +15,20 @@
  * the returned value is 0.
  * It can be used to implement bit locks.
  */
-#define test_and_set_bit_lock(nr, addr)	test_and_set_bit(nr, addr)
+static inline int test_and_set_bit_lock(unsigned int nr,
+					volatile unsigned long *p)
+{
+	long old;
+	unsigned long mask = BIT_MASK(nr);
+
+	p += BIT_WORD(nr);
+	if (READ_ONCE(*p) & mask)
+		return 1;
+
+	old = atomic_long_fetch_or_acquire(mask, (atomic_long_t *)p);
+	return !!(old & mask);
+}
+
 
 /**
  * clear_bit_unlock - Clear a bit in memory, for unlock
@@ -20,11 +37,11 @@
  *
  * This operation is atomic and provides release barrier semantics.
  */
-#define clear_bit_unlock(nr, addr)	\
-do {					\
-	smp_mb__before_atomic();	\
-	clear_bit(nr, addr);		\
-} while (0)
+static inline void clear_bit_unlock(unsigned int nr, volatile unsigned long *p)
+{
+	p += BIT_WORD(nr);
+	atomic_long_fetch_andnot_release(BIT_MASK(nr), (atomic_long_t *)p);
+}
 
 /**
  * __clear_bit_unlock - Clear a bit in memory, for unlock
@@ -37,11 +54,38 @@ do {					\
  *
  * See for example x86's implementation.
  */
-#define __clear_bit_unlock(nr, addr)	\
-do {					\
-	smp_mb__before_atomic();	\
-	clear_bit(nr, addr);		\
-} while (0)
+static inline void __clear_bit_unlock(unsigned int nr,
+				      volatile unsigned long *p)
+{
+	unsigned long old;
 
-#endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */
+	p += BIT_WORD(nr);
+	old = READ_ONCE(*p);
+	old &= ~BIT_MASK(nr);
+	atomic_long_set_release((atomic_long_t *)p, old);
+}
+
+/**
+ * clear_bit_unlock_is_negative_byte - Clear a bit in memory and test if bottom
+ *                                     byte is negative, for unlock.
+ * @nr: the bit to clear
+ * @addr: the address to start counting from
+ *
+ * This is a bit of a one-trick-pony for the filemap code, which clears
+ * PG_locked and tests PG_waiters,
+ */
+#ifndef clear_bit_unlock_is_negative_byte
+static inline bool clear_bit_unlock_is_negative_byte(unsigned int nr,
+						     volatile unsigned long *p)
+{
+	long old;
+	unsigned long mask = BIT_MASK(nr);
+
+	p += BIT_WORD(nr);
+	old = atomic_long_fetch_andnot_release(mask, (atomic_long_t *)p);
+	return !!(old & BIT(7));
+}
+#define clear_bit_unlock_is_negative_byte clear_bit_unlock_is_negative_byte
+#endif
 
+#endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */
-- 
2.1.4

WARNING: multiple messages have this Message-ID (diff)
From: will.deacon@arm.com (Will Deacon)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH v2 10/12] asm-generic/bitops/lock.h: Rewrite using atomic_fetch_*
Date: Mon, 26 Feb 2018 15:04:58 +0000	[thread overview]
Message-ID: <1519657500-15094-11-git-send-email-will.deacon@arm.com> (raw)
In-Reply-To: <1519657500-15094-1-git-send-email-will.deacon@arm.com>

The lock bitops can be implemented more efficiently using the atomic_fetch_*
ops, which provide finer-grained control over the memory ordering semantics
than the bitops.

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 include/asm-generic/bitops/lock.h | 68 ++++++++++++++++++++++++++++++++-------
 1 file changed, 56 insertions(+), 12 deletions(-)

diff --git a/include/asm-generic/bitops/lock.h b/include/asm-generic/bitops/lock.h
index 67ab280ad134..3ae021368f48 100644
--- a/include/asm-generic/bitops/lock.h
+++ b/include/asm-generic/bitops/lock.h
@@ -2,6 +2,10 @@
 #ifndef _ASM_GENERIC_BITOPS_LOCK_H_
 #define _ASM_GENERIC_BITOPS_LOCK_H_
 
+#include <linux/atomic.h>
+#include <linux/compiler.h>
+#include <asm/barrier.h>
+
 /**
  * test_and_set_bit_lock - Set a bit and return its old value, for lock
  * @nr: Bit to set
@@ -11,7 +15,20 @@
  * the returned value is 0.
  * It can be used to implement bit locks.
  */
-#define test_and_set_bit_lock(nr, addr)	test_and_set_bit(nr, addr)
+static inline int test_and_set_bit_lock(unsigned int nr,
+					volatile unsigned long *p)
+{
+	long old;
+	unsigned long mask = BIT_MASK(nr);
+
+	p += BIT_WORD(nr);
+	if (READ_ONCE(*p) & mask)
+		return 1;
+
+	old = atomic_long_fetch_or_acquire(mask, (atomic_long_t *)p);
+	return !!(old & mask);
+}
+
 
 /**
  * clear_bit_unlock - Clear a bit in memory, for unlock
@@ -20,11 +37,11 @@
  *
  * This operation is atomic and provides release barrier semantics.
  */
-#define clear_bit_unlock(nr, addr)	\
-do {					\
-	smp_mb__before_atomic();	\
-	clear_bit(nr, addr);		\
-} while (0)
+static inline void clear_bit_unlock(unsigned int nr, volatile unsigned long *p)
+{
+	p += BIT_WORD(nr);
+	atomic_long_fetch_andnot_release(BIT_MASK(nr), (atomic_long_t *)p);
+}
 
 /**
  * __clear_bit_unlock - Clear a bit in memory, for unlock
@@ -37,11 +54,38 @@ do {					\
  *
  * See for example x86's implementation.
  */
-#define __clear_bit_unlock(nr, addr)	\
-do {					\
-	smp_mb__before_atomic();	\
-	clear_bit(nr, addr);		\
-} while (0)
+static inline void __clear_bit_unlock(unsigned int nr,
+				      volatile unsigned long *p)
+{
+	unsigned long old;
 
-#endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */
+	p += BIT_WORD(nr);
+	old = READ_ONCE(*p);
+	old &= ~BIT_MASK(nr);
+	atomic_long_set_release((atomic_long_t *)p, old);
+}
+
+/**
+ * clear_bit_unlock_is_negative_byte - Clear a bit in memory and test if bottom
+ *                                     byte is negative, for unlock.
+ * @nr: the bit to clear
+ * @addr: the address to start counting from
+ *
+ * This is a bit of a one-trick-pony for the filemap code, which clears
+ * PG_locked and tests PG_waiters,
+ */
+#ifndef clear_bit_unlock_is_negative_byte
+static inline bool clear_bit_unlock_is_negative_byte(unsigned int nr,
+						     volatile unsigned long *p)
+{
+	long old;
+	unsigned long mask = BIT_MASK(nr);
+
+	p += BIT_WORD(nr);
+	old = atomic_long_fetch_andnot_release(mask, (atomic_long_t *)p);
+	return !!(old & BIT(7));
+}
+#define clear_bit_unlock_is_negative_byte clear_bit_unlock_is_negative_byte
+#endif
 
+#endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */
-- 
2.1.4

  parent reply	other threads:[~2018-02-26 15:06 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-26 15:04 [RFC PATCH v2 00/12] Rewrite asm-generic/bitops/{atomic,lock}.h and use on arm64 Will Deacon
2018-02-26 15:04 ` [RFC PATCH v2 00/12] Rewrite asm-generic/bitops/{atomic, lock}.h " Will Deacon
2018-02-26 15:04 ` [RFC PATCH v2 01/12] h8300: Don't include linux/kernel.h in asm/atomic.h Will Deacon
2018-02-26 15:04   ` Will Deacon
2018-02-26 15:04 ` [RFC PATCH v2 02/12] m68k: Don't use asm-generic/bitops/lock.h Will Deacon
2018-02-26 15:04   ` Will Deacon
2018-02-26 15:04 ` [RFC PATCH v2 03/12] asm-generic: Move some macros from linux/bitops.h to a new bits.h file Will Deacon
2018-02-26 15:04   ` Will Deacon
2018-02-26 15:04 ` [RFC PATCH v2 04/12] openrisc: Don't pull in all of linux/bitops.h in asm/cmpxchg.h Will Deacon
2018-02-26 15:04   ` Will Deacon
2018-02-26 15:04 ` [RFC PATCH v2 05/12] sh: Don't pull in all of linux/bitops.h in asm/cmpxchg-xchg.h Will Deacon
2018-02-26 15:04   ` Will Deacon
2018-02-26 15:04 ` [RFC PATCH v2 06/12] arm64: fpsimd: include <linux/init.h> in fpsimd.h Will Deacon
2018-02-26 15:04   ` Will Deacon
2018-02-26 15:37   ` Mark Rutland
2018-02-26 15:37     ` Mark Rutland
2018-02-26 15:04 ` [RFC PATCH v2 07/12] arm64: lse: Include compiler_types.h and export.h for out-of-line LL/SC Will Deacon
2018-02-26 15:04   ` Will Deacon
2018-02-26 15:42   ` Mark Rutland
2018-02-26 15:42     ` Mark Rutland
2018-02-26 15:04 ` [RFC PATCH v2 08/12] arm64: cmpxchg: Include build_bug.h instead of bug.h for BUILD_BUG Will Deacon
2018-02-26 15:04   ` Will Deacon
2018-02-26 15:48   ` Mark Rutland
2018-02-26 15:48     ` Mark Rutland
2018-02-27 17:33     ` Will Deacon
2018-02-27 17:33       ` Will Deacon
2018-02-27 17:34       ` Mark Rutland
2018-02-27 17:34         ` Mark Rutland
2018-02-26 15:04 ` [RFC PATCH v2 09/12] asm-generic/bitops/atomic.h: Rewrite using atomic_fetch_* Will Deacon
2018-02-26 15:04   ` Will Deacon
2018-02-26 15:04 ` Will Deacon [this message]
2018-02-26 15:04   ` [RFC PATCH v2 10/12] asm-generic/bitops/lock.h: " Will Deacon
2018-02-26 15:04 ` [RFC PATCH v2 11/12] arm64: Replace our atomic/lock bitop implementations with asm-generic Will Deacon
2018-02-26 15:04   ` Will Deacon
2018-02-26 15:05 ` [RFC PATCH v2 12/12] arm64: bitops: Include <asm-generic/bitops/ext2-atomic-setbit.h> Will Deacon
2018-02-26 15:05   ` Will Deacon
2018-03-01  7:16 ` [RFC PATCH v2 00/12] Rewrite asm-generic/bitops/{atomic,lock}.h and use on arm64 Masahiro Yamada
2018-03-01  7:16   ` Masahiro Yamada
2018-03-12  3:56   ` Masahiro Yamada
2018-03-12  3:56     ` Masahiro Yamada
2018-03-19 17:21     ` Will Deacon
2018-03-19 17:21       ` Will Deacon

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=1519657500-15094-11-git-send-email-will.deacon@arm.com \
    --to=will.deacon@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=yamada.masahiro@socionext.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.