2004-09-10 03:24:48

by Kohei KaiGai

[permalink] [raw]
Subject: [PATCH] atomic_inc_return() for i386[1/5] (Re: atomic_inc_return)


[1/5] atomic_inc_return-linux-2.6.9-rc1.i386.patch
This patch implements atomic_inc_return() and so on for i386,
and includes runtime check whether CPU is legacy 386.
It is same as I posted to LKML and Andi Kleen at '04/09/01.

Signed-off-by: KaiGai, Kohei <[email protected]>
--------
Kai Gai <[email protected]>


diff -rNU4 linux-2.6.9-rc1/include/asm-i386/atomic.h linux-2.6.9-rc1.atomic_inc_return/include/asm-i386/atomic.h
--- linux-2.6.9-rc1/include/asm-i386/atomic.h 2004-08-24 16:02:24.000000000 +0900
+++ linux-2.6.9-rc1.atomic_inc_return/include/asm-i386/atomic.h 2004-09-10 10:15:18.000000000 +0900
@@ -1,8 +1,10 @@
#ifndef __ARCH_I386_ATOMIC__
#define __ARCH_I386_ATOMIC__

#include <linux/config.h>
+#include <linux/compiler.h>
+#include <asm/processor.h>

/*
* Atomic operations that C can't guarantee us. Useful for
* resource counting etc..
@@ -175,8 +177,48 @@
:"ir" (i), "m" (v->counter) : "memory");
return c;
}

+/**
+ * atomic_add_return - add and return
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns @i + @v
+ */
+static __inline__ int atomic_add_return(int i, atomic_t *v)
+{
+ int __i;
+#ifdef CONFIG_M386
+ if(unlikely(boot_cpu_data.x86==3))
+ goto no_xadd;
+#endif
+ /* Modern 486+ processor */
+ __i = i;
+ __asm__ __volatile__(
+ LOCK "xaddl %0, %1;"
+ :"=r"(i)
+ :"m"(v->counter), "0"(i));
+ return i + __i;
+
+#ifdef CONFIG_M386
+no_xadd: /* Legacy 386 processor */
+ local_irq_disable();
+ __i = atomic_read(v);
+ atomic_set(v, i + __i);
+ local_irq_enable();
+ return i + __i;
+#endif
+}
+
+static __inline__ int atomic_sub_return(int i, atomic_t *v)
+{
+ return atomic_add_return(-i,v);
+}
+
+#define atomic_inc_return(v) (atomic_add_return(1,v))
+#define atomic_dec_return(v) (atomic_sub_return(1,v))
+
/* These are x86-specific, used by some header files */
#define atomic_clear_mask(mask, addr) \
__asm__ __volatile__(LOCK "andl %0,%1" \
: : "r" (~(mask)),"m" (*addr) : "memory")


2004-09-10 05:41:36

by Chris Wedgwood

[permalink] [raw]
Subject: Re: [PATCH] atomic_inc_return() for i386[1/5] (Re: atomic_inc_return)

On Fri, Sep 10, 2004 at 12:26:54PM +0900, Kaigai Kohei wrote:

> +static __inline__ int atomic_add_return(int i, atomic_t *v)
> +{
> + int __i;
> +#ifdef CONFIG_M386
> + if(unlikely(boot_cpu_data.x86==3))
> + goto no_xadd;
> +#endif

i didn't check what code is generated, but isn't that expensive? i
guess most people building i386 kernels want maximum compatability so
it probably doesn't matter...

2004-09-11 23:07:56

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] atomic_inc_return() for i386[1/5] (Re: atomic_inc_return)

[email protected] (Kaigai Kohei) wrote:
>
>
> [1/5] atomic_inc_return-linux-2.6.9-rc1.i386.patch
> This patch implements atomic_inc_return() and so on for i386,
> and includes runtime check whether CPU is legacy 386.
> It is same as I posted to LKML and Andi Kleen at '04/09/01.
>

