[dev.regabi] runtime/cgo: call setg_gcc in crosscall_amd64

Currently, when using cgo, the g pointer is set via a separate
call to setg_gcc or with inline assembly in threadentry. This CL
changes it to call setg_gcc in crosscall_amd64, like other g-
register platforms. When we have an actual g register on AMD64,
we'll need to set the register immediately before calling into
Go.

Change-Id: Ib1171e05cd0dabba3b7d12e072084d141051cf3d
Reviewed-on: https://go-review.googlesource.com/c/go/+/289192
Trust: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Zhang 2021-02-02 17:26:57 -05:00
parent 120b819f45
commit 63de211014
10 changed files with 23 additions and 49 deletions

View File

@ -30,9 +30,14 @@ EXT(crosscall_amd64):
pushq %r15
#if defined(_WIN64)
movq %r8, %rdi /* arg of setg_gcc */
call *%rdx /* setg_gcc */
call *%rcx /* fn */
#else
call *%rdi /* fn */
movq %rdi, %rbx
movq %rdx, %rdi /* arg of setg_gcc */
call *%rsi /* setg_gcc */
call *%rbx /* fn */
#endif
popq %r15

View File

@ -9,13 +9,16 @@
#include "libcgo_unix.h"
static void* threadentry(void*);
static void (*setg_gcc)(void*);
void
x_cgo_init(G *g)
x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase)
{
pthread_attr_t attr;
size_t size;
setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
g->stacklo = (uintptr)&attr - size + 4096;
@ -57,10 +60,6 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
// Move the g pointer into the slot reserved in thread local storage.
// Constant must match the one in cmd/link/internal/ld/sym.go.
asm volatile("movq %0, %%gs:0x30" :: "r"(ts.g));
crosscall_amd64(ts.fn);
crosscall_amd64(ts.fn, setg_gcc, (void*)ts.g);
return nil;
}

View File

@ -61,11 +61,6 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
/*
* Set specific keys.
*/
setg_gcc((void*)ts.g);
crosscall_amd64(ts.fn);
crosscall_amd64(ts.fn, setg_gcc, (void*)ts.g);
return nil;
}

View File

@ -69,11 +69,6 @@ threadentry(void *v)
free(v);
_cgo_tsan_release();
/*
* Set specific keys.
*/
setg_gcc((void*)ts.g);
crosscall_amd64(ts.fn);
crosscall_amd64(ts.fn, setg_gcc, (void*)ts.g);
return nil;
}

View File

@ -89,11 +89,6 @@ threadentry(void *v)
free(v);
_cgo_tsan_release();
/*
* Set specific keys.
*/
setg_gcc((void*)ts.g);
crosscall_amd64(ts.fn);
crosscall_amd64(ts.fn, setg_gcc, (void*)ts.g);
return nil;
}

View File

@ -62,11 +62,6 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
/*
* Set specific keys.
*/
setg_gcc((void*)ts.g);
// On NetBSD, a new thread inherits the signal stack of the
// creating thread. That confuses minit, so we remove that
// signal stack here before calling the regular mstart. It's
@ -78,6 +73,6 @@ threadentry(void *v)
ss.ss_flags = SS_DISABLE;
sigaltstack(&ss, nil);
crosscall_amd64(ts.fn);
crosscall_amd64(ts.fn, setg_gcc, (void*)ts.g);
return nil;
}

View File

@ -60,11 +60,6 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
/*
* Set specific keys.
*/
setg_gcc((void*)ts.g);
crosscall_amd64(ts.fn);
crosscall_amd64(ts.fn, setg_gcc, (void*)ts.g);
return nil;
}

View File

@ -72,11 +72,6 @@ threadentry(void *v)
ts = *(ThreadStart*)v;
free(v);
/*
* Set specific keys.
*/
setg_gcc((void*)ts.g);
crosscall_amd64(ts.fn);
crosscall_amd64(ts.fn, setg_gcc, (void*)ts.g);
return nil;
}

View File

@ -12,10 +12,12 @@
#include "libcgo_windows.h"
static void threadentry(void*);
static void (*setg_gcc)(void*);
void
x_cgo_init(G *g)
x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase)
{
setg_gcc = setg;
}
@ -46,10 +48,8 @@ threadentry(void *v)
*/
asm volatile (
"movq %0, %%gs:0x28\n" // MOVL tls0, 0x28(GS)
"movq %%gs:0x28, %%rax\n" // MOVQ 0x28(GS), tmp
"movq %1, 0(%%rax)\n" // MOVQ g, 0(GS)
:: "r"(ts.tls), "r"(ts.g) : "%rax"
:: "r"(ts.tls)
);
crosscall_amd64(ts.fn);
crosscall_amd64(ts.fn, setg_gcc, (void*)ts.g);
}

View File

@ -66,7 +66,7 @@ uintptr_t _cgo_wait_runtime_init_done(void);
/*
* Call fn in the 6c world.
*/
void crosscall_amd64(void (*fn)(void));
void crosscall_amd64(void (*fn)(void), void (*setg_gcc)(void*), void *g);
/*
* Call fn in the 8c world.