|
|
12745e |
diff -pruN glibc-2.17-c758a686/nptl/sysdeps/pthread/unwind-forcedunwind.c glibc-2.17-c758a686/nptl/sysdeps/pthread/unwind-forcedunwind.c
|
|
|
12745e |
--- glibc-2.17-c758a686/nptl/sysdeps/pthread/unwind-forcedunwind.c 2010-05-04 16:57:23.000000000 +0530
|
|
|
12745e |
+++ glibc-2.17-c758a686/nptl/sysdeps/pthread/unwind-forcedunwind.c 2014-06-02 23:00:02.901013275 +0530
|
|
|
5de29b |
@@ -45,8 +45,10 @@ pthread_cancel_init (void)
|
|
|
5de29b |
|
|
|
5de29b |
if (__builtin_expect (libgcc_s_handle != NULL, 1))
|
|
|
5de29b |
{
|
|
|
5de29b |
- /* Force gcc to reload all values. */
|
|
|
5de29b |
- asm volatile ("" ::: "memory");
|
|
|
5de29b |
+ /* Order reads so as to prevent speculation of loads
|
|
|
5de29b |
+ of libgcc_s_{resume,personality,forcedunwind,getcfa}
|
|
|
5de29b |
+ to points prior to the write barrier. */
|
|
|
5de29b |
+ atomic_read_barrier ();
|
|
|
5de29b |
return;
|
|
|
5de29b |
}
|
|
|
5de29b |
|
|
|
5de29b |
@@ -72,9 +74,14 @@ pthread_cancel_init (void)
|
|
|
5de29b |
libgcc_s_forcedunwind = forcedunwind;
|
|
|
5de29b |
PTR_MANGLE (getcfa);
|
|
|
5de29b |
libgcc_s_getcfa = getcfa;
|
|
|
5de29b |
- /* Make sure libgcc_s_handle is written last. Otherwise,
|
|
|
5de29b |
- pthread_cancel_init might return early even when the pointer the
|
|
|
5de29b |
- caller is interested in is not initialized yet. */
|
|
|
5de29b |
+ /* At the point at which any thread writes the handle
|
|
|
5de29b |
+ to libgcc_s_handle, the initialization is complete.
|
|
|
5de29b |
+ The writing of libgcc_s_handle is atomic. All other
|
|
|
5de29b |
+ threads reading libgcc_s_handle do so atomically. Any
|
|
|
5de29b |
+ thread that does not execute this function must issue
|
|
|
5de29b |
+ a read barrier to ensure that all of the above has
|
|
|
5de29b |
+ actually completed and that the values of the
|
|
|
5de29b |
+ function pointers are correct. */
|
|
|
5de29b |
atomic_write_barrier ();
|
|
|
5de29b |
libgcc_s_handle = handle;
|
|
|
5de29b |
}
|
|
|
5de29b |
@@ -91,13 +98,19 @@ __unwind_freeres (void)
|
|
|
5de29b |
}
|
|
|
5de29b |
}
|
|
|
5de29b |
|
|
|
5de29b |
-void
|
|
|
5de29b |
-_Unwind_Resume (struct _Unwind_Exception *exc)
|
|
|
5de29b |
+static __always_inline void
|
|
|
5de29b |
+_maybe_pthread_cancel_init (void)
|
|
|
5de29b |
{
|
|
|
5de29b |
if (__builtin_expect (libgcc_s_handle == NULL, 0))
|
|
|
5de29b |
pthread_cancel_init ();
|
|
|
5de29b |
else
|
|
|
5de29b |
atomic_read_barrier ();
|
|
|
5de29b |
+}
|
|
|
5de29b |
+
|
|
|
5de29b |
+void
|
|
|
5de29b |
+_Unwind_Resume (struct _Unwind_Exception *exc)
|
|
|
5de29b |
+{
|
|
|
5de29b |
+ _maybe_pthread_cancel_init ();
|
|
|
5de29b |
|
|
|
5de29b |
void (*resume) (struct _Unwind_Exception *exc) = libgcc_s_resume;
|
|
|
5de29b |
PTR_DEMANGLE (resume);
|
|
|
5de29b |
@@ -108,10 +123,7 @@ __gcc_personality_v0 (int version, _Unwi
|
|
|
5de29b |
struct _Unwind_Exception *ue_header,
|
|
|
5de29b |
struct _Unwind_Context *context)
|
|
|
5de29b |
{
|
|
|
5de29b |
- if (__builtin_expect (libgcc_s_handle == NULL, 0))
|
|
|
5de29b |
- pthread_cancel_init ();
|
|
|
5de29b |
- else
|
|
|
5de29b |
- atomic_read_barrier ();
|
|
|
5de29b |
+ _maybe_pthread_cancel_init ();
|
|
|
5de29b |
|
|
|
5de29b |
_Unwind_Reason_Code (*personality)
|
|
|
5de29b |
(int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *,
|
|
|
5de29b |
@@ -122,10 +136,7 @@ _Unwind_Reason_Code
|
|
|
5de29b |
_Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop,
|
|
|
5de29b |
void *stop_argument)
|
|
|
5de29b |
{
|
|
|
5de29b |
- if (__builtin_expect (libgcc_s_handle == NULL, 0))
|
|
|
5de29b |
- pthread_cancel_init ();
|
|
|
5de29b |
- else
|
|
|
5de29b |
- atomic_read_barrier ();
|
|
|
5de29b |
+ _maybe_pthread_cancel_init ();
|
|
|
5de29b |
|
|
|
5de29b |
_Unwind_Reason_Code (*forcedunwind)
|
|
|
5de29b |
(struct _Unwind_Exception *, _Unwind_Stop_Fn, void *)
|
|
|
5de29b |
@@ -135,10 +148,7 @@ _Unwind_ForcedUnwind (struct _Unwind_Exc
|
|
|
5de29b |
_Unwind_Word
|
|
|
5de29b |
_Unwind_GetCFA (struct _Unwind_Context *context)
|
|
|
5de29b |
{
|
|
|
5de29b |
- if (__builtin_expect (libgcc_s_handle == NULL, 0))
|
|
|
5de29b |
- pthread_cancel_init ();
|
|
|
5de29b |
- else
|
|
|
5de29b |
- atomic_read_barrier ();
|
|
|
5de29b |
+ _maybe_pthread_cancel_init ();
|
|
|
5de29b |
|
|
|
5de29b |
_Unwind_Word (*getcfa) (struct _Unwind_Context *) = libgcc_s_getcfa;
|
|
|
5de29b |
PTR_DEMANGLE (getcfa);
|
|
|
12745e |
diff -pruN glibc-2.17-c758a686/sysdeps/gnu/unwind-resume.c glibc-2.17-c758a686/sysdeps/gnu/unwind-resume.c
|
|
|
12745e |
--- glibc-2.17-c758a686/sysdeps/gnu/unwind-resume.c 2010-05-04 16:57:23.000000000 +0530
|
|
|
12745e |
+++ glibc-2.17-c758a686/sysdeps/gnu/unwind-resume.c 2014-06-02 23:02:26.812007078 +0530
|
|
|
5de29b |
@@ -20,8 +20,11 @@
|
|
|
5de29b |
#include <dlfcn.h>
|
|
|
5de29b |
#include <stdio.h>
|
|
|
5de29b |
#include <unwind.h>
|
|
|
5de29b |
+#include <pthreadP.h>
|
|
|
5de29b |
+#include <sysdep.h>
|
|
|
5de29b |
#include <gnu/lib-names.h>
|
|
|
5de29b |
|
|
|
5de29b |
+static void *libgcc_s_handle;
|
|
|
5de29b |
static void (*libgcc_s_resume) (struct _Unwind_Exception *exc);
|
|
|
5de29b |
static _Unwind_Reason_Code (*libgcc_s_personality)
|
|
|
5de29b |
(int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *,
|
|
|
5de29b |
@@ -42,13 +45,32 @@ init (void)
|
|
|
5de29b |
|
|
|
5de29b |
libgcc_s_resume = resume;
|
|
|
5de29b |
libgcc_s_personality = personality;
|
|
|
5de29b |
+ atomic_write_barrier ();
|
|
|
5de29b |
+ /* At the point at which any thread writes the handle
|
|
|
5de29b |
+ to libgcc_s_handle, the initialization is complete.
|
|
|
5de29b |
+ The writing of libgcc_s_handle is atomic. All other
|
|
|
5de29b |
+ threads reading libgcc_s_handle do so atomically. Any
|
|
|
5de29b |
+ thread that does not execute this function must issue
|
|
|
5de29b |
+ a read barrier to ensure that all of the above has
|
|
|
5de29b |
+ actually completed and that the values of the
|
|
|
5de29b |
+ function pointers are correct. */
|
|
|
5de29b |
+ libgcc_s_handle = handle;
|
|
|
5de29b |
}
|
|
|
5de29b |
|
|
|
5de29b |
+static __always_inline void
|
|
|
5de29b |
+_maybe_init (void)
|
|
|
5de29b |
+{
|
|
|
5de29b |
+ if (__builtin_expect (libgcc_s_handle == NULL, 0))
|
|
|
5de29b |
+ init ();
|
|
|
5de29b |
+ else
|
|
|
5de29b |
+ atomic_read_barrier ();
|
|
|
5de29b |
+}
|
|
|
5de29b |
+
|
|
|
5de29b |
+
|
|
|
5de29b |
void
|
|
|
5de29b |
_Unwind_Resume (struct _Unwind_Exception *exc)
|
|
|
5de29b |
{
|
|
|
5de29b |
- if (__builtin_expect (libgcc_s_resume == NULL, 0))
|
|
|
5de29b |
- init ();
|
|
|
5de29b |
+ _maybe_init ();
|
|
|
5de29b |
libgcc_s_resume (exc);
|
|
|
5de29b |
}
|
|
|
5de29b |
|
|
|
5de29b |
@@ -58,8 +80,7 @@ __gcc_personality_v0 (int version, _Unwi
|
|
|
5de29b |
struct _Unwind_Exception *ue_header,
|
|
|
5de29b |
struct _Unwind_Context *context)
|
|
|
5de29b |
{
|
|
|
5de29b |
- if (__builtin_expect (libgcc_s_personality == NULL, 0))
|
|
|
5de29b |
- init ();
|
|
|
5de29b |
+ _maybe_init ();
|
|
|
5de29b |
return libgcc_s_personality (version, actions, exception_class,
|
|
|
5de29b |
ue_header, context);
|
|
|
5de29b |
}
|