re PR libgcc/48076 (Unsafe double checked locking in __emutls_get_address)
authorRichard Henderson <rth@redhat.com>
Wed, 28 Nov 2012 21:01:26 +0000 (13:01 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 28 Nov 2012 21:01:26 +0000 (13:01 -0800)
PR libgcc/48076
        * emutls.c (__emutls_get_address): Avoid race condition between
        obj->loc.offset read and emutls_key initialization.

From-SVN: r193907

libgcc/ChangeLog
libgcc/emutls.c

index c547dcb06c6df26eee58e2f0c74d8ec51417b792..6506e85e89fa5849049e13784bde53d0c427d82f 100644 (file)
@@ -1,3 +1,9 @@
+2012-11-28  Richard Henderson  <rth@redhat.com>
+
+       PR libgcc/48076
+       * emutls.c (__emutls_get_address): Avoid race condition between
+       obj->loc.offset read and emutls_key initialization.
+       
 2012-11-22  Georg-Johann Lay  <avr@gjlay.de>
 
        Adjust decimal point of signed accum mode to GCC default.
index 22ea4403edbd564226d966c3921e2dc049baf81f..f1b653b7d542a29a970bb1b7409f8945288bdb1a 100644 (file)
@@ -136,7 +136,7 @@ __emutls_get_address (struct __emutls_object *obj)
 #ifndef __GTHREADS
   abort ();
 #else
-  pointer offset = obj->loc.offset;
+  pointer offset = __atomic_load_n (&obj->loc.offset, __ATOMIC_ACQUIRE);
 
   if (__builtin_expect (offset == 0, 0))
     {
@@ -147,7 +147,7 @@ __emutls_get_address (struct __emutls_object *obj)
       if (offset == 0)
        {
          offset = ++emutls_size;
-         obj->loc.offset = offset;
+         __atomic_store_n (&obj->loc.offset, offset, __ATOMIC_RELEASE);
        }
       __gthread_mutex_unlock (&emutls_mutex);
     }