2015-07-09 18:03:37

by Peter Zijlstra

[permalink] [raw]
Subject: [RFC][PATCH 23/24] atomic: Collapse all atomic_{set,clear}_mask definitions

Move the now generic definitions of atomic_{set,clear}_mask() into
linux/atomic.h to avoid endless and pointless repetition.

Also, provide an atomic_nand() wrapper for those few archs that can
implement that.


Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
---
arch/arc/include/asm/atomic.h | 10 ----------
arch/blackfin/include/asm/atomic.h | 10 ----------
arch/frv/include/asm/atomic.h | 10 ----------
arch/m32r/include/asm/atomic.h | 11 -----------
arch/m68k/include/asm/atomic.h | 10 ----------
arch/metag/include/asm/atomic_lnkget.h | 10 ----------
arch/metag/include/asm/atomic_lock1.h | 10 ----------
arch/mn10300/include/asm/atomic.h | 24 ------------------------
arch/powerpc/kernel/misc_32.S | 19 -------------------
arch/s390/include/asm/atomic.h | 10 ----------
arch/sh/include/asm/atomic.h | 10 ----------
arch/x86/include/asm/atomic.h | 10 ----------
arch/xtensa/include/asm/atomic.h | 10 ----------
include/asm-generic/atomic.h | 10 ----------
include/linux/atomic.h | 17 +++++++++++++++++
15 files changed, 17 insertions(+), 164 deletions(-)

--- a/arch/arc/include/asm/atomic.h
+++ b/arch/arc/include/asm/atomic.h
@@ -151,16 +151,6 @@ ATOMIC_OP(xor, ^=, xor)
#undef ATOMIC_OP_RETURN
#undef ATOMIC_OP

-static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
-static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
/**
* __atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
--- a/arch/blackfin/include/asm/atomic.h
+++ b/arch/blackfin/include/asm/atomic.h
@@ -32,16 +32,6 @@ asmlinkage int __raw_atomic_test_asm(con
#define atomic_and(i, v) (void)__raw_atomic_and_asm(&(v)->counter, i)
#define atomic_xor(i, v) (void)__raw_atomic_xor_asm(&(v)->counter, i)

-static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
-static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
#endif

#include <asm-generic/atomic.h>
--- a/arch/frv/include/asm/atomic.h
+++ b/arch/frv/include/asm/atomic.h
@@ -198,14 +198,4 @@ ATOMIC_OP(xor)

#undef ATOMIC_OP

-static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
-static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
#endif /* _ASM_ATOMIC_H */
--- a/arch/m32r/include/asm/atomic.h
+++ b/arch/m32r/include/asm/atomic.h
@@ -242,15 +242,4 @@ static __inline__ int __atomic_add_unles
return c;
}

-
-static __inline__ __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
-static __inline__ __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
#endif /* _ASM_M32R_ATOMIC_H */
--- a/arch/m68k/include/asm/atomic.h
+++ b/arch/m68k/include/asm/atomic.h
@@ -173,16 +173,6 @@ static inline int atomic_add_negative(in
return c != 0;
}

-static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
-static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
--- a/arch/metag/include/asm/atomic_lnkget.h
+++ b/arch/metag/include/asm/atomic_lnkget.h
@@ -81,16 +81,6 @@ ATOMIC_OP(xor)
#undef ATOMIC_OP_RETURN
#undef ATOMIC_OP

