Date: Sat, 3 Mar 2012 17:57:37 +0100 From: Olivier Houchard <cognet@ci0.org> To: Bruce Evans <brde@optusnet.com.au> Cc: svn-src-projects@FreeBSD.org, src-committers@FreeBSD.org Subject: Re: svn commit: r232456 - projects/armv6/sys/arm/include Message-ID: <20120303165737.GA26775@ci0.org> In-Reply-To: <20120304011922.G5792@besplex.bde.org> References: <201203031223.q23CN73s081573@svn.freebsd.org> <20120304011922.G5792@besplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--tThc/1wpZn/ma/RB Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Sun, Mar 04, 2012 at 02:14:46AM +1100, Bruce Evans wrote: > On Sat, 3 Mar 2012, Olivier Houchard wrote: > > >Log: > > Get the right casts for long operations > > I think you mean "the wrong casts". i386 was broken similarly, but amd64 > is still correct -- amd64 has no casts at all in its big list of #defines > (but the list is excessively complete, with must cases unused). > Hi Bruce, I understand your concerns. These casts are indeed bogus, and will become even more when we'll support 64bits arm, which should come with 64bits long. I can't do much for long which should be 64bits even on 32bits machines, that is set in stone now, however I can certainly remove the bogus casts. Would the attached patch be OK for you ? It duplicates the various atomic functions to add a _long variant (for armv6 at least, for armv5 it just introduces _long variants which calls the _32 version, but at least it should catch any signedness/type error), and it removes the bogus casts for the ptr version, and just #defines it to the __32 version, since that's what uintptr_t is. Regards, Olivier --tThc/1wpZn/ma/RB Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="atomic.h.diff" Index: atomic.h =================================================================== --- atomic.h (revision 232462) +++ atomic.h (working copy) @@ -74,6 +74,21 @@ #endif } +#define ATOMIC_ACQ_REL_LONG(NAME) \ +static __inline void \ +atomic_##NAME##_acq_long(__volatile u_long *p, u_long v) \ +{ \ + atomic_##NAME##_long(p, v); \ + __do_dmb(); \ +} \ + \ +static __inline void \ +atomic_##NAME##_rel_long(__volatile u_long *p, u_long v) \ +{ \ + __do_dmb(); \ + atomic_##NAME##_long(p, v); \ +} + #define ATOMIC_ACQ_REL(NAME, WIDTH) \ static __inline void \ atomic_##NAME##_acq_##WIDTH(__volatile uint##WIDTH##_t *p, uint##WIDTH##_t v)\ @@ -105,6 +120,21 @@ } static __inline void +atomic_set_long(volatile u_long *address, u_long setmask) +{ + u_long tmp = 0, tmp2 = 0; + + __asm __volatile("1: ldrex %0, [%2]\n" + "orr %0, %0, %3\n" + "strex %1, %0, [%2]\n" + "cmp %1, #0\n" + "bne 1b\n" + : "=&r" (tmp), "+r" (tmp2) + , "+r" (address), "+r" (setmask) : : "memory"); + +} + +static __inline void atomic_clear_32(volatile uint32_t *address, uint32_t setmask) { uint32_t tmp = 0, tmp2 = 0; @@ -118,6 +148,20 @@ ,"+r" (address), "+r" (setmask) : : "memory"); } +static __inline void +atomic_clear_long(volatile u_long *address, u_long setmask) +{ + u_long tmp = 0, tmp2 = 0; + + __asm __volatile("1: ldrex %0, [%2]\n" + "bic %0, %0, %3\n" + "strex %1, %0, [%2]\n" + "cmp %1, #0\n" + "bne 1b\n" + : "=&r" (tmp), "+r" (tmp2) + ,"+r" (address), "+r" (setmask) : : "memory"); +} + static __inline u_int32_t atomic_cmpset_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval) { @@ -137,15 +181,43 @@ return (ret); } +static __inline u_long +atomic_cmpset_long(volatile u_long *p, volatile u_long cmpval, volatile u_long newval) +{ + u_long ret; + + __asm __volatile("1: ldrex %0, [%1]\n" + "cmp %0, %2\n" + "movne %0, #0\n" + "bne 2f\n" + "strex %0, %3, [%1]\n" + "cmp %0, #0\n" + "bne 1b\n" + "moveq %0, #1\n" + "2:" + : "=&r" (ret) + ,"+r" (p), "+r" (cmpval), "+r" (newval) : : "memory"); + return (ret); +} + static __inline u_int32_t atomic_cmpset_acq_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval) { - int ret = atomic_cmpset_32(p, cmpval, newval); + u_int32_t ret = atomic_cmpset_32(p, cmpval, newval); __do_dmb(); return (ret); } +static __inline u_long +atomic_cmpset_acq_long(volatile u_long *p, volatile u_long cmpval, volatile u_long newval) +{ + u_long ret = atomic_cmpset_long(p, cmpval, newval); + + __do_dmb(); + return (ret); +} + static __inline u_int32_t atomic_cmpset_rel_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval) { @@ -154,6 +226,15 @@ return (atomic_cmpset_32(p, cmpval, newval)); } +static __inline u_long +atomic_cmpset_rel_long(volatile u_long *p, volatile u_long cmpval, volatile u_long newval) +{ + + __do_dmb(); + return (atomic_cmpset_long(p, cmpval, newval)); +} + + static __inline void atomic_add_32(volatile u_int32_t *p, u_int32_t val) { @@ -169,6 +250,20 @@ } static __inline void +atomic_add_long(volatile u_long *p, u_long val) +{ + u_long tmp = 0, tmp2 = 0; + + __asm __volatile("1: ldrex %0, [%2]\n" + "add %0, %0, %3\n" + "strex %1, %0, [%2]\n" + "cmp %1, #0\n" + "bne 1b\n" + : "=&r" (tmp), "+r" (tmp2) + ,"+r" (p), "+r" (val) : : "memory"); +} + +static __inline void atomic_subtract_32(volatile u_int32_t *p, u_int32_t val) { uint32_t tmp = 0, tmp2 = 0; @@ -182,13 +277,31 @@ ,"+r" (p), "+r" (val) : : "memory"); } +static __inline void +atomic_subtract_long(volatile u_long *p, u_long val) +{ + u_long tmp = 0, tmp2 = 0; + __asm __volatile("1: ldrex %0, [%2]\n" + "sub %0, %0, %3\n" + "strex %1, %0, [%2]\n" + "cmp %1, #0\n" + "bne 1b\n" + : "=&r" (tmp), "+r" (tmp2) + ,"+r" (p), "+r" (val) : : "memory"); +} + ATOMIC_ACQ_REL(clear, 32) ATOMIC_ACQ_REL(add, 32) ATOMIC_ACQ_REL(subtract, 32) ATOMIC_ACQ_REL(set, 32) +ATOMIC_ACQ_REL_LONG(clear) +ATOMIC_ACQ_REL_LONG(add) +ATOMIC_ACQ_REL_LONG(subtract) +ATOMIC_ACQ_REL_LONG(set) #undef ATOMIC_ACQ_REL +#undef ATOMIC_ACQ_REL_LONG static __inline uint32_t atomic_fetchadd_32(volatile uint32_t *p, uint32_t val) @@ -238,6 +351,53 @@ *p = v; } +static __inline u_long +atomic_fetchadd_long(volatile u_long *p, u_long val) +{ + u_long tmp = 0, tmp2 = 0, ret = 0; + + __asm __volatile("1: ldrex %0, [%3]\n" + "add %1, %0, %4\n" + "strex %2, %1, [%3]\n" + "cmp %2, #0\n" + "bne 1b\n" + : "+r" (ret), "=&r" (tmp), "+r" (tmp2) + ,"+r" (p), "+r" (val) : : "memory"); + return (ret); +} + +static __inline u_long +atomic_readandclear_long(volatile u_long *p) +{ + u_long ret, tmp = 0, tmp2 = 0; + + __asm __volatile("1: ldrex %0, [%3]\n" + "mov %1, #0\n" + "strex %2, %1, [%3]\n" + "cmp %2, #0\n" + "bne 1b\n" + : "=r" (ret), "=&r" (tmp), "+r" (tmp2) + ,"+r" (p) : : "memory"); + return (ret); +} + +static __inline u_long +atomic_load_acq_long(volatile u_long *p) +{ + u_long v; + + v = *p; + __do_dmb(); + return (v); +} + +static __inline void +atomic_store_rel_long(volatile u_long *p, u_long v) +{ + + __do_dmb(); + *p = v; +} #else /* < armv6 */ #define __with_interrupts_disabled(expr) \ @@ -489,9 +649,64 @@ #define atomic_subtract_rel_32 atomic_subtract_32 #define atomic_subtract_acq_32 atomic_subtract_32 #define atomic_store_rel_32 atomic_store_32 +#define atomic_store_rel_long atomic_store_long #define atomic_load_acq_32 atomic_load_32 +#define atomic_load_acq_long atomic_load_long #undef __with_interrupts_disabled +static __inline void +atomic_add_long(volatile u_long *p, u_long v) +{ + + atomic_add_32((volatile uint32_t *)p, (volatile uint32_t)v); +} + +static __inline void +atomic_clear_long(volatile u_long *p, u_long v) +{ + + atomic_clear_32((volatile uint32_t *)p, (volatile uint32_t)v); +} + +static __inline int +atomic_cmpset_long(volatile u_long *dst, u_long old, u_long newe) +{ + + return (atomic_cmpset_32((volatile uint32_t *)dst, + (volatile uint32_t)old, (volatile uint32_t)newe)); +} + +static __inline u_long +atomic_fetchadd_long(volatile u_long *p, u_long v) +{ + + return (atomic_fetchadd_32((volatile uint32_t *)p, + (volatile uint32_t)v)); +} + +static __inline void +atomic_readandclear_long(volatile u_long *p) +{ + + atomic_readandclear_32((volatile uint32_t *)p); +} + +static __inline void +atomic_set_long(volatile u_long *p, u_long v) +{ + + atomic_set_32((volatile uint32_t *)p, (volatile uint32_t)v); +} + +static __inline void +atomic_subtract_long(volatile u_long *p, u_long v) +{ + + atomic_subtract_32((volatile uint32_t *)p, (volatile uint32_t)v); +} + + + #endif /* _LOCORE */ #endif /* Arch >= v6 */ @@ -509,57 +724,24 @@ *dst = src; } -#define atomic_set_long(p, v) \ - atomic_set_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_set_acq_long(p, v) \ - atomic_set_acq_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_set_rel_long(p, v) \ - atomic_set_rel_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_clear_long(p, v) \ - atomic_clear_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_clear_acq_long(p, v) \ - atomic_clear_acq_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_clear_rel_long(p, v) \ - atomic_clear_rel_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_add_long(p, v) \ - atomic_add_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_add_acq_long(p, v) \ - atomic_add_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_add_rel_long(p, v) \ - atomic_add_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_subtract_long(p, v) \ - atomic_subtract_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_subtract_acq_long(p, v) \ - atomic_subtract_acq_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_subtract_rel_long(p, v) \ - atomic_subtract_rel_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_cmpset_long(p, cmpval, newval) \ - atomic_cmpset_32((volatile u_int *)(p), (u_int)(cmpval), \ - (u_int)(newval)) -#define atomic_cmpset_acq_long(p, cmpval, newval) \ - atomic_cmpset_acq_32((volatile u_int *)(p), (u_int)(cmpval), \ - (u_int)(newval)) -#define atomic_cmpset_rel_long(p, cmpval, newval) \ - atomic_cmpset_rel_32((volatile u_int *)(p), (u_int)(cmpval), \ - (u_int)(newval)) -#define atomic_load_acq_long(p) \ - (u_long)atomic_load_acq_32((volatile u_int *)(p)) -#define atomic_store_rel_long(p, v) \ - atomic_store_rel_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_fetchadd_long(p, v) \ - atomic_fetchadd_32((volatile u_int *)(p), (u_int)(v)) -#define atomic_readandclear_long(p) \ - atomic_readandclear_32((volatile u_int *)(p)) +static __inline int +atomic_load_long(volatile u_long *v) +{ + return (*v); +} +static __inline void +atomic_store_long(volatile u_long *dst, u_long src) +{ + *dst = src; +} + #define atomic_clear_ptr atomic_clear_32 #define atomic_set_ptr atomic_set_32 -#define atomic_cmpset_ptr(dst, old, new) \ - atomic_cmpset_32((volatile u_int *)(dst), (u_int)(old), (u_int)(new)) -#define atomic_cmpset_rel_ptr(dst, old, new) \ - atomic_cmpset_rel_32((volatile u_int *)(dst), (u_int)(old), (u_int)(new)) -#define atomic_cmpset_acq_ptr(dst, old, new) \ - atomic_cmpset_acq_32((volatile u_int *)(dst), (u_int)(old), (u_int)(new)) +#define atomic_cmpset_ptr atomic_cmpset_32 +#define atomic_cmpset_rel_ptr atomic_cmpset_rel_32 +#define atomic_cmpset_acq_ptr atomic_cmpset_acq_32 #define atomic_store_ptr atomic_store_32 #define atomic_store_rel_ptr atomic_store_ptr --tThc/1wpZn/ma/RB--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120303165737.GA26775>