From 8a0bc29bedd45324c52cfdc7717fabfc82673e4d Mon Sep 17 00:00:00 2001 From: qmuntal Date: Tue, 30 Sep 2025 17:23:49 +0200 Subject: [PATCH] runtime/cgo: deduplicate x_cgo_init and crosscall1 Most platforms share the same implementation for x_cgo_init and crosscall1. Solaris diverges too much and is left for a future CL. Cq-Include-Trybots: luci.golang.try:gotip-freebsd-amd64,gotip-darwin-amd64_14,gotip-darwin-arm64_15,gotip-netbsd-arm64,gotip-openbsd-ppc64,gotip-solaris-amd64,gotip-linux-ppc64_power10 Change-Id: Ib2eeb6456caa5c055e1ac1907c2fdf63db58dafc Reviewed-on: https://go-review.googlesource.com/c/go/+/708035 Reviewed-by: Cherry Mui Reviewed-by: Michael Pratt LUCI-TryBot-Result: Go LUCI Reviewed-by: Junyang Shao --- src/runtime/cgo/gcc_darwin_amd64.c | 30 ----- src/runtime/cgo/gcc_dragonfly_amd64.c | 29 ----- src/runtime/cgo/gcc_freebsd.c | 57 +++------ src/runtime/cgo/gcc_freebsd_amd64.c | 41 ------ .../{gcc_darwin_arm64.c => gcc_ios_arm64.c} | 29 ++--- src/runtime/cgo/gcc_libinit.c | 24 ---- src/runtime/cgo/gcc_linux.c | 37 ------ src/runtime/cgo/gcc_linux_amd64.c | 63 ---------- src/runtime/cgo/gcc_linux_arm64.c | 58 --------- src/runtime/cgo/gcc_linux_s390x.c | 34 ----- src/runtime/cgo/gcc_netbsd.c | 70 ++++------- src/runtime/cgo/gcc_openbsd.c | 31 ----- src/runtime/cgo/gcc_ppc64x.c | 38 ------ src/runtime/cgo/gcc_unix.c | 118 ++++++++++++++++++ src/runtime/cgo/libcgo_unix.h | 5 - 15 files changed, 168 insertions(+), 496 deletions(-) delete mode 100644 src/runtime/cgo/gcc_darwin_amd64.c delete mode 100644 src/runtime/cgo/gcc_dragonfly_amd64.c delete mode 100644 src/runtime/cgo/gcc_freebsd_amd64.c rename src/runtime/cgo/{gcc_darwin_arm64.c => gcc_ios_arm64.c} (84%) delete mode 100644 src/runtime/cgo/gcc_linux.c delete mode 100644 src/runtime/cgo/gcc_linux_amd64.c delete mode 100644 src/runtime/cgo/gcc_linux_arm64.c delete mode 100644 src/runtime/cgo/gcc_linux_s390x.c delete mode 100644 src/runtime/cgo/gcc_openbsd.c delete mode 100644 src/runtime/cgo/gcc_ppc64x.c create mode 100644 src/runtime/cgo/gcc_unix.c diff --git a/src/runtime/cgo/gcc_darwin_amd64.c b/src/runtime/cgo/gcc_darwin_amd64.c deleted file mode 100644 index 0a9198e29f..0000000000 --- a/src/runtime/cgo/gcc_darwin_amd64.c +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include /* for strerror */ -#include "libcgo.h" -#include "libcgo_unix.h" - -static void (*setg_gcc)(void*); - -void -x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) -{ - setg_gcc = setg; - _cgo_set_stacklo(g, NULL); -} - - -extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -void* -threadentry(void *v) -{ - ThreadStart ts; - - ts = *(ThreadStart*)v; - free(v); - - crosscall1(ts.fn, setg_gcc, (void*)ts.g); - return nil; -} diff --git a/src/runtime/cgo/gcc_dragonfly_amd64.c b/src/runtime/cgo/gcc_dragonfly_amd64.c deleted file mode 100644 index 4851b2a6a0..0000000000 --- a/src/runtime/cgo/gcc_dragonfly_amd64.c +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include -#include "libcgo.h" -#include "libcgo_unix.h" - -static void (*setg_gcc)(void*); - -void -x_cgo_init(G *g, void (*setg)(void*)) -{ - setg_gcc = setg; - _cgo_set_stacklo(g, NULL); -} - -extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -void* -threadentry(void *v) -{ - ThreadStart ts; - - ts = *(ThreadStart*)v; - free(v); - - crosscall1(ts.fn, setg_gcc, (void*)ts.g); - return nil; -} diff --git a/src/runtime/cgo/gcc_freebsd.c b/src/runtime/cgo/gcc_freebsd.c index b5adecc5f1..606d6bd591 100644 --- a/src/runtime/cgo/gcc_freebsd.c +++ b/src/runtime/cgo/gcc_freebsd.c @@ -1,41 +1,16 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build freebsd && (386 || arm || arm64 || riscv64) - -#include -#include -#include "libcgo.h" -#include "libcgo_unix.h" - -#ifdef ARM_TP_ADDRESS -// ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000 -// and is known to runtime.read_tls_fallback. Verify it with -// cpp. -#if ARM_TP_ADDRESS != 0xffff1000 -#error Wrong ARM_TP_ADDRESS! -#endif -#endif - -static void (*setg_gcc)(void*); - -void -x_cgo_init(G *g, void (*setg)(void*)) -{ - setg_gcc = setg; - _cgo_set_stacklo(g, NULL); -} - -extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -void* -threadentry(void *v) -{ - ThreadStart ts; - - ts = *(ThreadStart*)v; - free(v); - - crosscall1(ts.fn, setg_gcc, ts.g); - return nil; -} +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build freebsd + +#include + +#ifdef ARM_TP_ADDRESS +// ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000 +// and is known to runtime.read_tls_fallback. Verify it with +// cpp. +#if ARM_TP_ADDRESS != 0xffff1000 +#error Wrong ARM_TP_ADDRESS! +#endif +#endif diff --git a/src/runtime/cgo/gcc_freebsd_amd64.c b/src/runtime/cgo/gcc_freebsd_amd64.c deleted file mode 100644 index 0fa81495a3..0000000000 --- a/src/runtime/cgo/gcc_freebsd_amd64.c +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include -#include -#include "libcgo.h" -#include "libcgo_unix.h" - -static void (*setg_gcc)(void*); - -void -x_cgo_init(G *g, void (*setg)(void*)) -{ - uintptr *pbounds; - - // Deal with memory sanitizer/clang interaction. - // See gcc_linux_amd64.c for details. - setg_gcc = setg; - pbounds = (uintptr*)malloc(2 * sizeof(uintptr)); - if (pbounds == NULL) { - fatalf("malloc failed: %s", strerror(errno)); - } - _cgo_set_stacklo(g, pbounds); - free(pbounds); -} - -extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -void* -threadentry(void *v) -{ - ThreadStart ts; - - ts = *(ThreadStart*)v; - _cgo_tsan_acquire(); - free(v); - _cgo_tsan_release(); - - crosscall1(ts.fn, setg_gcc, (void*)ts.g); - return nil; -} diff --git a/src/runtime/cgo/gcc_darwin_arm64.c b/src/runtime/cgo/gcc_ios_arm64.c similarity index 84% rename from src/runtime/cgo/gcc_darwin_arm64.c rename to src/runtime/cgo/gcc_ios_arm64.c index e502851fc1..32f517d464 100644 --- a/src/runtime/cgo/gcc_darwin_arm64.c +++ b/src/runtime/cgo/gcc_ios_arm64.c @@ -9,7 +9,6 @@ #include #include "libcgo.h" -#include "libcgo_unix.h" #include @@ -18,27 +17,16 @@ #include #endif -static void (*setg_gcc)(void*); +#if TARGET_OS_IPHONE -extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -void* -threadentry(void *v) +static void +threadentry_platform(void) { - ThreadStart ts; - - ts = *(ThreadStart*)v; - free(v); - #if TARGET_OS_IPHONE darwin_arm_init_thread_exception_port(); #endif - - crosscall1(ts.fn, setg_gcc, (void*)ts.g); - return nil; } -#if TARGET_OS_IPHONE - // init_working_dir sets the current working directory to the app root. // By default ios/arm64 processes start in "/". static void @@ -101,16 +89,15 @@ init_working_dir() #endif // TARGET_OS_IPHONE -void -x_cgo_init(G *g, void (*setg)(void*)) +static void +init_platform() { - //fprintf(stderr, "x_cgo_init = %p\n", &x_cgo_init); // aid debugging in presence of ASLR - setg_gcc = setg; - _cgo_set_stacklo(g, NULL); - #if TARGET_OS_IPHONE darwin_arm_init_mach_exception_handler(); darwin_arm_init_thread_exception_port(); init_working_dir(); #endif } + +void (*x_cgo_init_platform)(void) = init_platform; +void (*x_cgo_threadentry_platform)(void) = threadentry_platform; diff --git a/src/runtime/cgo/gcc_libinit.c b/src/runtime/cgo/gcc_libinit.c index 4b163c2d19..9d2402636e 100644 --- a/src/runtime/cgo/gcc_libinit.c +++ b/src/runtime/cgo/gcc_libinit.c @@ -83,30 +83,6 @@ _cgo_wait_runtime_init_done(void) { return 0; } -// _cgo_set_stacklo sets g->stacklo based on the stack size. -// This is common code called from x_cgo_init, which is itself -// called by rt0_go in the runtime package. -void _cgo_set_stacklo(G *g, uintptr *pbounds) -{ - uintptr bounds[2]; - - // pbounds can be passed in by the caller; see gcc_linux_amd64.c. - if (pbounds == NULL) { - pbounds = &bounds[0]; - } - - x_cgo_getstackbound(pbounds); - - g->stacklo = *pbounds; - - // Sanity check the results now, rather than getting a - // morestack on g0 crash. - if (g->stacklo >= g->stackhi) { - fprintf(stderr, "runtime/cgo: bad stack bounds: lo=%p hi=%p\n", (void*)(g->stacklo), (void*)(g->stackhi)); - abort(); - } -} - // Store the g into a thread-specific value associated with the pthread key pthread_g. // And pthread_key_destructor will dropm when the thread is exiting. void x_cgo_bindm(void* g) { diff --git a/src/runtime/cgo/gcc_linux.c b/src/runtime/cgo/gcc_linux.c deleted file mode 100644 index cdccbf3454..0000000000 --- a/src/runtime/cgo/gcc_linux.c +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux && (386 || arm || loong64 || mips || mipsle || mips64 || mips64le || riscv64) - -#include -#include "libcgo.h" -#include "libcgo_unix.h" - -void (*x_cgo_inittls)(void **tlsg, void **tlsbase) __attribute__((common)); -static void (*setg_gcc)(void*); - -void -x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) -{ - setg_gcc = setg; - - _cgo_set_stacklo(g, NULL); - - if (x_cgo_inittls) { - x_cgo_inittls(tlsg, tlsbase); - } -} - -extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -void* -threadentry(void *v) -{ - ThreadStart ts; - - ts = *(ThreadStart*)v; - free(v); - - crosscall1(ts.fn, setg_gcc, ts.g); - return nil; -} diff --git a/src/runtime/cgo/gcc_linux_amd64.c b/src/runtime/cgo/gcc_linux_amd64.c deleted file mode 100644 index 35c4f76457..0000000000 --- a/src/runtime/cgo/gcc_linux_amd64.c +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include -#include // strerror -#include -#include "libcgo.h" -#include "libcgo_unix.h" - -static void (*setg_gcc)(void*); - -// This will be set in gcc_android.c for android-specific customization. -void (*x_cgo_inittls)(void **tlsg, void **tlsbase) __attribute__((common)); - -void -x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) -{ - uintptr *pbounds; - - /* The memory sanitizer distributed with versions of clang - before 3.8 has a bug: if you call mmap before malloc, mmap - may return an address that is later overwritten by the msan - library. Avoid this problem by forcing a call to malloc - here, before we ever call malloc. - - This is only required for the memory sanitizer, so it's - unfortunate that we always run it. It should be possible - to remove this when we no longer care about versions of - clang before 3.8. The test for this is - misc/cgo/testsanitizers. - - GCC works hard to eliminate a seemingly unnecessary call to - malloc, so we actually use the memory we allocate. */ - - setg_gcc = setg; - pbounds = (uintptr*)malloc(2 * sizeof(uintptr)); - if (pbounds == NULL) { - fatalf("malloc failed: %s", strerror(errno)); - } - _cgo_set_stacklo(g, pbounds); - free(pbounds); - - if (x_cgo_inittls) { - x_cgo_inittls(tlsg, tlsbase); - } -} - - -extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -void* -threadentry(void *v) -{ - ThreadStart ts; - - ts = *(ThreadStart*)v; - _cgo_tsan_acquire(); - free(v); - _cgo_tsan_release(); - - crosscall1(ts.fn, setg_gcc, (void*)ts.g); - return nil; -} diff --git a/src/runtime/cgo/gcc_linux_arm64.c b/src/runtime/cgo/gcc_linux_arm64.c deleted file mode 100644 index bd4b36a553..0000000000 --- a/src/runtime/cgo/gcc_linux_arm64.c +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include -#include -#include -#include "libcgo.h" -#include "libcgo_unix.h" - -void (*x_cgo_inittls)(void **tlsg, void **tlsbase) __attribute__((common)); -static void (*setg_gcc)(void*); - -extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -void* -threadentry(void *v) -{ - ThreadStart ts; - - ts = *(ThreadStart*)v; - free(v); - - crosscall1(ts.fn, setg_gcc, (void*)ts.g); - return nil; -} - -void -x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) -{ - uintptr *pbounds; - - /* The memory sanitizer distributed with versions of clang - before 3.8 has a bug: if you call mmap before malloc, mmap - may return an address that is later overwritten by the msan - library. Avoid this problem by forcing a call to malloc - here, before we ever call malloc. - - This is only required for the memory sanitizer, so it's - unfortunate that we always run it. It should be possible - to remove this when we no longer care about versions of - clang before 3.8. The test for this is - misc/cgo/testsanitizers. - - GCC works hard to eliminate a seemingly unnecessary call to - malloc, so we actually use the memory we allocate. */ - - setg_gcc = setg; - pbounds = (uintptr*)malloc(2 * sizeof(uintptr)); - if (pbounds == NULL) { - fatalf("malloc failed: %s", strerror(errno)); - } - _cgo_set_stacklo(g, pbounds); - free(pbounds); - - if (x_cgo_inittls) { - x_cgo_inittls(tlsg, tlsbase); - } -} diff --git a/src/runtime/cgo/gcc_linux_s390x.c b/src/runtime/cgo/gcc_linux_s390x.c deleted file mode 100644 index 8f055e3087..0000000000 --- a/src/runtime/cgo/gcc_linux_s390x.c +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include -#include "libcgo.h" -#include "libcgo_unix.h" - -void (*x_cgo_inittls)(void **tlsg, void **tlsbase); -static void (*setg_gcc)(void*); - -void -x_cgo_init(G *g, void (*setg)(void*), void **tlsbase) -{ - setg_gcc = setg; - _cgo_set_stacklo(g, NULL); -} - -extern void crosscall_s390x(void (*fn)(void), void *g); - -void* -threadentry(void *v) -{ - ThreadStart ts; - - ts = *(ThreadStart*)v; - free(v); - - // Save g for this thread in C TLS - setg_gcc((void*)ts.g); - - crosscall_s390x(ts.fn, (void*)ts.g); - return nil; -} diff --git a/src/runtime/cgo/gcc_netbsd.c b/src/runtime/cgo/gcc_netbsd.c index c8c0969108..4e92c86f86 100644 --- a/src/runtime/cgo/gcc_netbsd.c +++ b/src/runtime/cgo/gcc_netbsd.c @@ -1,44 +1,26 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build netbsd && (386 || amd64 || arm || arm64) - -#include -#include -#include "libcgo.h" -#include "libcgo_unix.h" - -static void (*setg_gcc)(void*); - -void -x_cgo_init(G *g, void (*setg)(void*)) -{ - setg_gcc = setg; - _cgo_set_stacklo(g, NULL); -} - -extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -void* -threadentry(void *v) -{ - ThreadStart ts; - stack_t ss; - - ts = *(ThreadStart*)v; - free(v); - - // 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 - // a bit baroque to remove a signal stack here only to add one - // in minit, but it's a simple change that keeps NetBSD - // working like other OS's. At this point all signals are - // blocked, so there is no race. - memset(&ss, 0, sizeof ss); - ss.ss_flags = SS_DISABLE; - sigaltstack(&ss, nil); - - crosscall1(ts.fn, setg_gcc, ts.g); - return nil; -} +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build netbsd + +#include +#include + +static void +threadentry_platform(void) +{ + // 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 + // a bit baroque to remove a signal stack here only to add one + // in minit, but it's a simple change that keeps NetBSD + // working like other OS's. At this point all signals are + // blocked, so there is no race. + stack_t ss; + memset(&ss, 0, sizeof ss); + ss.ss_flags = SS_DISABLE; + sigaltstack(&ss, NULL); +} + +void (*x_cgo_threadentry_platform)(void) = threadentry_platform; diff --git a/src/runtime/cgo/gcc_openbsd.c b/src/runtime/cgo/gcc_openbsd.c deleted file mode 100644 index 166b9cd756..0000000000 --- a/src/runtime/cgo/gcc_openbsd.c +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build openbsd && (386 || arm || amd64 || arm64 || riscv64) - -#include -#include "libcgo.h" -#include "libcgo_unix.h" - -static void (*setg_gcc)(void*); - -void -x_cgo_init(G *g, void (*setg)(void*)) -{ - setg_gcc = setg; - _cgo_set_stacklo(g, NULL); -} - -extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -void* -threadentry(void *v) -{ - ThreadStart ts; - - ts = *(ThreadStart*)v; - free(v); - - crosscall1(ts.fn, setg_gcc, ts.g); - return nil; -} diff --git a/src/runtime/cgo/gcc_ppc64x.c b/src/runtime/cgo/gcc_ppc64x.c deleted file mode 100644 index 6f5a0bd9ad..0000000000 --- a/src/runtime/cgo/gcc_ppc64x.c +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build ppc64 || ppc64le - -#include -#include "libcgo.h" -#include "libcgo_unix.h" - -void (*x_cgo_inittls)(void **tlsg, void **tlsbase); -static void (*setg_gcc)(void*); - -void -x_cgo_init(G *g, void (*setg)(void*), void **tlsbase) -{ - setg_gcc = setg; - _cgo_set_stacklo(g, NULL); -} - -extern void crosscall_ppc64(void (*fn)(void), void *g); - -void* -threadentry(void *v) -{ - ThreadStart ts; - - ts = *(ThreadStart*)v; - _cgo_tsan_acquire(); - free(v); - _cgo_tsan_release(); - - // Save g for this thread in C TLS - setg_gcc((void*)ts.g); - - crosscall_ppc64(ts.fn, (void*)ts.g); - return nil; -} diff --git a/src/runtime/cgo/gcc_unix.c b/src/runtime/cgo/gcc_unix.c new file mode 100644 index 0000000000..6004f8ca11 --- /dev/null +++ b/src/runtime/cgo/gcc_unix.c @@ -0,0 +1,118 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build unix && !solaris + +#include +#include +#include +#include "libcgo.h" +#include "libcgo_unix.h" + +// Platform-specific hooks. +void (*x_cgo_inittls)(void **tlsg, void **tlsbase) __attribute__((weak)); +void (*x_cgo_init_platform)(void) __attribute__((weak)); +void (*x_cgo_threadentry_platform)(void) __attribute__((weak)); + +static void (*setg_gcc)(void*); + +// _cgo_set_stacklo sets g->stacklo based on the stack size. +// This is common code called from x_cgo_init, which is itself +// called by rt0_go in the runtime package. +static void +_cgo_set_stacklo(G *g) +{ + uintptr bounds[2]; + + x_cgo_getstackbound(bounds); + + g->stacklo = bounds[0]; + + // Sanity check the results now, rather than getting a + // morestack on g0 crash. + if (g->stacklo >= g->stackhi) { + fprintf(stderr, "runtime/cgo: bad stack bounds: lo=%p hi=%p\n", (void*)(g->stacklo), (void*)(g->stackhi)); + abort(); + } +} + +static void +clang_init() +{ +#if defined(__linux__) && (defined(__x86_64__) || defined(__aarch64__)) + /* The memory sanitizer distributed with versions of clang + before 3.8 has a bug: if you call mmap before malloc, mmap + may return an address that is later overwritten by the msan + library. Avoid this problem by forcing a call to malloc + here, before we ever call malloc. + + This is only required for the memory sanitizer, so it's + unfortunate that we always run it. It should be possible + to remove this when we no longer care about versions of + clang before 3.8. The test for this is + cmd/cgo/internal/testsanitizers . */ + uintptr *p; + p = (uintptr*)malloc(sizeof(uintptr)); + if (p == NULL) { + fatalf("malloc failed: %s", strerror(errno)); + } + /* GCC works hard to eliminate a seemingly unnecessary call to + malloc, so we actually touch the memory we allocate. */ + ((volatile char *)p)[0] = 0; + free(p); +#endif +} + +void +x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) +{ + clang_init(); + setg_gcc = setg; + _cgo_set_stacklo(g); + + if (x_cgo_inittls) { + x_cgo_inittls(tlsg, tlsbase); + } + if (x_cgo_init_platform) { + x_cgo_init_platform(); + } +} + +// TODO: change crosscall_ppc64 and crosscall_s390x so that it matches crosscall1 +// signature and behavior. +#if defined(__powerpc64__) +extern void crosscall_ppc64(void (*fn)(void), void *g); +#elif defined(__s390x__) +extern void crosscall_s390x(void (*fn)(void), void *g); +#else +extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); +#endif + +void* +threadentry(void *v) +{ + ThreadStart ts; + + ts = *(ThreadStart*)v; + _cgo_tsan_acquire(); + free(v); + _cgo_tsan_release(); + + if (x_cgo_threadentry_platform != NULL) { + x_cgo_threadentry_platform(); + } + +#if defined(__powerpc64__) + // Save g for this thread in C TLS + setg_gcc((void*)ts.g); + crosscall_ppc64(ts.fn, (void*)ts.g); +#elif defined(__s390x__) + // Save g for this thread in C TLS + setg_gcc((void*)ts.g); + crosscall_s390x(ts.fn, (void*)ts.g); +#else + crosscall1(ts.fn, setg_gcc, ts.g); +#endif + return NULL; +} diff --git a/src/runtime/cgo/libcgo_unix.h b/src/runtime/cgo/libcgo_unix.h index 5ce0224523..604fd5dc1b 100644 --- a/src/runtime/cgo/libcgo_unix.h +++ b/src/runtime/cgo/libcgo_unix.h @@ -4,11 +4,6 @@ #include -/* - * Initialize g->stacklo. - */ -extern void _cgo_set_stacklo(G *, uintptr *); - /* * Call pthread_create, retrying on EAGAIN. */