This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


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

Apparent multithread problems in basic_string template


We are using strings in a multi-threaded program here.  We had a problem because
 we were
not defining the _PTHREADS macro in order to use the right allocator.  We fixed
this allocator
problem. but while investigating the problem a colleague and I found what
appears to be another
problem with reference counting.

The end of this message contains a portion of the code for the basic_string
template from the sources for gcc-2.95.2.
The code shown begins on line 75 of bastring.h.  It contains definitions for
basic_string::grab() and basic_string::delete().

Except for the return value in grab(), it appears that these methods are more or
 less inverses of each other.  grab() increments
the reference count, and release() decrements it.

From looking at the code, it appears that release() has provisions to make sure
that the decrement of the reference
count behaves in an atomic fashion for Intel and Sparc machines.  It uses
assembly code for this, presumably for efficiency,
and I would guess that other architectures don't have the code to avoid paying
the cost of a mutex lock.  The corresponding
code for the increment of the reference count does not do anything to guarantee
that the operation behaves atomically.

A question and comment:

 - Shouldn't the increment be protected like the decrement, or have I
misunderstood somethng?

 - Perhaps the special code for decrementing should be compiled conditionally
only for multi-threaded
programs.

Please forgive me if I've misunderstood what's going on.  Thanks for any help
you can provide.

Kevin

-------------------------------------------------------------------------------------------------------------

// Code from std/bastring.h in gcc-2.95.2 library

charT* grab () { if (selfish) return clone (); ++ref; return data (); }
#if defined __i486__ || defined __i586__ || defined __i686__
    void release ()
      {
     size_t __val;
     // This opcode exists as a .byte instead of as a mnemonic for the
     // benefit of SCO OpenServer 5.  The system assembler (which is
     // essentially required on this target) can't assemble xaddl in
     //COFF mode.
     asm (".byte 0xf0, 0x0f, 0xc1, 0x02" // lock; xaddl %eax, (%edx)
         : "=a" (__val)
         : "0" (-1), "m" (ref), "d" (&ref)
         : "memory");

     if (__val == 1)
       delete this;
      }
#elif defined __sparcv9__
    void release ()
      {
     size_t __newval, __oldval = ref;
     do
       {
         __newval = __oldval - 1;
         __asm__ ("cas   [%4], %2, %0"
               : "=r" (__oldval), "=m" (ref)
               : "r" (__oldval), "m" (ref), "r"(&(ref)), "0" (__newval));
       }
     while (__newval != __oldval);

     if (__oldval == 0)
       delete this;
      }
#else
    void release () { if (--ref == 0) delete this; }
#endif

 **************************************************************************
The information contained herein is confidential and is intended solely
for the addressee(s).  It shall not be construed as a recommendation to
buy or sell any security.  Any unauthorized access, use, reproduction,
disclosure or dissemination is prohibited.

Neither SOCIETE GENERALE nor any of its subsidiaries or affiliates
shall assume any legal liability or responsibility for any incorrect,
misleading or altered information contained herein.
 **************************************************************************




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