diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2012-09-06 20:31:08 +0000 |
---|---|---|
committer | Benjamin Kosnik <bkoz@gcc.gnu.org> | 2012-09-06 20:31:08 +0000 |
commit | fa129f20b3d956e6e8a3a017c57e0c62a8ba3002 (patch) | |
tree | fc46d4517215160085224e179732892943443922 | |
parent | 385c06817b589184432e39c9cd318ec7e32d3de4 (diff) | |
download | gcc-fa129f20b3d956e6e8a3a017c57e0c62a8ba3002.zip gcc-fa129f20b3d956e6e8a3a017c57e0c62a8ba3002.tar.gz gcc-fa129f20b3d956e6e8a3a017c57e0c62a8ba3002.tar.bz2 |
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
-rw-r--r-- | libstdc++-v3/ChangeLog | 7 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/guard.cc | 19 |
2 files changed, 23 insertions, 3 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 707e474..f3a5852 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -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> PR libstdc++/54296 diff --git a/libstdc++-v3/libsupc++/guard.cc b/libstdc++-v3/libsupc++/guard.cc index adc9608..60165cd 100644 --- a/libstdc++-v3/libsupc++/guard.cc +++ b/libstdc++-v3/libsupc++/guard.cc @@ -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; } |