/* Subroutines needed for unwinding stack frames for exception handling. */
-/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008,
- 2009, 2010, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 1997-2017 Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@cygnus.com>.
This file is part of GCC.
#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
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;
+#define init_object_mutex_once()
#else
+#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
static __gthread_mutex_t object_mutex;
-#endif
-#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
static void
init_object_mutex (void)
{
__gthread_once (&once, init_object_mutex);
}
#else
+/* ??? Several targets include this file with stubbing parts of gthr.h
+ and expect no locking to be done. */
#define init_object_mutex_once()
+static __gthread_mutex_t object_mutex;
+#endif
#endif
/* Called from crtbegin.o to register the unwind info for an object. */
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);
}
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);
}
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);