Jan Beulich
2011-Nov-11 16:09 UTC
[Xen-devel] [PATCH] ia64: introduce atomic_{read,write}NN()
These are required to be able to build certain portions of common code.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/include/asm-ia64/linux-xen/asm/atomic.h
+++ b/xen/include/asm-ia64/linux-xen/asm/atomic.h
@@ -24,12 +24,9 @@ typedef struct { volatile __s32 counter;
typedef struct { volatile __s64 counter; } atomic64_t;
#ifndef XEN
+
#define ATOMIC_INIT(i) ((atomic_t) { (i) })
#define ATOMIC64_INIT(i) ((atomic64_t) { (i) })
-#else
-#define ATOMIC_INIT(i) { (i) }
-#define ATOMIC64_INIT(i) { (i) }
-#endif
#define atomic_read(v) ((v)->counter)
#define atomic64_read(v) ((v)->counter)
@@ -37,6 +34,55 @@ typedef struct { volatile __s64 counter;
#define atomic_set(v,i) (((v)->counter) = (i))
#define atomic64_set(v,i) (((v)->counter) = (i))
+#else
+
+#define ATOMIC_INIT(i) { (i) }
+#define ATOMIC64_INIT(i) { (i) }
+
+#define build_atomic_read(tag, type) \
+static inline type atomic_read##tag(const volatile type *addr) \
+{ \
+ type ret; \
+ asm volatile("ld%2.acq %0 = %1" \
+ : "=r" (ret) \
+ : "m" (*addr), "i" (sizeof(type))); \
+ return ret; \
+}
+
+#define build_atomic_write(tag, type) \
+static inline void atomic_write##tag(volatile type *addr, type val) \
+{ \
+ asm volatile("st%2.rel %0 = %1" \
+ : "=m" (*addr) \
+ : "r" (val), "i" (sizeof(type))); \
+}
+
+build_atomic_read(8, uint8_t)
+build_atomic_read(16, uint16_t)
+build_atomic_read(32, uint32_t)
+build_atomic_read(64, uint64_t)
+build_atomic_read(_int, int)
+build_atomic_read(_long, long)
+
+build_atomic_write(8, uint8_t)
+build_atomic_write(16, uint16_t)
+build_atomic_write(32, uint32_t)
+build_atomic_write(64, uint64_t)
+build_atomic_write(_int, int)
+build_atomic_write(_long, long)
+
+#define _atomic_read(v) ((v).counter)
+#define _atomic64_read(v) ((v).counter)
+#define atomic_read(v) atomic_read_int(&((v)->counter))
+#define atomic64_read(v) atomic_read_long(&((v)->counter))
+
+#define _atomic_set(v,i) (((v).counter) = (i))
+#define _atomic64_set(v,i) (((v).counter) = (i))
+#define atomic_set(v,i) atomic_write_int(&((v)->counter), i)
+#define atomic64_set(v,l) atomic_write_long(&((v)->counter), l)
+
+#endif
+
static __inline__ int
ia64_atomic_add (int i, atomic_t *v)
{
@@ -59,7 +105,7 @@ ia64_atomic64_add (__s64 i, atomic64_t *
do {
CMPXCHG_BUGCHECK(v);
- old = atomic_read(v);
+ old = atomic64_read(v);
new = old + i;
} while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic64_t)) != old);
return new;
@@ -87,7 +133,7 @@ ia64_atomic64_sub (__s64 i, atomic64_t *
do {
CMPXCHG_BUGCHECK(v);
- old = atomic_read(v);
+ old = atomic64_read(v);
new = old - i;
} while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic64_t)) != old);
return new;
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Keir Fraser
2011-Nov-11 16:40 UTC
Re: [Xen-devel] [PATCH] ia64: introduce atomic_{read,write}NN()
On 11/11/2011 16:09, "Jan Beulich" <JBeulich@suse.com> wrote:> These are required to be able to build certain portions of common code. > > Signed-off-by: Jan Beulich <jbeulich@suse.com>Acked-by: Keir Fraser <keir@xen.org>> --- a/xen/include/asm-ia64/linux-xen/asm/atomic.h > +++ b/xen/include/asm-ia64/linux-xen/asm/atomic.h > @@ -24,12 +24,9 @@ typedef struct { volatile __s32 counter; > typedef struct { volatile __s64 counter; } atomic64_t; > > #ifndef XEN > + > #define ATOMIC_INIT(i) ((atomic_t) { (i) }) > #define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) > -#else > -#define ATOMIC_INIT(i) { (i) } > -#define ATOMIC64_INIT(i) { (i) } > -#endif > > #define atomic_read(v) ((v)->counter) > #define atomic64_read(v) ((v)->counter) > @@ -37,6 +34,55 @@ typedef struct { volatile __s64 counter; > #define atomic_set(v,i) (((v)->counter) = (i)) > #define atomic64_set(v,i) (((v)->counter) = (i)) > > +#else > + > +#define ATOMIC_INIT(i) { (i) } > +#define ATOMIC64_INIT(i) { (i) } > + > +#define build_atomic_read(tag, type) \ > +static inline type atomic_read##tag(const volatile type *addr) \ > +{ \ > + type ret; \ > + asm volatile("ld%2.acq %0 = %1" \ > + : "=r" (ret) \ > + : "m" (*addr), "i" (sizeof(type))); \ > + return ret; \ > +} > + > +#define build_atomic_write(tag, type) \ > +static inline void atomic_write##tag(volatile type *addr, type val) \ > +{ \ > + asm volatile("st%2.rel %0 = %1" \ > + : "=m" (*addr) \ > + : "r" (val), "i" (sizeof(type))); \ > +} > + > +build_atomic_read(8, uint8_t) > +build_atomic_read(16, uint16_t) > +build_atomic_read(32, uint32_t) > +build_atomic_read(64, uint64_t) > +build_atomic_read(_int, int) > +build_atomic_read(_long, long) > + > +build_atomic_write(8, uint8_t) > +build_atomic_write(16, uint16_t) > +build_atomic_write(32, uint32_t) > +build_atomic_write(64, uint64_t) > +build_atomic_write(_int, int) > +build_atomic_write(_long, long) > + > +#define _atomic_read(v) ((v).counter) > +#define _atomic64_read(v) ((v).counter) > +#define atomic_read(v) atomic_read_int(&((v)->counter)) > +#define atomic64_read(v) atomic_read_long(&((v)->counter)) > + > +#define _atomic_set(v,i) (((v).counter) = (i)) > +#define _atomic64_set(v,i) (((v).counter) = (i)) > +#define atomic_set(v,i) atomic_write_int(&((v)->counter), i) > +#define atomic64_set(v,l) atomic_write_long(&((v)->counter), l) > + > +#endif > + > static __inline__ int > ia64_atomic_add (int i, atomic_t *v) > { > @@ -59,7 +105,7 @@ ia64_atomic64_add (__s64 i, atomic64_t * > > do { > CMPXCHG_BUGCHECK(v); > - old = atomic_read(v); > + old = atomic64_read(v); > new = old + i; > } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic64_t)) != old); > return new; > @@ -87,7 +133,7 @@ ia64_atomic64_sub (__s64 i, atomic64_t * > > do { > CMPXCHG_BUGCHECK(v); > - old = atomic_read(v); > + old = atomic64_read(v); > new = old - i; > } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic64_t)) != old); > return new; > > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
KUWAMURA Shin''ya
2011-Nov-25 01:52 UTC
Re: [Xen-devel] [PATCH] ia64: introduce atomic_{read, write}NN()
Hi Jan, Excuse me for too late response. Thank you for your work. But I have a question.>>>>> On Fri, 11 Nov 2011 16:09:25 +0000 >>>>> JBeulich@suse.com("Jan Beulich") said: > > +#define build_atomic_read(tag, type) \ > +static inline type atomic_read##tag(const volatile type *addr) \ > +{ \ > + type ret; \ > + asm volatile("ld%2.acq %0 = %1" \ > + : "=r" (ret) \ > + : "m" (*addr), "i" (sizeof(type))); \ > + return ret; \ > +} > + > +#define build_atomic_write(tag, type) \ > +static inline void atomic_write##tag(volatile type *addr, type val) \ > +{ \ > + asm volatile("st%2.rel %0 = %1" \ > + : "=m" (*addr) \ > + : "r" (val), "i" (sizeof(type))); \ > +}Why do you use explicitly ld.acq and st.rel? I think that volatile variables are always accessed using ld.acq and st.rel and they are not required. For example, The implementation of Linux is as follows: #define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic64_read(v) (*(volatile long *)&(v)->counter) Best regards, -- KUWAMURA Shin''ya
>>> On 25.11.11 at 02:52, "KUWAMURA Shin''ya" <kuwa@jp.fujitsu.com> wrote: > Hi Jan, > > Excuse me for too late response. Thank you for your work. > But I have a question. > >>>>>> On Fri, 11 Nov 2011 16:09:25 +0000 >>>>>> JBeulich@suse.com("Jan Beulich") said: >> >> +#define build_atomic_read(tag, type) \ >> +static inline type atomic_read##tag(const volatile type *addr) \ >> +{ \ >> + type ret; \ >> + asm volatile("ld%2.acq %0 = %1" \ >> + : "=r" (ret) \ >> + : "m" (*addr), "i" (sizeof(type))); \ >> + return ret; \ >> +} >> + >> +#define build_atomic_write(tag, type) \ >> +static inline void atomic_write##tag(volatile type *addr, type val) \ >> +{ \ >> + asm volatile("st%2.rel %0 = %1" \ >> + : "=m" (*addr) \ >> + : "r" (val), "i" (sizeof(type))); \ >> +} > > Why do you use explicitly ld.acq and st.rel? > I think that volatile variables are always accessed using ld.acq and > st.rel and they are not required.That would imply the compiler would attach these completers, but in inline assembly it obviously can''t.> For example, The implementation of Linux is as follows: > > #define atomic_read(v) (*(volatile int *)&(v)->counter) > #define atomic64_read(v) (*(volatile long *)&(v)->counter)Indeed - here the compiler is required to use acquire loads and release stores. The inline assembly has to mimic this behavior. Jan
On 25/11/2011 08:36, "Jan Beulich" <JBeulich@suse.com> wrote:>> Why do you use explicitly ld.acq and st.rel? >> I think that volatile variables are always accessed using ld.acq and >> st.rel and they are not required. > > That would imply the compiler would attach these completers, but in > inline assembly it obviously can''t. > >> For example, The implementation of Linux is as follows: >> >> #define atomic_read(v) (*(volatile int *)&(v)->counter) >> #define atomic64_read(v) (*(volatile long *)&(v)->counter) > > Indeed - here the compiler is required to use acquire loads and > release stores. The inline assembly has to mimic this behavior.I assume Jan was mimic''ing the use of inline asm in the x86 equivalents. I used asm for those, rather than straightforward volatile casting like in Linux''s ACCESS_ONCE() macro, just to be 100% sure about what is being emitted by the compiler. It''s not an especially compelling argument; arch/ia64 can implement them whichever way you see fit as far as I''m concerned. By the by, I''m also thing about switching the naming round to {read,write}N_atomic(), to avoid conflict with atomic_*() naming for manipulations of atomic_t. Then I can implement {read,write}_atomic() without the caller needing to hardcode the operation size. -- Keir