aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorqmuntal <quimmuntal@gmail.com>2026-04-01 16:07:46 +0200
committerQuim Muntal <quimmuntal@gmail.com>2026-04-10 03:20:39 -0700
commit0e31741044d519065f62a5e96499909d6cd230dc (patch)
treea9d4b59be92296a7de8640b8eee9842bc9c3c48e /src/runtime
parent824a8a315668598436072566727cc5b28ac2f8c9 (diff)
downloadgo-0e31741044d519065f62a5e96499909d6cd230dc.tar.xz
runtime: fix AIX library initialization
On AIX, libInit passes a function descriptor instead of the function pointer to pthread_create. This is a regression from CL 706417. Change-Id: I660175eb992a41ef61b1927c51392887a724cd76 Reviewed-on: https://go-review.googlesource.com/c/go/+/761780 Reviewed-by: Ian Lance Taylor <iant@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/libinit.go18
-rw-r--r--src/runtime/os_aix.go7
-rw-r--r--src/runtime/sys_aix_ppc64.s9
3 files changed, 32 insertions, 2 deletions
diff --git a/src/runtime/libinit.go b/src/runtime/libinit.go
index 7e298a2eca..2c81f61644 100644
--- a/src/runtime/libinit.go
+++ b/src/runtime/libinit.go
@@ -11,6 +11,13 @@ import (
"unsafe"
)
+// rt0LibGoFn holds the function pointer to rt0_lib_go suitable for thread
+// creation. On most platforms it is zero, meaning the raw code address should
+// be used. On AIX it is set by libpreinit to a function descriptor pointer,
+// because pthread_create on AIX expects a function descriptor, not a raw
+// code address.
+var rt0LibGoFn uintptr
+
// libInit is common startup code for most architectures when
// using -buildmode=c-archive or -buildmode=c-shared.
//
@@ -22,13 +29,20 @@ func libInit() {
// Synchronous initialization.
libpreinit()
+ // Use the platform-specific function pointer if set (e.g. AIX
+ // function descriptor), otherwise fall back to the raw code address.
+ fn := unsafe.Pointer(rt0LibGoFn)
+ if fn == nil {
+ fn = unsafe.Pointer(abi.FuncPCABIInternal(rt0_lib_go))
+ }
+
// Asynchronous initialization.
// Prefer creating a thread via cgo if it is available.
if _cgo_sys_thread_create != nil {
// No g because the TLS is not set up until later in rt0_go.
- asmcgocall_no_g(_cgo_sys_thread_create, unsafe.Pointer(abi.FuncPCABIInternal(rt0_lib_go)))
+ asmcgocall_no_g(_cgo_sys_thread_create, fn)
} else {
const stackSize = 0x800000 // 8192KB
- newosproc0(stackSize, unsafe.Pointer(abi.FuncPCABIInternal(rt0_lib_go)))
+ newosproc0(stackSize, fn)
}
}
diff --git a/src/runtime/os_aix.go b/src/runtime/os_aix.go
index 7a667c2419..bf78869328 100644
--- a/src/runtime/os_aix.go
+++ b/src/runtime/os_aix.go
@@ -162,6 +162,10 @@ func newosproc0(stacksize uintptr, fn unsafe.Pointer) {
//go:nosplit
//go:nowritebarrierrec
func libpreinit() {
+ // On AIX, pthread_create expects a function descriptor pointer,
+ // not a raw code address. Set rt0LibGoFn to the descriptor
+ // so that libInit passes the right value.
+ rt0LibGoFn = uintptr(unsafe.Pointer(&rt0LibGoDesc))
initsig(true)
}
@@ -203,6 +207,9 @@ func mdestroy(mp *m) {
// tstart is a function descriptor to _tstart defined in assembly.
var tstart funcDescriptor
+// rt0LibGoDesc is a function descriptor to rt0_lib_go defined in assembly.
+var rt0LibGoDesc funcDescriptor
+
func newosproc(mp *m) {
var (
attr pthread_attr
diff --git a/src/runtime/sys_aix_ppc64.s b/src/runtime/sys_aix_ppc64.s
index a0ef7e111a..41a4fa330c 100644
--- a/src/runtime/sys_aix_ppc64.s
+++ b/src/runtime/sys_aix_ppc64.s
@@ -197,6 +197,15 @@ DATA runtime·tstart+8(SB)/8, $TOC(SB)
DATA runtime·tstart+16(SB)/8, $0
GLOBL runtime·tstart(SB), NOPTR, $24
+// runtime.rt0LibGoDesc is a function descriptor to rt0_lib_go,
+// used by libInit to create a new thread on AIX where
+// pthread_create expects a function descriptor, not a raw
+// code address.
+DATA runtime·rt0LibGoDesc+0(SB)/8, $runtime·rt0_lib_go(SB)
+DATA runtime·rt0LibGoDesc+8(SB)/8, $TOC(SB)
+DATA runtime·rt0LibGoDesc+16(SB)/8, $0
+GLOBL runtime·rt0LibGoDesc(SB), NOPTR, $24
+
TEXT tstart<>(SB),NOSPLIT,$0
XOR R0, R0 // reset R0