diff options
| author | Chressie Himpel <chressie@google.com> | 2023-05-05 14:17:38 +0000 |
|---|---|---|
| committer | Chressie Himpel <chressie@google.com> | 2023-05-05 14:37:29 +0000 |
| commit | 72c33a5ef0eea8663328375d9d339ed150310ebb (patch) | |
| tree | a4272daf751239fcb9b2f1b8e1730800629f738c /src/runtime/proc.go | |
| parent | f379e78951a405e7e99a60fb231eeedbf976c108 (diff) | |
| download | go-72c33a5ef0eea8663328375d9d339ed150310ebb.tar.xz | |
Revert "runtime/cgo: store M for C-created thread in pthread key"
This reverts CL 485500.
Reason for revert: This breaks internal tests at Google, see b/280861579 and b/280820455.
Change-Id: I426278d400f7611170918fc07c524cb059b9cc55
Reviewed-on: https://go-review.googlesource.com/c/go/+/492995
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Chressie Himpel <chressie@google.com>
Diffstat (limited to 'src/runtime/proc.go')
| -rw-r--r-- | src/runtime/proc.go | 118 |
1 files changed, 16 insertions, 102 deletions
diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 0b9df169b2..1b75b2fc91 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -209,10 +209,6 @@ func main() { main_init_done = make(chan bool) if iscgo { - if _cgo_pthread_key_created == nil { - throw("_cgo_pthread_key_created missing") - } - if _cgo_thread_start == nil { throw("_cgo_thread_start missing") } @@ -227,13 +223,6 @@ func main() { if _cgo_notify_runtime_init_done == nil { throw("_cgo_notify_runtime_init_done missing") } - - // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. - if set_crosscall2 == nil { - throw("set_crosscall2 missing") - } - set_crosscall2() - // Start the template thread in case we enter Go from // a C-created thread and need to create a new thread. startTemplateThread() @@ -1891,15 +1880,11 @@ func allocm(pp *p, fn func(), id int64) *m { // pressed into service as the scheduling stack and current // goroutine for the duration of the cgo callback. // -// It calls dropm to put the m back on the list, -// 1. when the callback is done with the m in non-pthread platforms, -// 2. or when the C thread exiting on pthread platforms. -// -// The signal argument indicates whether we're called from a signal -// handler. +// When the callback is done with the m, it calls dropm to +// put the m back on the list. // //go:nosplit -func needm(signal bool) { +func needm() { if (iscgo || GOOS == "windows") && !cgoHasExtraM { // Can happen if C/C++ code calls Go from a global ctor. // Can also happen on Windows if a global ctor uses a @@ -1948,36 +1933,16 @@ func needm(signal bool) { osSetupTLS(mp) // Install g (= m->g0) and set the stack bounds - // to match the current stack. If we don't actually know + // to match the current stack. We don't actually know // how big the stack is, like we don't know how big any - // scheduling stack is, but we assume there's at least 32 kB. - // If we can get a more accurate stack bound from pthread, - // use that. + // scheduling stack is, but we assume there's at least 32 kB, + // which is more than enough for us. setg(mp.g0) gp := getg() gp.stack.hi = getcallersp() + 1024 gp.stack.lo = getcallersp() - 32*1024 - if !signal && _cgo_getstackbound != nil { - // Don't adjust if called from the signal handler. - // We are on the signal stack, not the pthread stack. - // (We could get the stack bounds from sigaltstack, but - // we're getting out of the signal handler very soon - // anyway. Not worth it.) - var low uintptr - asmcgocall(_cgo_getstackbound, unsafe.Pointer(&low)) - // getstackbound is an unsupported no-op on Windows. - if low != 0 { - gp.stack.lo = low - // TODO: Also get gp.stack.hi from getstackbound. - } - } gp.stackguard0 = gp.stack.lo + stackGuard - // Should mark we are already in Go now. - // Otherwise, we may call needm again when we get a signal, before cgocallbackg1, - // which means the extram list may be empty, that will cause a deadlock. - mp.isExtraInC = false - // Initialize this thread to use the m. asminit() minit() @@ -1987,17 +1952,6 @@ func needm(signal bool) { sched.ngsys.Add(-1) } -// Acquire an extra m and bind it to the C thread when a pthread key has been created. -// -//go:nosplit -func needAndBindM() { - needm(false) - - if _cgo_pthread_key_created != nil && *(*uintptr)(_cgo_pthread_key_created) != 0 { - cgoBindM() - } -} - // newextram allocates m's and puts them on the extra list. // It is called with a working local m, so that it can do things // like call schedlock and allocate. @@ -2042,8 +1996,6 @@ func oneNewExtraM() { gp.m = mp mp.curg = gp mp.isextra = true - // mark we are in C by default. - mp.isExtraInC = true mp.lockedInt++ mp.lockedg.set(gp) gp.lockedm.set(mp) @@ -2076,11 +2028,9 @@ func oneNewExtraM() { unlockextra(mp) } -// dropm puts the current m back onto the extra list. -// -// 1. On systems without pthreads, like Windows // dropm is called when a cgo callback has called needm but is now // done with the callback and returning back into the non-Go thread. +// It puts the current m back onto the extra list. // // The main expense here is the call to signalstack to release the // m's signal stack, and then the call to needm on the next callback @@ -2092,18 +2042,15 @@ func oneNewExtraM() { // call. These should typically not be scheduling operations, just a few // atomics, so the cost should be small. // -// 2. On systems with pthreads -// dropm is called while a non-Go thread is exiting. -// We allocate a pthread per-thread variable using pthread_key_create, -// to register a thread-exit-time destructor. -// And store the g into a thread-specific value associated with the pthread key, -// when first return back to C. -// So that the destructor would invoke dropm while the non-Go thread is exiting. -// This is much faster since it avoids expensive signal-related syscalls. -// -// NOTE: this always runs without a P, so, nowritebarrierrec required. -// -//go:nowritebarrierrec +// TODO(rsc): An alternative would be to allocate a dummy pthread per-thread +// variable using pthread_key_create. Unlike the pthread keys we already use +// on OS X, this dummy key would never be read by Go code. It would exist +// only so that we could register at thread-exit-time destructor. +// That destructor would put the m back onto the extra list. +// This is purely a performance optimization. The current version, +// in which dropm happens on each cgo call, is still correct too. +// We may have to keep the current version on systems with cgo +// but without pthreads, like Windows. func dropm() { // Clear m and g, and return m to the extra list. // After the call to setg we can only call nosplit functions @@ -2135,39 +2082,6 @@ func dropm() { msigrestore(sigmask) } -// bindm store the g0 of the current m into a thread-specific value. -// -// We allocate a pthread per-thread variable using pthread_key_create, -// to register a thread-exit-time destructor. -// We are here setting the thread-specific value of the pthread key, to enable the destructor. -// So that the pthread_key_destructor would dropm while the C thread is exiting. -// -// And the saved g will be used in pthread_key_destructor, -// since the g stored in the TLS by Go might be cleared in some platforms, -// before the destructor invoked, so, we restore g by the stored g, before dropm. -// -// We store g0 instead of m, to make the assembly code simpler, -// since we need to restore g0 in runtime.cgocallback. -// -// On systems without pthreads, like Windows, bindm shouldn't be used. -// -// NOTE: this always runs without a P, so, nowritebarrierrec required. -// -//go:nosplit -//go:nowritebarrierrec -func cgoBindM() { - if GOOS == "windows" || GOOS == "plan9" { - fatal("bindm in unexpected GOOS") - } - g := getg() - if g.m.g0 != g { - fatal("the current g is not g0") - } - if _cgo_bindm != nil { - asmcgocall(_cgo_bindm, unsafe.Pointer(g)) - } -} - // A helper function for EnsureDropM. func getm() uintptr { return uintptr(unsafe.Pointer(getg().m)) |
