]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/glibc/glibc-rh905941.patch
Merge branch 'bird' into next
[ipfire-2.x.git] / src / patches / glibc / glibc-rh905941.patch
1 diff -pruN a/nptl/sysdeps/pthread/unwind-forcedunwind.c b/nptl/sysdeps/pthread/unwind-forcedunwind.c
2 --- a/nptl/sysdeps/pthread/unwind-forcedunwind.c 2010-05-04 16:57:23.000000000 +0530
3 +++ b/nptl/sysdeps/pthread/unwind-forcedunwind.c 2014-06-02 23:00:02.901013275 +0530
4 @@ -45,8 +45,10 @@ pthread_cancel_init (void)
5
6 if (__builtin_expect (libgcc_s_handle != NULL, 1))
7 {
8 - /* Force gcc to reload all values. */
9 - asm volatile ("" ::: "memory");
10 + /* Order reads so as to prevent speculation of loads
11 + of libgcc_s_{resume,personality,forcedunwind,getcfa}
12 + to points prior to the write barrier. */
13 + atomic_read_barrier ();
14 return;
15 }
16
17 @@ -72,9 +74,14 @@ pthread_cancel_init (void)
18 libgcc_s_forcedunwind = forcedunwind;
19 PTR_MANGLE (getcfa);
20 libgcc_s_getcfa = getcfa;
21 - /* Make sure libgcc_s_handle is written last. Otherwise,
22 - pthread_cancel_init might return early even when the pointer the
23 - caller is interested in is not initialized yet. */
24 + /* At the point at which any thread writes the handle
25 + to libgcc_s_handle, the initialization is complete.
26 + The writing of libgcc_s_handle is atomic. All other
27 + threads reading libgcc_s_handle do so atomically. Any
28 + thread that does not execute this function must issue
29 + a read barrier to ensure that all of the above has
30 + actually completed and that the values of the
31 + function pointers are correct. */
32 atomic_write_barrier ();
33 libgcc_s_handle = handle;
34 }
35 @@ -91,11 +98,19 @@ __unwind_freeres (void)
36 }
37 }
38
39 -void
40 -_Unwind_Resume (struct _Unwind_Exception *exc)
41 +static __always_inline void
42 +_maybe_pthread_cancel_init (void)
43 {
44 if (__builtin_expect (libgcc_s_handle == NULL, 0))
45 pthread_cancel_init ();
46 + else
47 + atomic_read_barrier ();
48 +}
49 +
50 +void
51 +_Unwind_Resume (struct _Unwind_Exception *exc)
52 +{
53 + _maybe_pthread_cancel_init ();
54
55 void (*resume) (struct _Unwind_Exception *exc) = libgcc_s_resume;
56 PTR_DEMANGLE (resume);
57 @@ -108,8 +123,7 @@ __gcc_personality_v0 (int version, _Unwi
58 struct _Unwind_Exception *ue_header,
59 struct _Unwind_Context *context)
60 {
61 - if (__builtin_expect (libgcc_s_handle == NULL, 0))
62 - pthread_cancel_init ();
63 + _maybe_pthread_cancel_init ();
64
65 _Unwind_Reason_Code (*personality)
66 (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *,
67 @@ -122,8 +136,7 @@ _Unwind_Reason_Code
68 _Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop,
69 void *stop_argument)
70 {
71 - if (__builtin_expect (libgcc_s_handle == NULL, 0))
72 - pthread_cancel_init ();
73 + _maybe_pthread_cancel_init ();
74
75 _Unwind_Reason_Code (*forcedunwind)
76 (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *)
77 @@ -135,8 +148,7 @@ _Unwind_ForcedUnwind (struct _Unwind_Exc
78 _Unwind_Word
79 _Unwind_GetCFA (struct _Unwind_Context *context)
80 {
81 - if (__builtin_expect (libgcc_s_handle == NULL, 0))
82 - pthread_cancel_init ();
83 + _maybe_pthread_cancel_init ();
84
85 _Unwind_Word (*getcfa) (struct _Unwind_Context *) = libgcc_s_getcfa;
86 PTR_DEMANGLE (getcfa);
87 diff -pruN a/sysdeps/gnu/unwind-resume.c b/sysdeps/gnu/unwind-resume.c
88 --- a/sysdeps/gnu/unwind-resume.c 2010-05-04 16:57:23.000000000 +0530
89 +++ b/sysdeps/gnu/unwind-resume.c 2014-06-02 23:02:26.812007078 +0530
90 @@ -20,8 +20,11 @@
91 #include <dlfcn.h>
92 #include <stdio.h>
93 #include <unwind.h>
94 +#include <pthreadP.h>
95 +#include <sysdep.h>
96 #include <libgcc_s.h>
97
98 +static void *libgcc_s_handle;
99 static void (*libgcc_s_resume) (struct _Unwind_Exception *exc);
100 static _Unwind_Reason_Code (*libgcc_s_personality)
101 (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *,
102 @@ -42,13 +45,32 @@ init (void)
103
104 libgcc_s_resume = resume;
105 libgcc_s_personality = personality;
106 + atomic_write_barrier ();
107 + /* At the point at which any thread writes the handle
108 + to libgcc_s_handle, the initialization is complete.
109 + The writing of libgcc_s_handle is atomic. All other
110 + threads reading libgcc_s_handle do so atomically. Any
111 + thread that does not execute this function must issue
112 + a read barrier to ensure that all of the above has
113 + actually completed and that the values of the
114 + function pointers are correct. */
115 + libgcc_s_handle = handle;
116 }
117
118 +static __always_inline void
119 +_maybe_init (void)
120 +{
121 + if (__builtin_expect (libgcc_s_handle == NULL, 0))
122 + init ();
123 + else
124 + atomic_read_barrier ();
125 +}
126 +
127 +
128 void
129 _Unwind_Resume (struct _Unwind_Exception *exc)
130 {
131 - if (__builtin_expect (libgcc_s_resume == NULL, 0))
132 - init ();
133 + _maybe_init ();
134 libgcc_s_resume (exc);
135 }
136
137 @@ -58,8 +80,7 @@ __gcc_personality_v0 (int version, _Unwi
138 struct _Unwind_Exception *ue_header,
139 struct _Unwind_Context *context)
140 {
141 - if (__builtin_expect (libgcc_s_personality == NULL, 0))
142 - init ();
143 + _maybe_init ();
144 return libgcc_s_personality (version, actions, exception_class,
145 ue_header, context);
146 }