Fw: [patch] Make std::tr1::shared_ptr thread-safe.
Peter Dimov
pdimov@mmltd.net
Fri Apr 1 15:27:00 GMT 2005
Paolo Carlini wrote:
> Alexander Terekhov wrote:
>
>> It is about msync semantics of exchange_and_add(). If you rely on
>> msync semantics which it doesn't provide, your code is broken. If it
>> is guaranteed to provide "fully-fenced" semantics (mimicking Intel's
>> __sync_fetch_and_add()), then (apart from unneeded overhead) you're
>> fine.
>>
>>
> Ok. Therefore, can well be the case that the port maintainers that
> provided (inline assembly ) implementations of exchange_and_add for
> the various archs chose to provide "fully-fenced" semantics, right?
This is possible, but unlikely. Unless there is documentation stating that
__exchange_and_add needs to be fully fenced (which is a stronger requirement
than necessary), the port maintainers are free to not implement a
fully-fenced __exchange_and_add.
> Maybe you can volunteer to check a few of those implementations? Maybe
> ia64? For your convenience, reads, simply (exploiting built-ins in
> such case):
>
> namespace __gnu_cxx
> {
> _Atomic_word
> __attribute__ ((__unused__))
> __exchange_and_add(volatile _Atomic_word* __mem, int __val)
> { return __sync_fetch_and_add(__mem, __val); }
>
> void
> __attribute__ ((__unused__))
> __atomic_add(volatile _Atomic_word* __mem, int __val)
> { __sync_fetch_and_add(__mem, __val); }
> }
The __sync_* IA64 intrinsics are fully-fenced, as far as I know.
> You can find all of them under config/cpu/*/atomicity.h.
Some of the interesting ones are:
*** Alpha ***:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc%2b%2b-v3/config/cpu/alpha/atomicity.h?rev=1.6&content-type=text/x-cvsweb-markup
namespace __gnu_cxx
{
_Atomic_word
__attribute__ ((__unused__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val)
{
register int __result, __tmp;
__asm__ __volatile__ (
"\n$Lxadd_%=:\n\t"
"ldl_l %0,%3\n\t"
"addl %0,%4,%1\n\t"
"stl_c %1,%2\n\t"
"beq %1,$Lxadd_%=\n\t"
"mb"
: "=&r"(__result), "=&r"(__tmp), "=m"(*__mem)
: "m" (*__mem), "r"(__val));
return __result;
}
void
__attribute__ ((__unused__))
__atomic_add(volatile _Atomic_word* __mem, int __val)
{
register _Atomic_word __result;
__asm__ __volatile__ (
"\n$Ladd_%=:\n\t"
"ldl_l %0,%2\n\t"
"addl %0,%3,%0\n\t"
"stl_c %0,%1\n\t"
"beq %0,$Ladd_%=\n\t"
"mb"
: "=&r"(__result), "=m"(*__mem)
: "m" (*__mem), "r"(__val));
}
} // namespace __gnu_cxx
*** PowerPC ***:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc%2b%2b-v3/config/cpu/powerpc/atomicity.h?rev=1.9&content-type=text/x-cvsweb-markup
#ifdef __PPC405__
#define _STWCX "sync \n\tstwcx. "
#else
#define _STWCX "stwcx. "
#endif
namespace __gnu_cxx
{
_Atomic_word
__attribute__ ((__unused__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val)
{
_Atomic_word __tmp, __res;
__asm__ __volatile__ (
"/* Inline exchange & add */\n"
"0:\t"
"lwarx %0,0,%3 \n\t"
"add%I4 %1,%0,%4 \n\t"
_STWCX " %1,0,%3 \n\t"
"bne- 0b \n\t"
"/* End exchange & add */"
: "=&b"(__res), "=&r"(__tmp), "=m" (*__mem)
: "r" (__mem), "Ir"(__val), "m" (*__mem)
: "cr0");
return __res;
}
void
__attribute__ ((__unused__))
__atomic_add(volatile _Atomic_word* __mem, int __val)
{
_Atomic_word __tmp;
__asm__ __volatile__ (
"/* Inline atomic add */\n"
"0:\t"
"lwarx %0,0,%2 \n\t"
"add%I3 %0,%0,%3 \n\t"
_STWCX " %0,0,%2 \n\t"
"bne- 0b \n\t"
"/* End atomic add */"
: "=&b"(__tmp), "=m" (*__mem)
: "r" (__mem), "Ir"(__val), "m" (*__mem)
: "cr0");
}
} // namespace __gnu_cxx
*** Sparc ***:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc%2b%2b-v3/config/cpu/sparc/atomicity.h?rev=1.7&content-type=text/x-cvsweb-markup
namespace __gnu_cxx
{
#ifdef __arch64__
_Atomic_word
__attribute__ ((__unused__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val)
{
_Atomic_word __tmp1, __tmp2;
_Atomic_word __val_extended = __val;
__asm__ __volatile__("1: ldx [%3], %0\n\t"
" add %0, %4, %1\n\t"
" casx [%3], %0, %1\n\t"
" sub %0, %1, %0\n\t"
" brnz,pn %0, 1b\n\t"
" nop"
: "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__mem)
: "r" (__mem), "r" (__val_extended), "m" (*__mem));
return __tmp2;
}
void
__attribute__ ((__unused__))
__atomic_add(volatile _Atomic_word* __mem, int __val)
{
_Atomic_word __tmp1, __tmp2;
_Atomic_word __val_extended = __val;
__asm__ __volatile__("1: ldx [%3], %0\n\t"
" add %0, %4, %1\n\t"
" casx [%3], %0, %1\n\t"
" sub %0, %1, %0\n\t"
" brnz,pn %0, 1b\n\t"
" nop"
: "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__mem)
: "r" (__mem), "r" (__val_extended), "m" (*__mem));
}
#else /* __arch32__ */
template<int __inst>
struct _Atomicity_lock
{
static unsigned char _S_atomicity_lock;
};
template<int __inst>
unsigned char _Atomicity_lock<__inst>::_S_atomicity_lock = 0;
template unsigned char _Atomicity_lock<0>::_S_atomicity_lock;
_Atomic_word
__attribute__ ((__unused__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val)
{
_Atomic_word __result, __tmp;
__asm__ __volatile__("1: ldstub [%1], %0\n\t"
" cmp %0, 0\n\t"
" bne 1b\n\t"
" nop"
: "=&r" (__tmp)
: "r" (&_Atomicity_lock<0>::_S_atomicity_lock)
: "memory");
__result = *__mem;
*__mem += __val;
__asm__ __volatile__("stb %%g0, [%0]"
: /* no outputs */
: "r" (&_Atomicity_lock<0>::_S_atomicity_lock)
: "memory");
return __result;
}
void
__attribute__ ((__unused__))
__atomic_add(volatile _Atomic_word* __mem, int __val)
{
_Atomic_word __tmp;
__asm__ __volatile__("1: ldstub [%1], %0\n\t"
" cmp %0, 0\n\t"
" bne 1b\n\t"
" nop"
: "=&r" (__tmp)
: "r" (&_Atomicity_lock<0>::_S_atomicity_lock)
: "memory");
*__mem += __val;
__asm__ __volatile__("stb %%g0, [%0]"
: /* no outputs */
: "r" (&_Atomicity_lock<0>::_S_atomicity_lock)
: "memory");
}
#endif /* __arch32__ */
} // namespace __gnu_cxx
*** MIPS ***:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc%2b%2b-v3/config/cpu/mips/atomicity.h?rev=1.10&content-type=text/x-cvsweb-markup
namespace __gnu_cxx
{
_Atomic_word
__attribute__ ((__unused__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val)
{
_Atomic_word __result, __tmp;
__asm__ __volatile__
("/* Inline exchange & add */\n\t"
"1:\n\t"
".set push\n\t"
#if _MIPS_SIM == _ABIO32
".set mips2\n\t"
#endif
"ll %0,0(%2)\n\t"
"addu %1,%3,%0\n\t"
"sc %1,0(%2)\n\t"
".set pop\n\t"
"beqz %1,1b\n\t"
"/* End exchange & add */"
: "=&r"(__result), "=&r"(__tmp)
: "r"(__mem), "r"(__val)
: "memory" );
return __result;
}
void
__attribute__ ((__unused__))
__atomic_add(volatile _Atomic_word* __mem, int __val)
{
_Atomic_word __result;
__asm__ __volatile__
("/* Inline atomic add */\n\t"
"1:\n\t"
".set push\n\t"
#if _MIPS_SIM == _ABIO32
".set mips2\n\t"
#endif
"ll %0,0(%1)\n\t"
"addu %0,%2,%0\n\t"
"sc %0,0(%1)\n\t"
".set pop\n\t"
"beqz %0,1b\n\t"
"/* End atomic add */"
: "=&r"(__result)
: "r"(__mem), "r"(__val)
: "memory" );
}
} // namespace __gnu_cxx
More information about the Libstdc++
mailing list