re PR libgcc/71744 (Concurrently throwing exceptions is not scalable)
authorJakub Jelinek <jakub@redhat.com>
Fri, 16 Sep 2016 19:17:47 +0000 (21:17 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 16 Sep 2016 19:17:47 +0000 (21:17 +0200)
PR libgcc/71744
* unwind-dw2-fde.c (ATOMIC_FDE_FAST_PATH): Define if __register_frame*
is not the primary registry and atomics are available.
(any_objects_registered): New variable.
(__register_frame_info_bases, __register_frame_info_table_bases):
Atomically store 1 to any_objects_registered after registering first
unwind info.
(_Unwind_Find_FDE): Return early if any_objects_registered is 0.

From-SVN: r240193

libgcc/ChangeLog
libgcc/unwind-dw2-fde.c

index 73e3a4f6d6f48029bb332e3589b1fc375adcffe1..b5c7ea4a9af1143ca9658cad521773daf9794028 100644 (file)
@@ -1,3 +1,14 @@
+2016-09-16  Jakub Jelinek  <jakub@redhat.com>
+
+       PR libgcc/71744
+       * unwind-dw2-fde.c (ATOMIC_FDE_FAST_PATH): Define if __register_frame*
+       is not the primary registry and atomics are available.
+       (any_objects_registered): New variable.
+       (__register_frame_info_bases, __register_frame_info_table_bases):
+       Atomically store 1 to any_objects_registered after registering first
+       unwind info.
+       (_Unwind_Find_FDE): Return early if any_objects_registered is 0.
+
 2016-09-09  James Greenhalgh  <james.greenhalgh@arm.com>
 
        PR target/63250
index 5b16a1f87e25c8daa85c2d6b1acb2591859f275e..be82f65b916fead3429152c251d29114335359e2 100644 (file)
@@ -35,6 +35,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "unwind-pe.h"
 #include "unwind-dw2-fde.h"
 #include "gthr.h"
+#else
+#if (defined(__GTHREAD_MUTEX_INIT) || defined(__GTHREAD_MUTEX_INIT_FUNCTION)) \
+    && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
+#define ATOMIC_FDE_FAST_PATH 1
+#endif
 #endif
 
 /* The unseen_objects list contains objects that have been registered
@@ -43,6 +48,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    by decreasing value of pc_begin.  */
 static struct object *unseen_objects;
 static struct object *seen_objects;
+#ifdef ATOMIC_FDE_FAST_PATH
+static int any_objects_registered;
+#endif
 
 #ifdef __GTHREAD_MUTEX_INIT
 static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT;
@@ -96,6 +104,16 @@ __register_frame_info_bases (const void *begin, struct object *ob,
 
   ob->next = unseen_objects;
   unseen_objects = ob;
+#ifdef ATOMIC_FDE_FAST_PATH
+  /* Set flag that at least one library has registered FDEs.
+     Use relaxed MO here, it is up to the app to ensure that the library
+     loading/initialization happens-before using that library in other
+     threads (in particular unwinding with that library's functions
+     appearing in the backtraces).  Calling that library's functions
+     without waiting for the library to initialize would be racy.  */
+  if (!any_objects_registered)
+    __atomic_store_n (&any_objects_registered, 1, __ATOMIC_RELAXED);
+#endif
 
   __gthread_mutex_unlock (&object_mutex);
 }
@@ -140,6 +158,16 @@ __register_frame_info_table_bases (void *begin, struct object *ob,
 
   ob->next = unseen_objects;
   unseen_objects = ob;
+#ifdef ATOMIC_FDE_FAST_PATH
+  /* Set flag that at least one library has registered FDEs.
+     Use relaxed MO here, it is up to the app to ensure that the library
+     loading/initialization happens-before using that library in other
+     threads (in particular unwinding with that library's functions
+     appearing in the backtraces).  Calling that library's functions
+     without waiting for the library to initialize would be racy.  */
+  if (!any_objects_registered)
+    __atomic_store_n (&any_objects_registered, 1, __ATOMIC_RELAXED);
+#endif
 
   __gthread_mutex_unlock (&object_mutex);
 }
@@ -1001,6 +1029,19 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
   struct object *ob;
   const fde *f = NULL;
 
+#ifdef ATOMIC_FDE_FAST_PATH
+  /* For targets where unwind info is usually not registered through these
+     APIs anymore, avoid taking a global lock.
+     Use relaxed MO here, it is up to the app to ensure that the library
+     loading/initialization happens-before using that library in other
+     threads (in particular unwinding with that library's functions
+     appearing in the backtraces).  Calling that library's functions
+     without waiting for the library to initialize would be racy.  */
+  if (__builtin_expect (!__atomic_load_n (&any_objects_registered,
+                                         __ATOMIC_RELAXED), 1))
+    return NULL;
+#endif
+
   init_object_mutex_once ();
   __gthread_mutex_lock (&object_mutex);