-
Notifications
You must be signed in to change notification settings - Fork 17.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cmd/link,runtime: switch openbsd/amd64 to pthreads
This switches openbsd/amd64 to thread creation via pthreads, rather than doing direct system calls. Update #36435 Change-Id: I1105d5c392aa3e4c445d99c8cb80b927712e3529 Reviewed-on: https://go-review.googlesource.com/c/go/+/250180 Trust: Joel Sing <[email protected]> Run-TryBot: Joel Sing <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
- Loading branch information
Showing
14 changed files
with
418 additions
and
162 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Copyright 2020 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. | ||
|
||
// +build openbsd,amd64 | ||
|
||
package runtime | ||
|
||
import ( | ||
"unsafe" | ||
) | ||
|
||
var failThreadCreate = []byte("runtime: failed to create new OS thread\n") | ||
|
||
// mstart_stub provides glue code to call mstart from pthread_create. | ||
func mstart_stub() | ||
|
||
// May run with m.p==nil, so write barriers are not allowed. | ||
//go:nowritebarrierrec | ||
func newosproc(mp *m) { | ||
if false { | ||
print("newosproc m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n") | ||
} | ||
|
||
// Initialize an attribute object. | ||
var attr pthreadattr | ||
if err := pthread_attr_init(&attr); err != 0 { | ||
write(2, unsafe.Pointer(&failThreadCreate[0]), int32(len(failThreadCreate))) | ||
exit(1) | ||
} | ||
|
||
// Find out OS stack size for our own stack guard. | ||
var stacksize uintptr | ||
if pthread_attr_getstacksize(&attr, &stacksize) != 0 { | ||
write(2, unsafe.Pointer(&failThreadCreate[0]), int32(len(failThreadCreate))) | ||
exit(1) | ||
} | ||
mp.g0.stack.hi = stacksize // for mstart | ||
|
||
// Tell the pthread library we won't join with this thread. | ||
if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 { | ||
write(2, unsafe.Pointer(&failThreadCreate[0]), int32(len(failThreadCreate))) | ||
exit(1) | ||
} | ||
|
||
// Finally, create the thread. It starts at mstart_stub, which does some low-level | ||
// setup and then calls mstart. | ||
var oset sigset | ||
sigprocmask(_SIG_SETMASK, &sigset_all, &oset) | ||
err := pthread_create(&attr, funcPC(mstart_stub), unsafe.Pointer(mp)) | ||
sigprocmask(_SIG_SETMASK, &oset, nil) | ||
if err != 0 { | ||
write(2, unsafe.Pointer(&failThreadCreate[0]), int32(len(failThreadCreate))) | ||
exit(1) | ||
} | ||
|
||
pthread_attr_destroy(&attr) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Copyright 2011 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. | ||
|
||
// +build openbsd,!amd64 | ||
|
||
package runtime | ||
|
||
import ( | ||
"runtime/internal/sys" | ||
"unsafe" | ||
) | ||
|
||
//go:noescape | ||
func tfork(param *tforkt, psize uintptr, mm *m, gg *g, fn uintptr) int32 | ||
|
||
// May run with m.p==nil, so write barriers are not allowed. | ||
//go:nowritebarrier | ||
func newosproc(mp *m) { | ||
stk := unsafe.Pointer(mp.g0.stack.hi) | ||
if false { | ||
print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n") | ||
} | ||
|
||
// Stack pointer must point inside stack area (as marked with MAP_STACK), | ||
// rather than at the top of it. | ||
param := tforkt{ | ||
tf_tcb: unsafe.Pointer(&mp.tls[0]), | ||
tf_tid: nil, // minit will record tid | ||
tf_stack: uintptr(stk) - sys.PtrSize, | ||
} | ||
|
||
var oset sigset | ||
sigprocmask(_SIG_SETMASK, &sigset_all, &oset) | ||
ret := tfork(¶m, unsafe.Sizeof(param), mp, mp.g0, funcPC(mstart)) | ||
sigprocmask(_SIG_SETMASK, &oset, nil) | ||
|
||
if ret < 0 { | ||
print("runtime: failed to create new OS thread (have ", mcount()-1, " already; errno=", -ret, ")\n") | ||
if ret == -_EAGAIN { | ||
println("runtime: may need to increase max user processes (ulimit -p)") | ||
} | ||
throw("runtime.newosproc") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// Copyright 2018 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. | ||
|
||
// +build darwin openbsd,amd64 | ||
|
||
package runtime | ||
|
||
import "unsafe" | ||
|
||
// Call fn with arg as its argument. Return what fn returns. | ||
// fn is the raw pc value of the entry point of the desired function. | ||
// Switches to the system stack, if not already there. | ||
// Preserves the calling point as the location where a profiler traceback will begin. | ||
//go:nosplit | ||
func libcCall(fn, arg unsafe.Pointer) int32 { | ||
// Leave caller's PC/SP/G around for traceback. | ||
gp := getg() | ||
var mp *m | ||
if gp != nil { | ||
mp = gp.m | ||
} | ||
if mp != nil && mp.libcallsp == 0 { | ||
mp.libcallg.set(gp) | ||
mp.libcallpc = getcallerpc() | ||
// sp must be the last, because once async cpu profiler finds | ||
// all three values to be non-zero, it will use them | ||
mp.libcallsp = getcallersp() | ||
} else { | ||
// Make sure we don't reset libcallsp. This makes | ||
// libcCall reentrant; We remember the g/pc/sp for the | ||
// first call on an M, until that libcCall instance | ||
// returns. Reentrance only matters for signals, as | ||
// libc never calls back into Go. The tricky case is | ||
// where we call libcX from an M and record g/pc/sp. | ||
// Before that call returns, a signal arrives on the | ||
// same M and the signal handling code calls another | ||
// libc function. We don't want that second libcCall | ||
// from within the handler to be recorded, and we | ||
// don't want that call's completion to zero | ||
// libcallsp. | ||
// We don't need to set libcall* while we're in a sighandler | ||
// (even if we're not currently in libc) because we block all | ||
// signals while we're handling a signal. That includes the | ||
// profile signal, which is the one that uses the libcall* info. | ||
mp = nil | ||
} | ||
res := asmcgocall(fn, arg) | ||
if mp != nil { | ||
mp.libcallsp = 0 | ||
} | ||
return res | ||
} |
Oops, something went wrong.