mips: implement xor_unlock_is_negative_byte
Inspired by the mips test_and_change_bit(), this will surely be more efficient than the generic one defined in filemap.c Link: https://lkml.kernel.org/r/20231004165317.1061855-11-willy@infradead.org Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Cc: Albert Ou <aou@eecs.berkeley.edu> Cc: Alexander Gordeev <agordeev@linux.ibm.com> Cc: Andreas Dilger <adilger.kernel@dilger.ca> Cc: Christian Borntraeger <borntraeger@linux.ibm.com> Cc: Christophe Leroy <christophe.leroy@csgroup.eu> Cc: Geert Uytterhoeven <geert@linux-m68k.org> Cc: Heiko Carstens <hca@linux.ibm.com> Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Cc: Matt Turner <mattst88@gmail.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Nicholas Piggin <npiggin@gmail.com> Cc: Palmer Dabbelt <palmer@dabbelt.com> Cc: Paul Walmsley <paul.walmsley@sifive.com> Cc: Richard Henderson <richard.henderson@linaro.org> Cc: Sven Schnelle <svens@linux.ibm.com> Cc: "Theodore Ts'o" <tytso@mit.edu> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Cc: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
ea845e3173
commit
8da36b26e3
@ -73,7 +73,8 @@ int __mips_test_and_clear_bit(unsigned long nr,
|
|||||||
volatile unsigned long *addr);
|
volatile unsigned long *addr);
|
||||||
int __mips_test_and_change_bit(unsigned long nr,
|
int __mips_test_and_change_bit(unsigned long nr,
|
||||||
volatile unsigned long *addr);
|
volatile unsigned long *addr);
|
||||||
|
bool __mips_xor_is_negative_byte(unsigned long mask,
|
||||||
|
volatile unsigned long *addr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set_bit - Atomically set a bit in memory
|
* set_bit - Atomically set a bit in memory
|
||||||
@ -279,6 +280,29 @@ static inline int test_and_change_bit(unsigned long nr,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool xor_unlock_is_negative_byte(unsigned long mask,
|
||||||
|
volatile unsigned long *p)
|
||||||
|
{
|
||||||
|
unsigned long orig;
|
||||||
|
bool res;
|
||||||
|
|
||||||
|
smp_mb__before_atomic();
|
||||||
|
|
||||||
|
if (!kernel_uses_llsc) {
|
||||||
|
res = __mips_xor_is_negative_byte(mask, p);
|
||||||
|
} else {
|
||||||
|
orig = __test_bit_op(*p, "%0",
|
||||||
|
"xor\t%1, %0, %3",
|
||||||
|
"ir"(mask));
|
||||||
|
res = (orig & BIT(7)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
smp_llsc_mb();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#define xor_unlock_is_negative_byte xor_unlock_is_negative_byte
|
||||||
|
|
||||||
#undef __bit_op
|
#undef __bit_op
|
||||||
#undef __test_bit_op
|
#undef __test_bit_op
|
||||||
|
|
||||||
|
@ -146,3 +146,17 @@ int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__mips_test_and_change_bit);
|
EXPORT_SYMBOL(__mips_test_and_change_bit);
|
||||||
|
|
||||||
|
bool __mips_xor_is_negative_byte(unsigned long mask,
|
||||||
|
volatile unsigned long *addr)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned long data;
|
||||||
|
|
||||||
|
raw_local_irq_save(flags);
|
||||||
|
data = *addr;
|
||||||
|
*addr = data ^ mask;
|
||||||
|
raw_local_irq_restore(flags);
|
||||||
|
|
||||||
|
return (data & BIT(7)) != 0;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user