Re: [PATCH V4 07/22] LoongArch: Add atomic/locking headers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi, Peter,

On Fri, Oct 1, 2021 at 6:54 PM Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote:
>
> On Mon, Sep 27, 2021 at 02:42:44PM +0800, Huacai Chen wrote:
> > diff --git a/arch/loongarch/include/asm/bitops.h b/arch/loongarch/include/asm/bitops.h
> > new file mode 100644
> > index 000000000000..8b05d9683571
> > --- /dev/null
> > +++ b/arch/loongarch/include/asm/bitops.h
> > @@ -0,0 +1,220 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (C) 2020-2021 Loongson Technology Corporation Limited
> > + */
> > +#ifndef _ASM_BITOPS_H
> > +#define _ASM_BITOPS_H
> > +
> > +#ifndef _LINUX_BITOPS_H
> > +#error only <linux/bitops.h> can be included directly
> > +#endif
> > +
> > +#include <linux/compiler.h>
> > +#include <linux/types.h>
> > +#include <asm/barrier.h>
> > +#include <asm/byteorder.h>
> > +#include <asm/compiler.h>
> > +#include <asm/cpu-features.h>
> > +
> > +#if _LOONGARCH_SZLONG == 32
> > +#define __LL         "ll.w   "
> > +#define __SC         "sc.w   "
> > +#define __AMADD              "amadd.w        "
> > +#define __AMAND_SYNC "amand_db.w     "
> > +#define __AMOR_SYNC  "amor_db.w      "
> > +#define __AMXOR_SYNC "amxor_db.w     "
> > +#elif _LOONGARCH_SZLONG == 64
> > +#define __LL         "ll.d   "
> > +#define __SC         "sc.d   "
> > +#define __AMADD              "amadd.d        "
> > +#define __AMAND_SYNC "amand_db.d     "
> > +#define __AMOR_SYNC  "amor_db.d      "
> > +#define __AMXOR_SYNC "amxor_db.d     "
> > +#endif
> > +
> > +/*
> > + * set_bit - Atomically set a bit in memory
> > + * @nr: the bit to set
> > + * @addr: the address to start counting from
> > + */
> > +static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
> > +{
> > +     int bit = nr % BITS_PER_LONG;
> > +     volatile unsigned long *m = &addr[BIT_WORD(nr)];
> > +
> > +     __asm__ __volatile__(
> > +     "   " __AMOR_SYNC "$zero, %1, %0        \n"
> > +     : "+ZB" (*m)
> > +     : "r" (1UL << bit)
> > +     : "memory");
> > +}
> > +
> > +/*
> > + * clear_bit - Clears a bit in memory
> > + * @nr: Bit to clear
> > + * @addr: Address to start counting from
> > + */
> > +static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
> > +{
> > +     int bit = nr % BITS_PER_LONG;
> > +     volatile unsigned long *m = &addr[BIT_WORD(nr)];
> > +
> > +     __asm__ __volatile__(
> > +     "   " __AMAND_SYNC "$zero, %1, %0       \n"
> > +     : "+ZB" (*m)
> > +     : "r" (~(1UL << bit))
> > +     : "memory");
> > +}
> > +
> > +/*
> > + * clear_bit_unlock - Clears a bit in memory
> > + * @nr: Bit to clear
> > + * @addr: Address to start counting from
> > + */
> > +static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *addr)
> > +{
> > +     clear_bit(nr, addr);
> > +}
> > +
> > +/*
> > + * change_bit - Toggle a bit in memory
> > + * @nr: Bit to change
> > + * @addr: Address to start counting from
> > + */
> > +static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
> > +{
> > +     int bit = nr % BITS_PER_LONG;
> > +     volatile unsigned long *m = &addr[BIT_WORD(nr)];
> > +
> > +     __asm__ __volatile__(
> > +     "   " __AMXOR_SYNC "$zero, %1, %0       \n"
> > +     : "+ZB" (*m)
> > +     : "r" (1UL << bit)
> > +     : "memory");
> > +}
> > +
> > +/*
> > + * test_and_set_bit - Set a bit and return its old value
> > + * @nr: Bit to set
> > + * @addr: Address to count from
> > + */
> > +static inline int test_and_set_bit(unsigned long nr,
> > +     volatile unsigned long *addr)
> > +{
> > +     int bit = nr % BITS_PER_LONG;
> > +     unsigned long res;
> > +     volatile unsigned long *m = &addr[BIT_WORD(nr)];
> > +
> > +     __asm__ __volatile__(
> > +     "   " __AMOR_SYNC "%1, %2, %0       \n"
> > +     : "+ZB" (*m), "=&r" (res)
> > +     : "r" (1UL << bit)
> > +     : "memory");
> > +
> > +     res = res & (1UL << bit);
> > +
> > +     return res != 0;
> > +}
> > +
> > +/*
> > + * test_and_set_bit_lock - Set a bit and return its old value
> > + * @nr: Bit to set
> > + * @addr: Address to count from
> > + */
> > +static inline int test_and_set_bit_lock(unsigned long nr,
> > +     volatile unsigned long *addr)
> > +{
> > +     int bit = nr % BITS_PER_LONG;
> > +     unsigned long res;
> > +     volatile unsigned long *m = &addr[BIT_WORD(nr)];
> > +
> > +     __asm__ __volatile__(
> > +     "   " __AMOR_SYNC "%1, %2, %0       \n"
> > +     : "+ZB" (*m), "=&r" (res)
> > +     : "r" (1UL << bit)
> > +     : "memory");
> > +
> > +     res = res & (1UL << bit);
> > +
> > +     return res != 0;
> > +}
> > +/*
> > + * test_and_clear_bit - Clear a bit and return its old value
> > + * @nr: Bit to clear
> > + * @addr: Address to count from
> > + */
> > +static inline int test_and_clear_bit(unsigned long nr,
> > +     volatile unsigned long *addr)
> > +{
> > +     int bit = nr % BITS_PER_LONG;
> > +     unsigned long res, temp;
> > +     volatile unsigned long *m = &addr[BIT_WORD(nr)];
> > +
> > +     __asm__ __volatile__(
> > +     "   " __AMAND_SYNC "%1, %2, %0      \n"
> > +     : "+ZB" (*m), "=&r" (temp)
> > +     : "r" (~(1UL << bit))
> > +     : "memory");
> > +
> > +     res = temp & (1UL << bit);
> > +
> > +     return res != 0;
> > +}
> > +
> > +/*
> > + * test_and_change_bit - Change a bit and return its old value
> > + * @nr: Bit to change
> > + * @addr: Address to count from
> > + */
> > +static inline int test_and_change_bit(unsigned long nr,
> > +     volatile unsigned long *addr)
> > +{
> > +     int bit = nr % BITS_PER_LONG;
> > +     unsigned long res;
> > +     volatile unsigned long *m = &addr[BIT_WORD(nr)];
> > +
> > +     __asm__ __volatile__(
> > +     "   " __AMXOR_SYNC "%1, %2, %0      \n"
> > +     : "+ZB" (*m), "=&r" (res)
> > +     : "r" (1UL << bit)
> > +     : "memory");
> > +
> > +     res = res & (1UL << bit);
> > +
> > +     return res != 0;
> > +}
>
> Why is asm-generic/bitops/atomic.h not working for you?
It seems that __clear_bit_unlock() needs an additional mb() after the
generic version, all other functions are the same as the generic
version.

Huacai
>




[Index of Archives]     [Linux Kernel]     [Kernel Newbies]     [x86 Platform Driver]     [Netdev]     [Linux Wireless]     [Netfilter]     [Bugtraq]     [Linux Filesystems]     [Yosemite Discussion]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]

  Powered by Linux