diff options
| author | qmuntal <quimmuntal@gmail.com> | 2026-04-01 16:07:46 +0200 |
|---|---|---|
| committer | Quim Muntal <quimmuntal@gmail.com> | 2026-04-10 03:20:39 -0700 |
| commit | 0e31741044d519065f62a5e96499909d6cd230dc (patch) | |
| tree | a9d4b59be92296a7de8640b8eee9842bc9c3c48e | |
| parent | 824a8a315668598436072566727cc5b28ac2f8c9 (diff) | |
| download | go-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>
| -rw-r--r-- | src/runtime/libinit.go | 18 | ||||
| -rw-r--r-- | src/runtime/os_aix.go | 7 | ||||
| -rw-r--r-- | src/runtime/sys_aix_ppc64.s | 9 |
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 |
