mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
385c06817b
commit
fa129f20b3
|
|
@ -1,3 +1,10 @@
|
||||||
|
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
|
||||||
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
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue