This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Fw: [patch] Make std::tr1::shared_ptr thread-safe.


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]