https://gcc.gnu.org/g:a7ad4bee6fe7cd77aceb6e86380dcaeb6da82791

commit r17-2080-ga7ad4bee6fe7cd77aceb6e86380dcaeb6da82791
Author: Jonathan Wakely <[email protected]>
Date:   Wed Jul 1 19:44:41 2026 +0100

    libstdc++: Use atomic store for num_leap_seconds in tzdb.cc
    
    Although NumLeapSeconds::set_locked is always called with list_mutex()
    locked, if ATOMIC_INT_LOCK_FREE == 2 then readers ofthe variable will be
    loading it without list_mutex() locked. We need to use an atomic store
    even if the lock is held.
    
    Also simplify the non-atomic version of NumLeapSeconds::set to just set
    the variable instead of indirecting via set_locked.
    
    libstdc++-v3/ChangeLog:
    
            * src/c++20/tzdb.cc (_Node::NumLeapSeconds::set_locked)
            [ATOMIC_INT_LOCK_FREE == 2]: Use atomic store.
            (_Node::NumLeapSeconds::set) [ATOMIC_INT_LOCK_FREE != 2]: Set
            value directly instead of calling set_locked.
    
    Reviewed-by: Tomasz KamiƄski <[email protected]>

Diff:
---
 libstdc++-v3/src/c++20/tzdb.cc | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/src/c++20/tzdb.cc b/libstdc++-v3/src/c++20/tzdb.cc
index 1aae07033f73..998a363151dc 100644
--- a/libstdc++-v3/src/c++20/tzdb.cc
+++ b/libstdc++-v3/src/c++20/tzdb.cc
@@ -1463,16 +1463,22 @@ struct tzdb_list::_Node::NumLeapSeconds
     ref.store(val, memory_order::release);
 #else
     lock_guard<mutex> l(list_mutex());
-    set_locked(val, l);
+    count = val;
 #endif
   }
 
   void
   set_locked(unsigned val, const lock_guard<mutex>&)
   {
+#if ATOMIC_INT_LOCK_FREE == 2
+    // Even though the caller locked the mutex, we still need to use an
+    // atomic store in this case, because there could be concurrent loads.
+    set(val);
+#else
     // The only caller of this function locks list_mutex() so we would
     // deadlock if we locked it again here.
     count = val;
+#endif
   }
 
 private:

Reply via email to