From: Paul Burton <paul.burton@mips.com>
To: "linux-mips@vger.kernel.org" <linux-mips@vger.kernel.org>
Cc: Huacai Chen <chenhc@lemote.com>,
Jiaxun Yang <jiaxun.yang@flygoat.com>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
Paul Burton <pburton@wavecomp.com>
Subject: [PATCH v2 20/36] MIPS: bitops: Implement test_and_set_bit() in terms of _lock variant
Date: Tue, 1 Oct 2019 21:53:30 +0000 [thread overview]
Message-ID: <20191001215249.4157062-21-paul.burton@mips.com> (raw)
In-Reply-To: <20191001215249.4157062-1-paul.burton@mips.com>
The only difference between test_and_set_bit() & test_and_set_bit_lock()
is memory ordering barrier semantics - the former provides a full
barrier whilst the latter only provides acquire semantics.
We can therefore implement test_and_set_bit() in terms of
test_and_set_bit_lock() with the addition of the extra memory barrier.
Do this in order to avoid duplicating logic.
Signed-off-by: Paul Burton <paul.burton@mips.com>
---
Changes in v2: None
arch/mips/include/asm/bitops.h | 66 +++++++---------------------------
arch/mips/lib/bitops.c | 26 --------------
2 files changed, 13 insertions(+), 79 deletions(-)
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index 03532ae9f528..ea35a2e87b6d 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -31,8 +31,6 @@
void __mips_set_bit(unsigned long nr, volatile unsigned long *addr);
void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr);
void __mips_change_bit(unsigned long nr, volatile unsigned long *addr);
-int __mips_test_and_set_bit(unsigned long nr,
- volatile unsigned long *addr);
int __mips_test_and_set_bit_lock(unsigned long nr,
volatile unsigned long *addr);
int __mips_test_and_clear_bit(unsigned long nr,
@@ -236,24 +234,22 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
}
/*
- * test_and_set_bit - Set a bit and return its old value
+ * test_and_set_bit_lock - Set a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
*
- * This operation is atomic and cannot be reordered.
- * It also implies a memory barrier.
+ * This operation is atomic and implies acquire ordering semantics
+ * after the memory operation.
*/
-static inline int test_and_set_bit(unsigned long nr,
+static inline int test_and_set_bit_lock(unsigned long nr,
volatile unsigned long *addr)
{
unsigned long *m = ((unsigned long *)addr) + (nr >> SZLONG_LOG);
int bit = nr & SZLONG_MASK;
unsigned long res, temp;
- smp_mb__before_llsc();
-
if (!kernel_uses_llsc) {
- res = __mips_test_and_set_bit(nr, addr);
+ res = __mips_test_and_set_bit_lock(nr, addr);
} else if (R10000_LLSC_WAR) {
__asm__ __volatile__(
" .set push \n"
@@ -264,7 +260,7 @@ static inline int test_and_set_bit(unsigned long nr,
" beqzl %2, 1b \n"
" and %2, %0, %3 \n"
" .set pop \n"
- : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
+ : "=&r" (temp), "+m" (*m), "=&r" (res)
: "r" (1UL << bit)
: __LLSC_CLOBBER);
} else {
@@ -291,56 +287,20 @@ static inline int test_and_set_bit(unsigned long nr,
}
/*
- * test_and_set_bit_lock - Set a bit and return its old value
+ * test_and_set_bit - Set a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
*
- * This operation is atomic and implies acquire ordering semantics
- * after the memory operation.
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
*/
-static inline int test_and_set_bit_lock(unsigned long nr,
+static inline int test_and_set_bit(unsigned long nr,
volatile unsigned long *addr)
{
- unsigned long *m = ((unsigned long *)addr) + (nr >> SZLONG_LOG);
- int bit = nr & SZLONG_MASK;
- unsigned long res, temp;
-
- if (!kernel_uses_llsc) {
- res = __mips_test_and_set_bit_lock(nr, addr);
- } else if (R10000_LLSC_WAR) {
- __asm__ __volatile__(
- " .set push \n"
- " .set arch=r4000 \n"
- "1: " __LL "%0, %1 # test_and_set_bit \n"
- " or %2, %0, %3 \n"
- " " __SC "%2, %1 \n"
- " beqzl %2, 1b \n"
- " and %2, %0, %3 \n"
- " .set pop \n"
- : "=&r" (temp), "+m" (*m), "=&r" (res)
- : "r" (1UL << bit)
- : __LLSC_CLOBBER);
- } else {
- do {
- __asm__ __volatile__(
- " .set push \n"
- " .set "MIPS_ISA_ARCH_LEVEL" \n"
- " " __LL "%0, %1 # test_and_set_bit \n"
- " or %2, %0, %3 \n"
- " " __SC "%2, %1 \n"
- " .set pop \n"
- : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
- : "r" (1UL << bit)
- : __LLSC_CLOBBER);
- } while (unlikely(!res));
-
- res = temp & (1UL << bit);
- }
-
- smp_llsc_mb();
-
- return res != 0;
+ smp_mb__before_llsc();
+ return test_and_set_bit_lock(nr, addr);
}
+
/*
* test_and_clear_bit - Clear a bit and return its old value
* @nr: Bit to clear
diff --git a/arch/mips/lib/bitops.c b/arch/mips/lib/bitops.c
index 3b2a1e78a543..fba402c0879d 100644
--- a/arch/mips/lib/bitops.c
+++ b/arch/mips/lib/bitops.c
@@ -77,32 +77,6 @@ void __mips_change_bit(unsigned long nr, volatile unsigned long *addr)
EXPORT_SYMBOL(__mips_change_bit);
-/**
- * __mips_test_and_set_bit - Set a bit and return its old value. This is
- * called by test_and_set_bit() if it cannot find a faster solution.
- * @nr: Bit to set
- * @addr: Address to count from
- */
-int __mips_test_and_set_bit(unsigned long nr,
- volatile unsigned long *addr)
-{
- unsigned long *a = (unsigned long *)addr;
- unsigned bit = nr & SZLONG_MASK;
- unsigned long mask;
- unsigned long flags;
- int res;
-
- a += nr >> SZLONG_LOG;
- mask = 1UL << bit;
- raw_local_irq_save(flags);
- res = (mask & *a) != 0;
- *a |= mask;
- raw_local_irq_restore(flags);
- return res;
-}
-EXPORT_SYMBOL(__mips_test_and_set_bit);
-
-
/**
* __mips_test_and_set_bit_lock - Set a bit and return its old value. This is
* called by test_and_set_bit_lock() if it cannot find a faster solution.
--
2.23.0
next prev parent reply other threads:[~2019-10-01 21:53 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-01 21:53 [PATCH v2 00/36] MIPS: barriers & atomics cleanups Paul Burton
2019-10-01 21:53 ` [PATCH v2 01/36] MIPS: Unify sc beqz definition Paul Burton
2019-10-01 21:53 ` [PATCH v2 02/36] MIPS: Use compact branch for LL/SC loops on MIPSr6+ Paul Burton
2019-10-01 21:53 ` [PATCH v2 03/36] MIPS: barrier: Add __SYNC() infrastructure Paul Burton
2019-10-01 21:53 ` [PATCH v2 04/36] MIPS: barrier: Clean up rmb() & wmb() definitions Paul Burton
2019-10-01 21:53 ` [PATCH v2 05/36] MIPS: barrier: Clean up __smp_mb() definition Paul Burton
2019-10-01 21:53 ` [PATCH v2 06/36] MIPS: barrier: Remove fast_mb() Octeon #ifdef'ery Paul Burton
2019-10-01 21:53 ` [PATCH v2 07/36] MIPS: barrier: Clean up __sync() definition Paul Burton
2019-10-01 21:53 ` [PATCH v2 08/36] MIPS: barrier: Clean up sync_ginv() Paul Burton
2019-10-01 21:53 ` [PATCH v2 09/36] MIPS: atomic: Fix whitespace in ATOMIC_OP macros Paul Burton
2019-10-01 21:53 ` [PATCH v2 10/36] MIPS: atomic: Handle !kernel_uses_llsc first Paul Burton
2019-10-01 21:53 ` [PATCH v2 11/36] MIPS: atomic: Use one macro to generate 32b & 64b functions Paul Burton
2019-10-01 21:53 ` [PATCH v2 12/36] MIPS: atomic: Emit Loongson3 sync workarounds within asm Paul Burton
2019-10-01 21:53 ` [PATCH v2 13/36] MIPS: atomic: Use _atomic barriers in atomic_sub_if_positive() Paul Burton
2019-10-01 21:53 ` [PATCH v2 14/36] MIPS: atomic: Unify 32b & 64b sub_if_positive Paul Burton
2019-10-01 21:53 ` [PATCH v2 15/36] MIPS: atomic: Deduplicate 32b & 64b read, set, xchg, cmpxchg Paul Burton
2019-10-01 21:53 ` [PATCH v2 16/36] MIPS: bitops: Handle !kernel_uses_llsc first Paul Burton
2019-10-01 21:53 ` [PATCH v2 17/36] MIPS: bitops: Only use ins for bit 16 or higher Paul Burton
2019-10-01 21:53 ` [PATCH v2 18/36] MIPS: bitops: Use MIPS_ISA_REV, not #ifdefs Paul Burton
2019-10-01 21:53 ` [PATCH v2 19/36] MIPS: bitops: ins start position is always an immediate Paul Burton
2019-10-01 21:53 ` Paul Burton [this message]
2019-10-01 21:53 ` [PATCH v2 21/36] MIPS: bitops: Allow immediates in test_and_{set,clear,change}_bit Paul Burton
2019-10-01 21:53 ` [PATCH v2 22/36] MIPS: bitops: Use the BIT() macro Paul Burton
2019-10-01 21:53 ` [PATCH v2 23/36] MIPS: bitops: Avoid redundant zero-comparison for non-LLSC Paul Burton
2019-10-01 21:53 ` [PATCH v2 24/36] MIPS: bitops: Abstract LL/SC loops Paul Burton
2019-10-01 21:53 ` [PATCH v2 25/36] MIPS: bitops: Use BIT_WORD() & BITS_PER_LONG Paul Burton
2019-10-01 21:53 ` [PATCH v2 26/36] MIPS: bitops: Emit Loongson3 sync workarounds within asm Paul Burton
2019-10-01 21:53 ` [PATCH v2 27/36] MIPS: bitops: Use smp_mb__before_atomic in test_* ops Paul Burton
2019-10-01 21:53 ` [PATCH v2 28/36] MIPS: cmpxchg: Emit Loongson3 sync workarounds within asm Paul Burton
2019-10-01 21:53 ` [PATCH v2 29/36] MIPS: cmpxchg: Omit redundant barriers for Loongson3 Paul Burton
2019-10-01 21:53 ` [PATCH v2 30/36] MIPS: futex: Emit Loongson3 sync workarounds within asm Paul Burton
2019-10-01 21:53 ` [PATCH v2 31/36] MIPS: syscall: " Paul Burton
2019-10-01 21:53 ` [PATCH v2 32/36] MIPS: barrier: Remove loongson_llsc_mb() Paul Burton
2019-10-01 21:53 ` [PATCH v2 33/36] MIPS: barrier: Make __smp_mb__before_atomic() a no-op for Loongson3 Paul Burton
2019-10-01 21:53 ` [PATCH v2 34/36] MIPS: genex: Add Loongson3 LL/SC workaround to ejtag_debug_handler Paul Burton
2019-10-01 21:53 ` [PATCH v2 35/36] MIPS: genex: Don't reload address unnecessarily Paul Burton
2019-10-01 21:53 ` [PATCH v2 36/36] MIPS: Check Loongson3 LL/SC errata workaround correctness Paul Burton
2019-10-07 17:51 ` [PATCH v2 00/36] MIPS: barriers & atomics cleanups Paul Burton
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=20191001215249.4157062-21-paul.burton@mips.com \
--to=paul.burton@mips.com \
--cc=chenhc@lemote.com \
--cc=jiaxun.yang@flygoat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mips@vger.kernel.org \
--cc=pburton@wavecomp.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®