···
1
+
From f74059ffbcf53d8ff4db59ca9e7b07d58bd3e3c6 Mon Sep 17 00:00:00 2001
2
+
From: David McFarland <corngood@gmail.com>
3
+
Date: Fri, 4 Sep 2020 10:15:57 -0300
4
+
Subject: [PATCH] Cygwin: store tls pointer in win32 tls
6
+
Use WIN32 TLS instead of stack-relative pointers for TLS. This allows windows
7
+
fibers and boost coroutines to be used without crashing whenever a syscall is
10
+
NOTE: This should be submitted upstream, but there is a blocker first. In the
11
+
main branch there are conflicts with new ARM64 support. In addition to fixing
12
+
the conflicts, we should actually test whether ARM64 builds work too, first.
14
+
winsup/cygwin/create_posix_thread.cc | 2 ++
15
+
winsup/cygwin/cygtls.cc | 15 +++++++++++++++
16
+
winsup/cygwin/dcrt0.cc | 1 +
17
+
winsup/cygwin/fork.cc | 1 +
18
+
winsup/cygwin/include/cygwin/config.h | 2 +-
19
+
winsup/cygwin/init.cc | 12 ++++++++----
20
+
winsup/cygwin/local_includes/cygtls.h | 7 +++++--
21
+
winsup/cygwin/scripts/gendef | 15 ++++++++++-----
22
+
8 files changed, 43 insertions(+), 12 deletions(-)
24
+
diff --git a/winsup/cygwin/create_posix_thread.cc b/winsup/cygwin/create_posix_thread.cc
25
+
index 3fcd61707..85c1a8af3 100644
26
+
--- a/winsup/cygwin/create_posix_thread.cc
27
+
+++ b/winsup/cygwin/create_posix_thread.cc
28
+
@@ -52,6 +52,7 @@ pthread_wrapper (PVOID arg)
29
+
/* Set stack values in TEB */
30
+
PTEB teb = NtCurrentTeb ();
31
+
teb->Tib.StackBase = wrapper_arg.stackbase;
33
+
teb->Tib.StackLimit = wrapper_arg.stacklimit ?: wrapper_arg.stackaddr;
34
+
/* Set DeallocationStack value. If we have an application-provided stack,
35
+
we set DeallocationStack to NULL, so NtTerminateThread does not deallocate
36
+
@@ -250,6 +251,7 @@ create_new_main_thread_stack (PVOID &allocationbase)
38
+
NtCurrentTeb()->Tib.StackBase = ((PBYTE) allocationbase + stacksize);
39
+
NtCurrentTeb()->Tib.StackLimit = stacklimit;
41
+
return ((PBYTE) allocationbase + stacksize - 16);
44
+
diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc
45
+
index 13d133f47..d23f9b42a 100644
46
+
--- a/winsup/cygwin/cygtls.cc
47
+
+++ b/winsup/cygwin/cygtls.cc
48
+
@@ -17,6 +17,20 @@ details. */
49
+
#include "sigproc.h"
50
+
#include "exception.h"
52
+
+extern DWORD cygtls_slot;
54
+
+void _set_tls(TEB *teb)
56
+
+ TlsSetValue(cygtls_slot, teb->Tib.StackBase);
59
+
+_cygtls* _current_tls()
61
+
+ register void *ret;
62
+
+ __asm __volatile__ ("movl cygtls_slot(%%rip),%%r10d\nmovq %%gs:0x1480(,%%r10d,8),%0" : "=r" (ret) : : "r10");
63
+
+ return (_cygtls *) ((PBYTE) ret - __CYGTLS_PADSIZE__);
66
+
/* Two calls to get the stack right... */
68
+
_cygtls::call (DWORD (*func) (void *, void *), void *arg)
69
+
@@ -25,6 +39,7 @@ _cygtls::call (DWORD (*func) (void *, void *), void *arg)
70
+
/* Initialize this thread's ability to respond to things like
71
+
SIGSEGV or SIGFPE. */
74
+
_my_tls.call2 (func, arg, buf);
77
+
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
78
+
index f4c09befd..e6ba488f2 100644
79
+
--- a/winsup/cygwin/dcrt0.cc
80
+
+++ b/winsup/cygwin/dcrt0.cc
81
+
@@ -462,6 +462,7 @@ child_info_fork::alloc_stack ()
82
+
StackBase in the child to be the same as in the parent, so that the
83
+
computation of _my_tls is correct. */
84
+
teb->Tib.StackBase = (PVOID) stackbase;
89
+
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
90
+
index f88acdbbf..582f1a454 100644
91
+
--- a/winsup/cygwin/fork.cc
92
+
+++ b/winsup/cygwin/fork.cc
93
+
@@ -141,6 +141,7 @@ frok::child (volatile char * volatile here)
94
+
myself->pid, myself->ppid, __builtin_frame_address (0));
95
+
sigproc_printf ("hParent %p, load_dlls %d", hParent, load_dlls);
98
+
/* Make sure threadinfo information is properly set up. */
99
+
if (&_my_tls != _main_tls)
101
+
diff --git a/winsup/cygwin/include/cygwin/config.h b/winsup/cygwin/include/cygwin/config.h
102
+
index 2a7083278..21ce484cf 100644
103
+
--- a/winsup/cygwin/include/cygwin/config.h
104
+
+++ b/winsup/cygwin/include/cygwin/config.h
105
+
@@ -37,7 +37,7 @@ extern inline struct _reent *__getreent (void)
107
+
register char *ret;
109
+
- __asm __volatile__ ("movq %%gs:8,%0" : "=r" (ret));
110
+
+ __asm __volatile__ ("movl cygtls_slot(%%rip),%%r10d\nmovq %%gs:0x1480(,%%r10d,8),%0" : "=r" (ret) : : "r10");
112
+
#error unimplemented for this target
114
+
diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc
115
+
index ce6484aff..392ac8600 100644
116
+
--- a/winsup/cygwin/init.cc
117
+
+++ b/winsup/cygwin/init.cc
118
+
@@ -11,7 +11,7 @@ details. */
120
+
#include "shared_info.h"
122
+
-static DWORD _my_oldfunc;
123
+
+DWORD NO_COPY cygtls_slot;
125
+
static char *search_for = (char *) cygthread::stub;
126
+
unsigned threadfunc_ix[8];
127
+
@@ -22,7 +22,9 @@ static bool dll_finished_loading;
129
+
threadfunc_fe (VOID *arg)
131
+
- _cygtls::call ((DWORD (*) (void *, void *)) TlsGetValue (_my_oldfunc), arg);
132
+
+ PVOID f = TlsGetValue (cygtls_slot);
134
+
+ _cygtls::call ((DWORD (*) (void *, void *)) f, arg);
137
+
/* If possible, redirect the thread entry point to a cygwin routine which
138
+
@@ -59,7 +61,7 @@ munge_threadfunc ()
139
+
for (i = 0; threadfunc_ix[i]; i++)
140
+
if (!threadfunc || ebp[threadfunc_ix[i]] == threadfunc)
141
+
ebp[threadfunc_ix[i]] = (char *) threadfunc_fe;
142
+
- TlsSetValue (_my_oldfunc, threadfunc);
143
+
+ TlsSetValue (cygtls_slot, threadfunc);
147
+
@@ -78,6 +80,8 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
150
+
case DLL_PROCESS_ATTACH:
151
+
+ cygtls_slot = TlsAlloc ();
153
+
init_console_handler (false);
155
+
cygwin_hmodule = (HMODULE) h;
156
+
@@ -94,7 +98,6 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
157
+
memcpy (_REENT, _GLOBAL_REENT, sizeof (struct _reent));
160
+
- _my_oldfunc = TlsAlloc ();
161
+
dll_finished_loading = true;
163
+
case DLL_PROCESS_DETACH:
164
+
@@ -102,6 +105,7 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
167
+
case DLL_THREAD_ATTACH:
169
+
if (dll_finished_loading)
170
+
munge_threadfunc ();
172
+
diff --git a/winsup/cygwin/local_includes/cygtls.h b/winsup/cygwin/local_includes/cygtls.h
173
+
index 306497a33..e3a216280 100644
174
+
--- a/winsup/cygwin/local_includes/cygtls.h
175
+
+++ b/winsup/cygwin/local_includes/cygtls.h
176
+
@@ -301,8 +301,11 @@ private:
177
+
#include "cygerrno.h"
180
+
-#define _my_tls (*((_cygtls *) ((PBYTE) NtCurrentTeb()->Tib.StackBase \
181
+
- - __CYGTLS_PADSIZE__)))
182
+
+void _set_tls(TEB*);
183
+
+inline void _set_tls() { _set_tls(NtCurrentTeb()); }
184
+
+_cygtls* _current_tls();
186
+
+#define _my_tls (*_current_tls())
187
+
extern _cygtls *_main_tls;
188
+
extern _cygtls *_sig_tls;
190
+
diff --git a/winsup/cygwin/scripts/gendef b/winsup/cygwin/scripts/gendef
191
+
index 861a2405b..9a4479bd8 100755
192
+
--- a/winsup/cygwin/scripts/gendef
193
+
+++ b/winsup/cygwin/scripts/gendef
194
+
@@ -118,7 +118,8 @@ EOF
195
+
.seh_proc _sigfe_maybe
196
+
_sigfe_maybe: # stack is aligned on entry!
198
+
- movq %gs:8,%r10 # location of bottom of stack
199
+
+ movl cygtls_slot(%rip),%r10d
200
+
+ movq %gs:0x1480(,%r10d,8),%r10 # location of bottom of stack
201
+
leaq _cygtls.initialized(%r10),%r11 # where we will be looking
202
+
cmpq %r11,%rsp # stack loc > than tls
203
+
jge 0f # yep. we don't have a tls.
204
+
@@ -131,7 +132,8 @@ _sigfe_maybe: # stack is aligned on entry!
206
+
_sigfe: # stack is aligned on entry!
208
+
- movq %gs:8,%r10 # location of bottom of stack
209
+
+ movl cygtls_slot(%rip),%r10d
210
+
+ movq %gs:0x1480(,%r10d,8),%r10 # location of bottom of stack
212
+
xchgl %r11d,_cygtls.stacklock(%r10) # try to acquire lock
213
+
testl %r11d,%r11d # it will be zero
214
+
@@ -154,7 +156,8 @@ _sigfe: # stack is aligned on entry!
215
+
_sigbe: # return here after cygwin syscall
216
+
# stack is aligned on entry!
218
+
- movq %gs:8,%r10 # address of bottom of tls
219
+
+ movl cygtls_slot(%rip),%r10d
220
+
+ movq %gs:0x1480(,%r10d,8),%r10 # address of bottom of tls
222
+
xchgl %r11d,_cygtls.stacklock(%r10) # try to acquire lock
223
+
testl %r11d,%r11d # it will be zero
224
+
@@ -249,7 +252,8 @@ sigdelayed:
228
+
- movq %gs:8,%r12 # get tls
229
+
+ movl cygtls_slot(%rip),%r12d
230
+
+ movq %gs:0x1480(,%r12d,8),%r12 # get tls
231
+
movl _cygtls.saved_errno(%r12),%r15d # temporarily save saved_errno
232
+
movq \$_cygtls.start_offset,%rcx # point to beginning of tls block
233
+
addq %r12,%rcx # and store as first arg to method
234
+
@@ -316,7 +320,8 @@ stabilize_sig_stack:
239
+
+ movl cygtls_slot(%rip),%r12d
240
+
+ movq %gs:0x1480(,%r12d,8),%r12
242
+
xchgl %r10d,_cygtls.stacklock(%r12) # try to acquire lock