OSDN Git Service

2012-09-09 Thiago Macieira <thiago.macieira@intel.com>
authorbkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 10 Sep 2012 05:08:07 +0000 (05:08 +0000)
committerbkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 10 Sep 2012 05:08:07 +0000 (05:08 +0000)
PR libstdc++/54172
        * libsupc++/guard.cc (__cxa_guard_acquire): Exit the loop earlier if
        we detect that another thread has had success. Don't compare_exchange
        from a finished state back to a waiting state. Comment.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@191125 138bc75d-0d04-0410-961f-82ee72b054a4

libstdc++-v3/ChangeLog
libstdc++-v3/libsupc++/guard.cc

index cb4aa52..6726f8e 100644 (file)
@@ -1,3 +1,10 @@
+2012-09-09  Thiago Macieira  <thiago.macieira@intel.com>
+
+       PR libstdc++/54172
+        * libsupc++/guard.cc (__cxa_guard_acquire): Exit the loop earlier if
+        we detect that another thread has had success. Don't compare_exchange
+        from a finished state back to a waiting state. Comment.
+
 2012-09-09  Jonathan Wakely  <jwakely.gcc@gmail.com>
 
        PR libstdc++/54388
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;
               }