From f4919e4a824372c70af64a80e16db4de995bdc3c Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@redhat.com>
Date: Wed, 28 Nov 2012 13:01:26 -0800
Subject: [PATCH] re PR libgcc/48076 (Unsafe double checked locking in
 __emutls_get_address)

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 | 6 ++++++
 libgcc/emutls.c  | 4 ++--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index c547dcb06c6d..6506e85e89fa 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -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.
diff --git a/libgcc/emutls.c b/libgcc/emutls.c
index 22ea4403edbd..f1b653b7d542 100644
--- a/libgcc/emutls.c
+++ b/libgcc/emutls.c
@@ -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);
     }
-- 
GitLab