Commit fa129f20 by Thiago Macieira Committed by Benjamin Kosnik

re PR libstdc++/54172 (__cxa_guard_acquire thread-safety issue)

2012-09-06  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.

From-SVN: r191042
parent 385c0681
2012-09-06 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-05 François Dumont <fdumont@gcc.gnu.org> 2012-09-05 François Dumont <fdumont@gcc.gnu.org>
PR libstdc++/54296 PR libstdc++/54296
......
...@@ -244,13 +244,13 @@ namespace __cxxabiv1 ...@@ -244,13 +244,13 @@ namespace __cxxabiv1
if (__gthread_active_p ()) if (__gthread_active_p ())
{ {
int *gi = (int *) (void *) g; int *gi = (int *) (void *) g;
int expected(0);
const int guard_bit = _GLIBCXX_GUARD_BIT; const int guard_bit = _GLIBCXX_GUARD_BIT;
const int pending_bit = _GLIBCXX_GUARD_PENDING_BIT; const int pending_bit = _GLIBCXX_GUARD_PENDING_BIT;
const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT; const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
while (1) while (1)
{ {
int expected(0);
if (__atomic_compare_exchange_n(gi, &expected, pending_bit, false, if (__atomic_compare_exchange_n(gi, &expected, pending_bit, false,
__ATOMIC_ACQ_REL, __ATOMIC_ACQ_REL,
__ATOMIC_RELAXED)) __ATOMIC_RELAXED))
...@@ -264,13 +264,26 @@ namespace __cxxabiv1 ...@@ -264,13 +264,26 @@ namespace __cxxabiv1
// Already initialized. // Already initialized.
return 0; return 0;
} }
if (expected == pending_bit) if (expected == pending_bit)
{ {
// Use acquire here.
int newv = expected | waiting_bit; int newv = expected | waiting_bit;
if (!__atomic_compare_exchange_n(gi, &expected, newv, false, if (!__atomic_compare_exchange_n(gi, &expected, newv, false,
__ATOMIC_ACQ_REL, __ATOMIC_ACQ_REL,
__ATOMIC_RELAXED)) __ATOMIC_ACQUIRE))
continue; {
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; expected = newv;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment