OSDN Git Service

2012-09-09 Thiago Macieira <thiago.macieira@intel.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / libsupc++ / guard.cc
index adc9608..60165cd 100644 (file)
@@ -244,13 +244,13 @@ namespace __cxxabiv1
     if (__gthread_active_p ())
       {
        int *gi = (int *) (void *) g;
-       int expected(0);
        const int guard_bit = _GLIBCXX_GUARD_BIT;
        const int pending_bit = _GLIBCXX_GUARD_PENDING_BIT;
        const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
 
        while (1)
          {
+           int expected(0);
            if (__atomic_compare_exchange_n(gi, &expected, pending_bit, false,
                                            __ATOMIC_ACQ_REL,
                                            __ATOMIC_RELAXED))
@@ -264,13 +264,26 @@ namespace __cxxabiv1
                // Already initialized.
                return 0;       
              }
+
             if (expected == pending_bit)
               {
+                // Use acquire here.
                 int newv = expected | waiting_bit;
                 if (!__atomic_compare_exchange_n(gi, &expected, newv, false,
                                                  __ATOMIC_ACQ_REL, 
-                                                 __ATOMIC_RELAXED))
-                  continue;
+                                                 __ATOMIC_ACQUIRE))
+                  {
+                    if (expected == guard_bit)
+                      {
+                        // Make a thread that failed to set the
+                        // waiting bit exit the function earlier,
+                        // if it detects that another thread has
+                        // successfully finished initialising.
+                        return 0;
+                      }
+                    if (expected == 0)
+                      continue;
+                  }
                 
                 expected = newv;
               }