Hi!

These days on many targets that use dl_iterate_phdr to find .eh_frame_hdr
that way in most of the programs the old style EH registry is never used,
yet we still lock a global mutex and unlock it soon afterwards to find out
it is the case.

This patch adds a fast path to that, by replacing that with an atomic load
of a flag "has anything ever been registered in the old style registry"
and if the flag says no, it avoids the locking.

Of course, there is another locking in dl_iterate_phdr, which will need
agreement and cooperation in between the glibc and GCC projects, so this
isn't a full solution, but a path towards it.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-09-15  Jakub Jelinek  <ja...@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.

--- libgcc/unwind-dw2-fde.c.jj  2016-01-04 15:14:09.000000000 +0100
+++ libgcc/unwind-dw2-fde.c     2016-07-07 13:25:39.248845579 +0200
@@ -35,6 +35,11 @@ see the files COPYING3 and COPYING.RUNTI
 #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.RUNTI
    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,10 @@ __register_frame_info_bases (const void
 
   ob->next = unseen_objects;
   unseen_objects = ob;
+#ifdef ATOMIC_FDE_FAST_PATH
+  if (!any_objects_registered)
+    __atomic_store_n (&any_objects_registered, 1, __ATOMIC_RELEASE);
+#endif
 
   __gthread_mutex_unlock (&object_mutex);
 }
@@ -140,6 +152,10 @@ __register_frame_info_table_bases (void
 
   ob->next = unseen_objects;
   unseen_objects = ob;
+#ifdef ATOMIC_FDE_FAST_PATH
+  if (!any_objects_registered)
+    __atomic_store_n (&any_objects_registered, 1, __ATOMIC_RELEASE);
+#endif
 
   __gthread_mutex_unlock (&object_mutex);
 }
@@ -1001,6 +1017,14 @@ _Unwind_Find_FDE (void *pc, struct dwarf
   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.  */
+  if (__builtin_expect (!__atomic_load_n (&any_objects_registered,
+                                         __ATOMIC_ACQUIRE), 1))
+    return NULL;
+#endif
+
   init_object_mutex_once ();
   __gthread_mutex_lock (&object_mutex);
 

        Jakub

Reply via email to