diff options
| author | qmuntal <quimmuntal@gmail.com> | 2025-09-30 14:54:16 +0200 |
|---|---|---|
| committer | Quim Muntal <quimmuntal@gmail.com> | 2026-02-13 08:07:09 -0800 |
| commit | 65b9017c0e955ad57fb42c3bf82aa0ff51ddbff5 (patch) | |
| tree | 5c746c95203f2485f02c48c1cd960e5eeaf0f94d /src/runtime | |
| parent | c9cbeb0a1b08a9830a3d2d4abe0c2108e52f7647 (diff) | |
| download | go-65b9017c0e955ad57fb42c3bf82aa0ff51ddbff5.tar.xz | |
runtime/cgo: deduplicate pthreads-related functions
Almost all pthread-related functions are exactly the same for Unix OSes.
Their implementation can be shared, taking into account the small
differences using standard predefined macros.
Cq-Include-Trybots: luci.golang.try:gotip-freebsd-amd64,gotip-darwin-amd64_14,gotip-darwin-arm64_15,gotip-netbsd-arm64,gotip-openbsd-amd64,gotip-openbsd-ppc64,gotip-solaris-amd64,gotip-linux-ppc64_power10
Change-Id: I8bee25f0619a5b315439cf12d94312c36c3e5a73
Reviewed-on: https://go-review.googlesource.com/c/go/+/707955
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/cgo/gcc_darwin_amd64.c | 33 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_darwin_arm64.c | 34 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_dragonfly_amd64.c | 34 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_fatalf.c | 2 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_freebsd.c | 33 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_freebsd_amd64.c | 33 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_libinit.c | 41 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_libinit_windows.c | 2 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_linux.c | 32 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_linux_amd64.c | 31 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_linux_arm64.c | 32 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_linux_s390x.c | 32 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_netbsd.c | 32 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_openbsd.c | 33 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_ppc64x.c | 32 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_solaris_amd64.c | 39 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_stack_darwin.c | 25 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_stack_unix.c | 48 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_stack_windows.c | 7 | ||||
| -rw-r--r-- | src/runtime/cgo/libcgo_unix.h | 4 | ||||
| -rw-r--r-- | src/runtime/cgo/pthread_unix.c | 138 |
21 files changed, 158 insertions, 539 deletions
diff --git a/src/runtime/cgo/gcc_darwin_amd64.c b/src/runtime/cgo/gcc_darwin_amd64.c index 1ffbbd75f2..0a9198e29f 100644 --- a/src/runtime/cgo/gcc_darwin_amd64.c +++ b/src/runtime/cgo/gcc_darwin_amd64.c @@ -3,12 +3,9 @@ // license that can be found in the LICENSE file. #include <string.h> /* for strerror */ -#include <pthread.h> -#include <signal.h> #include "libcgo.h" #include "libcgo_unix.h" -static void* threadentry(void*); static void (*setg_gcc)(void*); void @@ -19,36 +16,8 @@ x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) } -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - size_t size; - int err; - - sigfillset(&ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - size = pthread_get_stacksize_np(pthread_self()); - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, size); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - // Leave stacklo=0 and set stackhi=size; mstart will do the rest. - ts->g->stackhi = size; - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); - abort(); - } -} - extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_darwin_arm64.c b/src/runtime/cgo/gcc_darwin_arm64.c index e800e9303c..e502851fc1 100644 --- a/src/runtime/cgo/gcc_darwin_arm64.c +++ b/src/runtime/cgo/gcc_darwin_arm64.c @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. #include <limits.h> -#include <pthread.h> -#include <signal.h> #include <string.h> /* for strerror */ #include <sys/param.h> #include <unistd.h> @@ -20,40 +18,10 @@ #include <CoreFoundation/CFString.h> #endif -static void *threadentry(void*); static void (*setg_gcc)(void*); -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - size_t size; - int err; - - //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug - sigfillset(&ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - size = pthread_get_stacksize_np(pthread_self()); - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, size); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - // Leave stacklo=0 and set stackhi=size; mstart will do the rest. - ts->g->stackhi = size; - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); - abort(); - } -} - extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_dragonfly_amd64.c b/src/runtime/cgo/gcc_dragonfly_amd64.c index 646e9e653a..4851b2a6a0 100644 --- a/src/runtime/cgo/gcc_dragonfly_amd64.c +++ b/src/runtime/cgo/gcc_dragonfly_amd64.c @@ -2,15 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -#include <sys/types.h> -#include <sys/signalvar.h> -#include <pthread.h> -#include <signal.h> #include <string.h> #include "libcgo.h" #include "libcgo_unix.h" -static void* threadentry(void*); static void (*setg_gcc)(void*); void @@ -20,35 +15,8 @@ x_cgo_init(G *g, void (*setg)(void*)) _cgo_set_stacklo(g, NULL); } -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - size_t size; - int err; - - SIGFILLSET(ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_getstacksize(&attr, &size); - - // Leave stacklo=0 and set stackhi=size; mstart will do the rest. - ts->g->stackhi = size; - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fatalf("pthread_create failed: %s", strerror(err)); - } -} - extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_fatalf.c b/src/runtime/cgo/gcc_fatalf.c index 822c0150bd..8d46e9187d 100644 --- a/src/runtime/cgo/gcc_fatalf.c +++ b/src/runtime/cgo/gcc_fatalf.c @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build aix || (!android && linux) || dragonfly || freebsd || netbsd || openbsd || solaris +//go:build unix && !android #include <stdarg.h> #include <stdio.h> diff --git a/src/runtime/cgo/gcc_freebsd.c b/src/runtime/cgo/gcc_freebsd.c index 1cc582a3bb..b5adecc5f1 100644 --- a/src/runtime/cgo/gcc_freebsd.c +++ b/src/runtime/cgo/gcc_freebsd.c @@ -4,11 +4,7 @@ //go:build freebsd && (386 || arm || arm64 || riscv64) -#include <sys/types.h> -#include <sys/signalvar.h> #include <machine/sysarch.h> -#include <pthread.h> -#include <signal.h> #include <string.h> #include "libcgo.h" #include "libcgo_unix.h" @@ -22,7 +18,6 @@ #endif #endif -static void* threadentry(void*); static void (*setg_gcc)(void*); void @@ -32,34 +27,8 @@ x_cgo_init(G *g, void (*setg)(void*)) _cgo_set_stacklo(g, NULL); } -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - size_t size; - int err; - - SIGFILLSET(ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_getstacksize(&attr, &size); - // Leave stacklo=0 and set stackhi=size; mstart will do the rest. - ts->g->stackhi = size; - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fatalf("pthread_create failed: %s", strerror(err)); - } -} - extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_freebsd_amd64.c b/src/runtime/cgo/gcc_freebsd_amd64.c index ec23a00fee..0fa81495a3 100644 --- a/src/runtime/cgo/gcc_freebsd_amd64.c +++ b/src/runtime/cgo/gcc_freebsd_amd64.c @@ -2,16 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -#include <sys/types.h> #include <errno.h> -#include <sys/signalvar.h> -#include <pthread.h> -#include <signal.h> #include <string.h> #include "libcgo.h" #include "libcgo_unix.h" -static void* threadentry(void*); static void (*setg_gcc)(void*); void @@ -30,34 +25,8 @@ x_cgo_init(G *g, void (*setg)(void*)) free(pbounds); } -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - size_t size; - int err; - - SIGFILLSET(ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_getstacksize(&attr, &size); - // Leave stacklo=0 and set stackhi=size; mstart will do the rest. - ts->g->stackhi = size; - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fatalf("pthread_create failed: %s", strerror(err)); - } -} - extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_libinit.c b/src/runtime/cgo/gcc_libinit.c index 05998fadf8..4b163c2d19 100644 --- a/src/runtime/cgo/gcc_libinit.c +++ b/src/runtime/cgo/gcc_libinit.c @@ -12,11 +12,8 @@ #pragma GCC diagnostic ignored "-Watomic-alignment" #include <pthread.h> -#include <errno.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> // strerror -#include <time.h> #include "libcgo.h" #include "libcgo_unix.h" @@ -41,21 +38,6 @@ static void (*cgo_context_function)(struct cgoContextArg*); // The symbolizer function, used when symbolizing C frames. static void (*cgo_symbolizer_function)(struct cgoSymbolizerArg*); -void -x_cgo_sys_thread_create(void* (*func)(void*), void* arg) { - pthread_attr_t attr; - pthread_t p; - int err; - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - err = _cgo_try_pthread_create(&p, &attr, func, arg); - if (err != 0) { - fprintf(stderr, "pthread_create failed: %s", strerror(err)); - abort(); - } -} - uintptr_t _cgo_wait_runtime_init_done(void) { void (*pfn)(struct cgoContextArg*); @@ -208,29 +190,6 @@ void x_cgo_call_symbolizer_function(struct cgoSymbolizerArg* arg) { _cgo_tsan_release(); } -// _cgo_try_pthread_create retries pthread_create if it fails with -// EAGAIN. -int -_cgo_try_pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*pfn)(void*), void* arg) { - int tries; - int err; - struct timespec ts; - - for (tries = 0; tries < 20; tries++) { - err = pthread_create(thread, attr, pfn, arg); - if (err == 0) { - return 0; - } - if (err != EAGAIN) { - return err; - } - ts.tv_sec = 0; - ts.tv_nsec = (tries + 1) * 1000 * 1000; // Milliseconds. - nanosleep(&ts, nil); - } - return EAGAIN; -} - static void pthread_key_destructor(void* g) { if (x_crosscall2_ptr != NULL) { diff --git a/src/runtime/cgo/gcc_libinit_windows.c b/src/runtime/cgo/gcc_libinit_windows.c index 7e7ff3e667..d2082e0916 100644 --- a/src/runtime/cgo/gcc_libinit_windows.c +++ b/src/runtime/cgo/gcc_libinit_windows.c @@ -212,3 +212,5 @@ void _cgo_beginthread(unsigned long (__stdcall *func)(void*), void* arg) { fprintf(stderr, "runtime: failed to create new OS thread (%lu)\n", GetLastError()); abort(); } + +void x_cgo_getstackbound(uintptr bounds[2]) {} // no-op for now diff --git a/src/runtime/cgo/gcc_linux.c b/src/runtime/cgo/gcc_linux.c index fbdb5e652a..cdccbf3454 100644 --- a/src/runtime/cgo/gcc_linux.c +++ b/src/runtime/cgo/gcc_linux.c @@ -4,14 +4,10 @@ //go:build linux && (386 || arm || loong64 || mips || mipsle || mips64 || mips64le || riscv64) -#include <pthread.h> #include <string.h> -#include <signal.h> #include "libcgo.h" #include "libcgo_unix.h" -static void *threadentry(void*); - void (*x_cgo_inittls)(void **tlsg, void **tlsbase) __attribute__((common)); static void (*setg_gcc)(void*); @@ -27,34 +23,8 @@ x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) } } -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - size_t size; - int err; - - sigfillset(&ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_getstacksize(&attr, &size); - // Leave stacklo=0 and set stackhi=size; mstart will do the rest. - ts->g->stackhi = size; - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fatalf("pthread_create failed: %s", strerror(err)); - } -} - extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_linux_amd64.c b/src/runtime/cgo/gcc_linux_amd64.c index c81fde2887..35c4f76457 100644 --- a/src/runtime/cgo/gcc_linux_amd64.c +++ b/src/runtime/cgo/gcc_linux_amd64.c @@ -2,15 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -#include <pthread.h> #include <errno.h> #include <string.h> // strerror -#include <signal.h> #include <stdlib.h> #include "libcgo.h" #include "libcgo_unix.h" -static void* threadentry(void*); static void (*setg_gcc)(void*); // This will be set in gcc_android.c for android-specific customization. @@ -50,34 +47,8 @@ x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) } -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - size_t size; - int err; - - sigfillset(&ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_getstacksize(&attr, &size); - // Leave stacklo=0 and set stackhi=size; mstart will do the rest. - ts->g->stackhi = size; - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fatalf("pthread_create failed: %s", strerror(err)); - } -} - extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_linux_arm64.c b/src/runtime/cgo/gcc_linux_arm64.c index ce46804ba2..bd4b36a553 100644 --- a/src/runtime/cgo/gcc_linux_arm64.c +++ b/src/runtime/cgo/gcc_linux_arm64.c @@ -2,47 +2,17 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -#include <pthread.h> #include <errno.h> #include <string.h> -#include <signal.h> #include <stdlib.h> #include "libcgo.h" #include "libcgo_unix.h" -static void *threadentry(void*); - void (*x_cgo_inittls)(void **tlsg, void **tlsbase) __attribute__((common)); static void (*setg_gcc)(void*); -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - size_t size; - int err; - - sigfillset(&ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_getstacksize(&attr, &size); - // Leave stacklo=0 and set stackhi=size; mstart will do the rest. - ts->g->stackhi = size; - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fatalf("pthread_create failed: %s", strerror(err)); - } -} - extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_linux_s390x.c b/src/runtime/cgo/gcc_linux_s390x.c index 1fae4e7d44..8f055e3087 100644 --- a/src/runtime/cgo/gcc_linux_s390x.c +++ b/src/runtime/cgo/gcc_linux_s390x.c @@ -2,14 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -#include <pthread.h> #include <string.h> -#include <signal.h> #include "libcgo.h" #include "libcgo_unix.h" -static void *threadentry(void*); - void (*x_cgo_inittls)(void **tlsg, void **tlsbase); static void (*setg_gcc)(void*); @@ -20,35 +16,9 @@ x_cgo_init(G *g, void (*setg)(void*), void **tlsbase) _cgo_set_stacklo(g, NULL); } -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - size_t size; - int err; - - sigfillset(&ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_getstacksize(&attr, &size); - // Leave stacklo=0 and set stackhi=size; mstart will do the rest. - ts->g->stackhi = size; - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fatalf("pthread_create failed: %s", strerror(err)); - } -} - extern void crosscall_s390x(void (*fn)(void), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_netbsd.c b/src/runtime/cgo/gcc_netbsd.c index 98b629e805..c8c0969108 100644 --- a/src/runtime/cgo/gcc_netbsd.c +++ b/src/runtime/cgo/gcc_netbsd.c @@ -4,14 +4,11 @@ //go:build netbsd && (386 || amd64 || arm || arm64) -#include <sys/types.h> -#include <pthread.h> #include <signal.h> #include <string.h> #include "libcgo.h" #include "libcgo_unix.h" -static void* threadentry(void*); static void (*setg_gcc)(void*); void @@ -21,35 +18,8 @@ x_cgo_init(G *g, void (*setg)(void*)) _cgo_set_stacklo(g, NULL); } - -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - size_t size; - int err; - - sigfillset(&ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_getstacksize(&attr, &size); - // Leave stacklo=0 and set stackhi=size; mstart will do the rest. - ts->g->stackhi = size; - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fatalf("pthread_create failed: %s", strerror(err)); - } -} - extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_openbsd.c b/src/runtime/cgo/gcc_openbsd.c index b31c312f59..166b9cd756 100644 --- a/src/runtime/cgo/gcc_openbsd.c +++ b/src/runtime/cgo/gcc_openbsd.c @@ -4,14 +4,10 @@ //go:build openbsd && (386 || arm || amd64 || arm64 || riscv64) -#include <sys/types.h> -#include <pthread.h> -#include <signal.h> #include <string.h> #include "libcgo.h" #include "libcgo_unix.h" -static void* threadentry(void*); static void (*setg_gcc)(void*); void @@ -21,35 +17,8 @@ x_cgo_init(G *g, void (*setg)(void*)) _cgo_set_stacklo(g, NULL); } -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - size_t size; - int err; - - sigfillset(&ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_getstacksize(&attr, &size); - - // Leave stacklo=0 and set stackhi=size; mstart will do the rest. - ts->g->stackhi = size; - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fatalf("pthread_create failed: %s", strerror(err)); - } -} - extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_ppc64x.c b/src/runtime/cgo/gcc_ppc64x.c index e1a5c14ff9..6f5a0bd9ad 100644 --- a/src/runtime/cgo/gcc_ppc64x.c +++ b/src/runtime/cgo/gcc_ppc64x.c @@ -4,14 +4,10 @@ //go:build ppc64 || ppc64le -#include <pthread.h> #include <string.h> -#include <signal.h> #include "libcgo.h" #include "libcgo_unix.h" -static void *threadentry(void*); - void (*x_cgo_inittls)(void **tlsg, void **tlsbase); static void (*setg_gcc)(void*); @@ -22,35 +18,9 @@ x_cgo_init(G *g, void (*setg)(void*), void **tlsbase) _cgo_set_stacklo(g, NULL); } -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - size_t size; - int err; - - sigfillset(&ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_getstacksize(&attr, &size); - // Leave stacklo=0 and set stackhi=size; mstart will do the rest. - ts->g->stackhi = size; - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fatalf("pthread_create failed: %s", strerror(err)); - } -} - extern void crosscall_ppc64(void (*fn)(void), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_solaris_amd64.c b/src/runtime/cgo/gcc_solaris_amd64.c index 9b106a63ea..492522bdfb 100644 --- a/src/runtime/cgo/gcc_solaris_amd64.c +++ b/src/runtime/cgo/gcc_solaris_amd64.c @@ -2,14 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -#include <pthread.h> #include <string.h> -#include <signal.h> #include <ucontext.h> #include "libcgo.h" #include "libcgo_unix.h" -static void* threadentry(void*); static void (*setg_gcc)(void*); void @@ -35,42 +32,8 @@ x_cgo_init(G *g, void (*setg)(void*)) } } -void -_cgo_sys_thread_start(ThreadStart *ts) -{ - pthread_attr_t attr; - sigset_t ign, oset; - pthread_t p; - void *base; - size_t size; - int err; - - sigfillset(&ign); - pthread_sigmask(SIG_SETMASK, &ign, &oset); - - pthread_attr_init(&attr); - - if (pthread_attr_getstack(&attr, &base, &size) != 0) - perror("runtime/cgo: pthread_attr_getstack failed"); - if (size == 0) { - ts->g->stackhi = 2 << 20; - if (pthread_attr_setstack(&attr, NULL, ts->g->stackhi) != 0) - perror("runtime/cgo: pthread_attr_setstack failed"); - } else { - ts->g->stackhi = size; - } - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); - - pthread_sigmask(SIG_SETMASK, &oset, nil); - - if (err != 0) { - fatalf("pthread_create failed: %s", strerror(err)); - } -} - extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); -static void* +void* threadentry(void *v) { ThreadStart ts; diff --git a/src/runtime/cgo/gcc_stack_darwin.c b/src/runtime/cgo/gcc_stack_darwin.c deleted file mode 100644 index 28364c7420..0000000000 --- a/src/runtime/cgo/gcc_stack_darwin.c +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2023 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 <pthread.h> -#include "libcgo.h" - -void -x_cgo_getstackbound(uintptr bounds[2]) -{ - void* addr; - size_t size; - pthread_t p; - - p = pthread_self(); - addr = pthread_get_stackaddr_np(p); // high address (!) - size = pthread_get_stacksize_np(p); - - // bounds points into the Go stack. TSAN can't see the synchronization - // in Go around stack reuse. - _cgo_tsan_acquire(); - bounds[0] = (uintptr)addr - size; - bounds[1] = (uintptr)addr; - _cgo_tsan_release(); -} diff --git a/src/runtime/cgo/gcc_stack_unix.c b/src/runtime/cgo/gcc_stack_unix.c deleted file mode 100644 index 9550cd7839..0000000000 --- a/src/runtime/cgo/gcc_stack_unix.c +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2023 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 && !darwin - -#ifndef _GNU_SOURCE // pthread_getattr_np -#define _GNU_SOURCE -#endif - -#include <pthread.h> -#include "libcgo.h" - -void -x_cgo_getstackbound(uintptr bounds[2]) -{ - pthread_attr_t attr; - void *addr; - size_t size; - - // Needed before pthread_getattr_np, too, since before glibc 2.32 - // it did not call pthread_attr_init in all cases (see #65625). - pthread_attr_init(&attr); -#if defined(__GLIBC__) || defined(__BIONIC__) || (defined(__sun) && !defined(__illumos__)) - // pthread_getattr_np is a GNU extension supported in glibc. - // Solaris is not glibc but does support pthread_getattr_np - // (and the fallback doesn't work...). Illumos does not. - pthread_getattr_np(pthread_self(), &attr); // GNU extension - pthread_attr_getstack(&attr, &addr, &size); // low address -#elif defined(__illumos__) - pthread_attr_get_np(pthread_self(), &attr); - pthread_attr_getstack(&attr, &addr, &size); // low address -#else - // We don't know how to get the current stacks, leave it as - // 0 and the caller will use an estimate based on the current - // SP. - addr = 0; - size = 0; -#endif - pthread_attr_destroy(&attr); - - // bounds points into the Go stack. TSAN can't see the synchronization - // in Go around stack reuse. - _cgo_tsan_acquire(); - bounds[0] = (uintptr)addr; - bounds[1] = (uintptr)addr + size; - _cgo_tsan_release(); -} diff --git a/src/runtime/cgo/gcc_stack_windows.c b/src/runtime/cgo/gcc_stack_windows.c deleted file mode 100644 index d798cc77d1..0000000000 --- a/src/runtime/cgo/gcc_stack_windows.c +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2023 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 "libcgo.h" - -void x_cgo_getstackbound(uintptr bounds[2]) {} // no-op for now diff --git a/src/runtime/cgo/libcgo_unix.h b/src/runtime/cgo/libcgo_unix.h index b8f8d30d30..5ce0224523 100644 --- a/src/runtime/cgo/libcgo_unix.h +++ b/src/runtime/cgo/libcgo_unix.h @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +#include <pthread.h> + /* * Initialize g->stacklo. */ @@ -18,3 +20,5 @@ extern int _cgo_try_pthread_create(pthread_t*, const pthread_attr_t*, void* (*)( */ extern int _cgo_openbsd_try_pthread_create(int (*)(pthread_t*, const pthread_attr_t*, void *(*pfn)(void*), void*), pthread_t*, const pthread_attr_t*, void* (*)(void*), void* arg); + +extern void* threadentry(void*); diff --git a/src/runtime/cgo/pthread_unix.c b/src/runtime/cgo/pthread_unix.c new file mode 100644 index 0000000000..7b5248817a --- /dev/null +++ b/src/runtime/cgo/pthread_unix.c @@ -0,0 +1,138 @@ +// Copyright 2025 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
+
+#ifndef _GNU_SOURCE // pthread_getattr_np
+#define _GNU_SOURCE
+#endif
+
+#include <pthread.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include "libcgo.h"
+#include "libcgo_unix.h"
+
+void
+_cgo_sys_thread_start(ThreadStart *ts)
+{
+ pthread_attr_t attr;
+ sigset_t ign, oset;
+ pthread_t p;
+ size_t size;
+ int err;
+
+ sigfillset(&ign);
+ pthread_sigmask(SIG_SETMASK, &ign, &oset);
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+#if defined(__APPLE__)
+ // Copy stack size from parent thread instead of using the
+ // non-main thread default stack size.
+ size = pthread_get_stacksize_np(pthread_self());
+ pthread_attr_setstacksize(&attr, size);
+#else
+ pthread_attr_getstacksize(&attr, &size);
+#endif
+
+#if defined(__sun)
+ // Solaris can report 0 stack size, fix it.
+ if (size == 0) {
+ size = 2 << 20;
+ if (pthread_attr_setstacksize(&attr, size) != 0) {
+ perror("runtime/cgo: pthread_attr_setstacksize failed");
+ }
+ }
+#endif
+
+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
+ ts->g->stackhi = size;
+ err = _cgo_try_pthread_create(&p, &attr, threadentry, ts);
+
+ pthread_sigmask(SIG_SETMASK, &oset, nil);
+
+ if (err != 0) {
+ fatalf("pthread_create failed: %s", strerror(err));
+ }
+}
+
+void
+x_cgo_sys_thread_create(void* (*func)(void*), void* arg) {
+ pthread_attr_t attr;
+ pthread_t p;
+ int err;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ err = _cgo_try_pthread_create(&p, &attr, func, arg);
+ if (err != 0) {
+ fatalf("pthread_create failed: %s", strerror(err));
+ }
+}
+
+void
+x_cgo_getstackbound(uintptr bounds[2])
+{
+ pthread_attr_t attr;
+ void *addr;
+ size_t size;
+
+ // Needed before pthread_getattr_np, too, since before glibc 2.32
+ // it did not call pthread_attr_init in all cases (see #65625).
+ pthread_attr_init(&attr);
+#if defined(__APPLE__)
+ // On macOS/iOS, use the non-portable pthread_get_stackaddr_np
+ // and pthread_get_stacksize_np APIs (high address + size).
+ addr = pthread_get_stackaddr_np(pthread_self());
+ size = pthread_get_stacksize_np(pthread_self());
+ addr = (void*)((uintptr)addr - size); // convert to low address
+#elif defined(__GLIBC__) || defined(__BIONIC__) || (defined(__sun) && !defined(__illumos__))
+ // pthread_getattr_np is a GNU extension supported in glibc.
+ // Solaris is not glibc but does support pthread_getattr_np
+ // (and the fallback doesn't work...). Illumos does not.
+ pthread_getattr_np(pthread_self(), &attr); // GNU extension
+ pthread_attr_getstack(&attr, &addr, &size); // low address
+#elif defined(__illumos__)
+ pthread_attr_get_np(pthread_self(), &attr);
+ pthread_attr_getstack(&attr, &addr, &size); // low address
+#else
+ // We don't know how to get the current stacks, leave it as
+ // 0 and the caller will use an estimate based on the current
+ // SP.
+ addr = 0;
+ size = 0;
+#endif
+ pthread_attr_destroy(&attr);
+
+ // bounds points into the Go stack. TSAN can't see the synchronization
+ // in Go around stack reuse.
+ _cgo_tsan_acquire();
+ bounds[0] = (uintptr)addr;
+ bounds[1] = (uintptr)addr + size;
+ _cgo_tsan_release();
+}
+
+// _cgo_try_pthread_create retries pthread_create if it fails with EAGAIN.
+int
+_cgo_try_pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*pfn)(void*), void* arg) {
+ int tries;
+ int err;
+ struct timespec ts;
+
+ for (tries = 0; tries < 20; tries++) {
+ err = pthread_create(thread, attr, pfn, arg);
+ if (err == 0) {
+ return 0;
+ }
+ if (err != EAGAIN) {
+ return err;
+ }
+ ts.tv_sec = 0;
+ ts.tv_nsec = (tries + 1) * 1000 * 1000; // Milliseconds.
+ nanosleep(&ts, nil);
+ }
+ return EAGAIN;
+}
|
