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