-static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
-static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
{
int result, temp;
--- a/arch/metag/include/asm/atomic_lock1.h
+++ b/arch/metag/include/asm/atomic_lock1.h
@@ -76,16 +76,6 @@ ATOMIC_OP(xor, ^=)
#undef ATOMIC_OP_RETURN
#undef ATOMIC_OP

-static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
-static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
{
int ret;
--- a/arch/mn10300/include/asm/atomic.h
+++ b/arch/mn10300/include/asm/atomic.h
@@ -130,30 +130,6 @@ static inline void atomic_dec(atomic_t *
#define atomic_xchg(ptr, v) (xchg(&(ptr)->counter, (v)))
#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))

-/**
- * atomic_clear_mask - Atomically clear bits in memory
- * @mask: Mask of the bits to be cleared
- * @v: pointer to word in memory
- *
- * Atomically clears the bits set in mask from the memory word specified.
- */
-static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
-/**
- * atomic_set_mask - Atomically set bits in memory
- * @mask: Mask of the bits to be set
- * @v: pointer to word in memory
- *
- * Atomically sets the bits set in mask from the memory word specified.
- */
-static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
#endif /* __KERNEL__ */
#endif /* CONFIG_SMP */
#endif /* _ASM_ATOMIC_H */
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -596,25 +596,6 @@ _GLOBAL(copy_page)
b 2b

/*
- * void atomic_clear_mask(atomic_t mask, atomic_t *addr)
- * void atomic_set_mask(atomic_t mask, atomic_t *addr);
- */
-_GLOBAL(atomic_clear_mask)
-10: lwarx r5,0,r4
- andc r5,r5,r3
- PPC405_ERR77(0,r4)
- stwcx. r5,0,r4
- bne- 10b
- blr
-_GLOBAL(atomic_set_mask)
-10: lwarx r5,0,r4
- or r5,r5,r3
- PPC405_ERR77(0,r4)
- stwcx. r5,0,r4
- bne- 10b
- blr
-
-/*
* Extended precision shifts.
*
* Updated to be valid for shift counts from 0 to 63 inclusive.
--- a/arch/s390/include/asm/atomic.h
+++ b/arch/s390/include/asm/atomic.h
@@ -132,16 +132,6 @@ ATOMIC_OP(xor, XOR)

#undef ATOMIC_OP

-static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
-static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))

static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
--- a/arch/sh/include/asm/atomic.h
+++ b/arch/sh/include/asm/atomic.h
@@ -25,16 +25,6 @@
#include <asm/atomic-irq.h>
#endif

-static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
-static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
#define atomic_dec_return(v) atomic_sub_return(1, (v))
#define atomic_inc_return(v) atomic_add_return(1, (v))
--- a/arch/x86/include/asm/atomic.h
+++ b/arch/x86/include/asm/atomic.h
@@ -234,16 +234,6 @@ static __always_inline short int atomic_
return *v;
}

-static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
-static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
#ifdef CONFIG_X86_32
# include <asm/atomic64_32.h>
#else
--- a/arch/xtensa/include/asm/atomic.h
+++ b/arch/xtensa/include/asm/atomic.h
@@ -152,16 +152,6 @@ ATOMIC_OP(xor)
#undef ATOMIC_OP_RETURN
#undef ATOMIC_OP

-static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
-static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
/**
* atomic_sub_and_test - subtract value from variable and test result
* @i: integer value to subtract
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -113,16 +113,6 @@ ATOMIC_OP(xor, ^)
#undef ATOMIC_OP_RETURN
#undef ATOMIC_OP

-static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
- atomic_and(~mask, v);
-}
-
-static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
- atomic_or(mask, v);
-}
-
/*
* Atomic operations that C can't guarantee us. Useful for
* resource counting etc..
--- a/include/linux/atomic.h
+++ b/include/linux/atomic.h
@@ -28,6 +28,23 @@ static inline int atomic_add_unless(atom
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
#endif

+#ifndef atomic_nand
+static inline void atomic_nand(int i, atomic_t *v)
+{
+ atomic_and(~i, v);
+}
+#endif
+
+static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
+{
+ atomic_nand(mask, v);
+}
+
+static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
+{
+ atomic_or(mask, v);
+}
+
/**
* atomic_inc_not_zero_hint - increment if not null
* @v: pointer of type atomic_t


2015-07-10 09:10:39

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [RFC][PATCH 23/24] atomic: Collapse all atomic_{set,clear}_mask definitions

Hi Peter,

On Thu, Jul 9, 2015 at 7:29 PM, Peter Zijlstra <[email protected]> wrote:
> --- a/include/linux/atomic.h
> +++ b/include/linux/atomic.h
> @@ -28,6 +28,23 @@ static inline int atomic_add_unless(atom
> #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
> #endif
>
> +#ifndef atomic_nand
> +static inline void atomic_nand(int i, atomic_t *v)
> +{
> + atomic_and(~i, v);

That sounds like a misnomer...

Your NAND is "A & ~B", while my[*] NAND is "~(A & B)"?

[*] https://en.wikipedia.org/wiki/NAND_logic

What about atomic_clear()? (Is atomic_bic() too ARM-centric?)

> +}
> +#endif
> +
> +static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
> +{
> + atomic_nand(mask, v);
> +}

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

2015-07-10 09:14:14

by Vineet Gupta

[permalink] [raw]
Subject: Re: [RFC][PATCH 23/24] atomic: Collapse all atomic_{set,clear}_mask definitions

On Friday 10 July 2015 02:40 PM, Geert Uytterhoeven wrote:
> Hi Peter,
>
> On Thu, Jul 9, 2015 at 7:29 PM, Peter Zijlstra <[email protected]> wrote:
>> > --- a/include/linux/atomic.h
>> > +++ b/include/linux/atomic.h
>> > @@ -28,6 +28,23 @@ static inline int atomic_add_unless(atom
>> > #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
>> > #endif
>> >
>> > +#ifndef atomic_nand
>> > +static inline void atomic_nand(int i, atomic_t *v)
>> > +{
>> > + atomic_and(~i, v);
> That sounds like a misnomer...
>
> Your NAND is "A & ~B", while my[*] NAND is "~(A & B)"?
>
> [*] https://en.wikipedia.org/wiki/NAND_logic
>
> What about atomic_clear()? (Is atomic_bic() too ARM-centric?)
>

ARM + ARC centric :-)

We have the BIC instruction as well which does the same: A & ~B

-Vineet

2015-07-10 10:40:15

by Peter Zijlstra

[permalink] [raw]
Subject: Re: [RFC][PATCH 23/24] atomic: Collapse all atomic_{set,clear}_mask definitions

On Fri, Jul 10, 2015 at 11:10:33AM +0200, Geert Uytterhoeven wrote:
> Hi Peter,
>
> On Thu, Jul 9, 2015 at 7:29 PM, Peter Zijlstra <[email protected]> wrote:
> > --- a/include/linux/atomic.h
> > +++ b/include/linux/atomic.h
> > @@ -28,6 +28,23 @@ static inline int atomic_add_unless(atom
> > #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
> > #endif
> >
> > +#ifndef atomic_nand
> > +static inline void atomic_nand(int i, atomic_t *v)
> > +{
> > + atomic_and(~i, v);
>
> That sounds like a misnomer...
>
> Your NAND is "A & ~B", while my[*] NAND is "~(A & B)"?
>
> [*] https://en.wikipedia.org/wiki/NAND_logic

Right you are.

> What about atomic_clear()? (Is atomic_bic() too ARM-centric?)

atomic_and_not() ?

2015-07-10 13:34:14

by Chris Metcalf

[permalink] [raw]
Subject: Re: [RFC][PATCH 23/24] atomic: Collapse all atomic_{set,clear}_mask definitions

On 7/10/2015 6:39 AM, Peter Zijlstra wrote:
> On Fri, Jul 10, 2015 at 11:10:33AM +0200, Geert Uytterhoeven wrote:
>> Hi Peter,
>>
>> On Thu, Jul 9, 2015 at 7:29 PM, Peter Zijlstra <[email protected]> wrote:
>>> --- a/include/linux/atomic.h
>>> +++ b/include/linux/atomic.h
>>> @@ -28,6 +28,23 @@ static inline int atomic_add_unless(atom
>>> #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
>>> #endif
>>>
>>> +#ifndef atomic_nand
>>> +static inline void atomic_nand(int i, atomic_t *v)
>>> +{
>>> + atomic_and(~i, v);
>> That sounds like a misnomer...
>>
>> Your NAND is "A & ~B", while my[*] NAND is "~(A & B)"?
>>
>> [*] https://en.wikipedia.org/wiki/NAND_logic
> Right you are.
>
>> What about atomic_clear()? (Is atomic_bic() too ARM-centric?)
> atomic_and_not() ?

I've seen this as ANDN (as opposed to NAND). That's the name I used in
the tilepro atomics as the thing that implements the bitmask clear operation.
SPARC also has an "andn" instruction with this semantics.

--
Chris Metcalf, EZChip Semiconductor
http://www.ezchip.com

2015-07-10 13:43:35

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [RFC][PATCH 23/24] atomic: Collapse all atomic_{set,clear}_mask definitions

On Fri, Jul 10, 2015 at 09:34:04AM -0400, Chris Metcalf wrote:
> On 7/10/2015 6:39 AM, Peter Zijlstra wrote:
> >On Fri, Jul 10, 2015 at 11:10:33AM +0200, Geert Uytterhoeven wrote:
> >>Hi Peter,
> >>
> >>On Thu, Jul 9, 2015 at 7:29 PM, Peter Zijlstra <[email protected]> wrote:
> >>>--- a/include/linux/atomic.h
> >>>+++ b/include/linux/atomic.h
> >>>@@ -28,6 +28,23 @@ static inline int atomic_add_unless(atom
> >>> #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
> >>> #endif
> >>>
> >>>+#ifndef atomic_nand
> >>>+static inline void atomic_nand(int i, atomic_t *v)
> >>>+{
> >>>+ atomic_and(~i, v);
> >>That sounds like a misnomer...
> >>
> >>Your NAND is "A & ~B", while my[*] NAND is "~(A & B)"?
> >>
> >>[*] https://en.wikipedia.org/wiki/NAND_logic
> >Right you are.
> >
> >>What about atomic_clear()? (Is atomic_bic() too ARM-centric?)
> >atomic_and_not() ?
>
> I've seen this as ANDN (as opposed to NAND). That's the name I used in
> the tilepro atomics as the thing that implements the bitmask clear operation.
> SPARC also has an "andn" instruction with this semantics.

The obvious question though is whether we have an established name for this
operation elsewhere in the kernel, and whether we should have consistency.
In include/linux, we already have (grepping for 'and_*not'):

include/linux/nodemask.h:#define nodes_andnot(dst, src1, src2) \
include/linux/bitmap.h:extern int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
include/linux/cpumask.h:static inline int cpumask_andnot(struct cpumask *dstp,

We also have:

include/linux/signal.h:#define _sig_andn(x,y) ((x) & ~(y))

which seems to be the only instance of "andn" in include/.

--
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

2015-07-10 16:27:54

by Peter Zijlstra

[permalink] [raw]
Subject: Re: [RFC][PATCH 23/24] atomic: Collapse all atomic_{set,clear}_mask definitions

On Fri, Jul 10, 2015 at 02:42:56PM +0100, Russell King - ARM Linux wrote:
> The obvious question though is whether we have an established name for this
> operation elsewhere in the kernel, and whether we should have consistency.

Consistency is good.

> In include/linux, we already have (grepping for 'and_*not'):
>
> include/linux/nodemask.h:#define nodes_andnot(dst, src1, src2) \
> include/linux/bitmap.h:extern int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
> include/linux/cpumask.h:static inline int cpumask_andnot(struct cpumask *dstp,
>
> We also have:
>
> include/linux/signal.h:#define _sig_andn(x,y) ((x) & ~(y))
>
> which seems to be the only instance of "andn" in include/.

How about I rename the _sig_andn one to _sig_andnot, and go with
atomic_andnot, to match the *mask functions.

2015-07-10 17:35:52

by Chris Metcalf

[permalink] [raw]
Subject: Re: [RFC][PATCH 23/24] atomic: Collapse all atomic_{set,clear}_mask definitions

On 07/10/2015 12:27 PM, Peter Zijlstra wrote:
> On Fri, Jul 10, 2015 at 02:42:56PM +0100, Russell King - ARM Linux wrote:
>> The obvious question though is whether we have an established name for this
>> operation elsewhere in the kernel, and whether we should have consistency.
> Consistency is good.
>
>> In include/linux, we already have (grepping for 'and_*not'):
>>
>> include/linux/nodemask.h:#define nodes_andnot(dst, src1, src2) \
>> include/linux/bitmap.h:extern int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
>> include/linux/cpumask.h:static inline int cpumask_andnot(struct cpumask *dstp,
>>
>> We also have:
>>
>> include/linux/signal.h:#define _sig_andn(x,y) ((x) & ~(y))
>>
>> which seems to be the only instance of "andn" in include/.
> How about I rename the _sig_andn one to _sig_andnot, and go with
> atomic_andnot, to match the *mask functions.

I'll respin my patch to just tweak tilepro's "andn" to use
"andnot" as well while I'm at it, then. Making "andnot" a stand-alone
patch would cause conflicts so it might as well go in with your change.

--
Chris Metcalf, EZChip Semiconductor
http://www.ezchip.com

2015-07-10 19:46:10

by Chris Metcalf

[permalink] [raw]
Subject: Re: [RFC][PATCH 23/24] atomic: Collapse all atomic_{set,clear}_mask definitions

On 07/10/2015 12:27 PM, Peter Zijlstra wrote:
> On Fri, Jul 10, 2015 at 02:42:56PM +0100, Russell King - ARM Linux wrote:
>> The obvious question though is whether we have an established name for this
>> operation elsewhere in the kernel, and whether we should have consistency.
> Consistency is good.
>
>> In include/linux, we already have (grepping for 'and_*not'):
>>
>> include/linux/nodemask.h:#define nodes_andnot(dst, src1, src2) \
>> include/linux/bitmap.h:extern int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
>> include/linux/cpumask.h:static inline int cpumask_andnot(struct cpumask *dstp,
>>
>> We also have:
>>
>> include/linux/signal.h:#define _sig_andn(x,y) ((x) & ~(y))
>>
>> which seems to be the only instance of "andn" in include/.
> How about I rename the _sig_andn one to _sig_andnot, and go with
> atomic_andnot, to match the *mask functions.

On further examination, there is also FUTEX_OP_ANDN, which is originally
what
inspired me to use the name atomic_andn(). So I think churning the
nomenclature
around for tilepro isn't really particularly helpful, and I won't bother.

In any case I think "andn" and "andnot" are both fine names for
atomic_xxx :-)

--
Chris Metcalf, EZChip Semiconductor
http://www.ezchip.com