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