]> www.infradead.org Git - users/willy/pagecache.git/commitdiff
mips: Implement xor_unlock_is_negative_byte
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Fri, 21 Jul 2023 17:45:30 +0000 (13:45 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Wed, 4 Oct 2023 01:18:59 +0000 (21:18 -0400)
Inspired by the mips test_and_change_bit(), this will surely be more
efficient than the generic one defined in filemap.c

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
arch/mips/include/asm/bitops.h
arch/mips/lib/bitops.c

index b4bf754f7db3f7fda634f8d659c8d0d120d05479..d98a05c478f427614bbd3afad6fb9bc0db5c93d4 100644 (file)
@@ -73,7 +73,8 @@ int __mips_test_and_clear_bit(unsigned long nr,
                              volatile unsigned long *addr);
 int __mips_test_and_change_bit(unsigned long nr,
                               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
@@ -279,6 +280,29 @@ static inline int test_and_change_bit(unsigned long nr,
        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 __test_bit_op
 
index 116d0bd8b2ae9988a5876bec7407caf0ae89a09e..00aee98e9d545804084a4dfc9e32141a5ea31661 100644 (file)
@@ -146,3 +146,17 @@ int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
        return res;
 }
 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;
+}