aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/proc.go
diff options
context:
space:
mode:
authorChressie Himpel <chressie@google.com>2023-05-05 14:17:38 +0000
committerChressie Himpel <chressie@google.com>2023-05-05 14:37:29 +0000
commit72c33a5ef0eea8663328375d9d339ed150310ebb (patch)
treea4272daf751239fcb9b2f1b8e1730800629f738c /src/runtime/proc.go
parentf379e78951a405e7e99a60fb231eeedbf976c108 (diff)
downloadgo-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.go118
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))