Can we not use the `alternative instruction' stuff to eliminate the runtime
test?


>
> diff -rNU4 linux-2.6.9-rc1/include/asm-i386/atomic.h linux-2.6.9-rc1.atomic_inc_return/include/asm-i386/atomic.h
> --- linux-2.6.9-rc1/include/asm-i386/atomic.h 2004-08-24 16:02:24.000000000 +0900
> +++ linux-2.6.9-rc1.atomic_inc_return/include/asm-i386/atomic.h 2004-09-10 10:15:18.000000000 +0900
> @@ -1,8 +1,10 @@
> #ifndef __ARCH_I386_ATOMIC__
> #define __ARCH_I386_ATOMIC__
>
> #include <linux/config.h>
> +#include <linux/compiler.h>
> +#include <asm/processor.h>
>
> /*
> * Atomic operations that C can't guarantee us. Useful for
> * resource counting etc..
> @@ -175,8 +177,48 @@
> :"ir" (i), "m" (v->counter) : "memory");
> return c;
> }
>
> +/**
> + * atomic_add_return - add and return
> + * @v: pointer of type atomic_t
> + * @i: integer value to add
> + *
> + * Atomically adds @i to @v and returns @i + @v
> + */
> +static __inline__ int atomic_add_return(int i, atomic_t *v)
> +{
> + int __i;
> +#ifdef CONFIG_M386
> + if(unlikely(boot_cpu_data.x86==3))
> + goto no_xadd;
> +#endif
> + /* Modern 486+ processor */
> + __i = i;
> + __asm__ __volatile__(
> + LOCK "xaddl %0, %1;"
> + :"=r"(i)
> + :"m"(v->counter), "0"(i));
> + return i + __i;
> +
> +#ifdef CONFIG_M386
> +no_xadd: /* Legacy 386 processor */
> + local_irq_disable();
> + __i = atomic_read(v);
> + atomic_set(v, i + __i);
> + local_irq_enable();
> + return i + __i;
> +#endif
> +}
> +
> +static __inline__ int atomic_sub_return(int i, atomic_t *v)
> +{
> + return atomic_add_return(-i,v);
> +}
> +
> +#define atomic_inc_return(v) (atomic_add_return(1,v))
> +#define atomic_dec_return(v) (atomic_sub_return(1,v))
> +
> /* These are x86-specific, used by some header files */
> #define atomic_clear_mask(mask, addr) \
> __asm__ __volatile__(LOCK "andl %0,%1" \
> : : "r" (~(mask)),"m" (*addr) : "memory")

2004-09-12 08:25:42

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH] atomic_inc_return() for i386[1/5] (Re: atomic_inc_return)

On Sat, Sep 11, 2004 at 04:05:32PM -0700, Andrew Morton wrote:
> [email protected] (Kaigai Kohei) wrote:
> >
> >
> > [1/5] atomic_inc_return-linux-2.6.9-rc1.i386.patch
> > This patch implements atomic_inc_return() and so on for i386,
> > and includes runtime check whether CPU is legacy 386.
> > It is same as I posted to LKML and Andi Kleen at '04/09/01.
> >
>
> Can we not use the `alternative instruction' stuff to eliminate the runtime
> test?

Yes, we could. I suggested this to Kaigai-san earlier, but
he decided that it was too complicated because he would have needed
to add an additional alternative() macro with enough parameters.

Given that atomic instructions are quite costly anyways and the jump
should be very predictable he's probably right that it wouldn't
be worth the effort.

-Andi

2004-09-12 09:08:57

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] atomic_inc_return() for i386[1/5] (Re: atomic_inc_return)

Andi Kleen <[email protected]> wrote:
>
> On Sat, Sep 11, 2004 at 04:05:32PM -0700, Andrew Morton wrote:
> > [email protected] (Kaigai Kohei) wrote:
> > >
> > >
> > > [1/5] atomic_inc_return-linux-2.6.9-rc1.i386.patch
> > > This patch implements atomic_inc_return() and so on for i386,
> > > and includes runtime check whether CPU is legacy 386.
> > > It is same as I posted to LKML and Andi Kleen at '04/09/01.
> > >
> >
> > Can we not use the `alternative instruction' stuff to eliminate the runtime
> > test?
>
> Yes, we could. I suggested this to Kaigai-san earlier, but
> he decided that it was too complicated because he would have needed
> to add an additional alternative() macro with enough parameters.
>
> Given that atomic instructions are quite costly anyways and the jump
> should be very predictable he's probably right that it wouldn't
> be worth the effort.
>

Hm. Well if these things only have a few callsites then OK. But if we go
and do something like implementing atomic_inc() or up_read() or whatever
with atomic_add_return() then we'd need to do something from a codesize
POV.