aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/os_darwin.go
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2018-04-23 07:30:32 -0700
committerKeith Randall <khr@golang.org>2018-04-30 02:41:03 +0000
commitb7f1777a709e575cb6aa03c25a976d06d36cb6a6 (patch)
tree4620a0bfb1fdc25cca0d09f148c6b964eb7b0643 /src/runtime/os_darwin.go
parent743fd9171fe82045a2f25e6910d919322010c59a (diff)
downloadgo-b7f1777a709e575cb6aa03c25a976d06d36cb6a6.tar.gz
go-b7f1777a709e575cb6aa03c25a976d06d36cb6a6.zip
runtime,cmd/ld: on darwin, create theads using libc
Replace thread creation with calls to the pthread library in libc. Update #17490 Change-Id: I1e19965c45255deb849b059231252fc6a7861d6c Reviewed-on: https://go-review.googlesource.com/108679 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/runtime/os_darwin.go')
-rw-r--r--src/runtime/os_darwin.go92
1 files changed, 63 insertions, 29 deletions
diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go
index 63351f504d..9d3139b2ad 100644
--- a/src/runtime/os_darwin.go
+++ b/src/runtime/os_darwin.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build 386 amd64
+
package runtime
import "unsafe"
@@ -13,9 +15,6 @@ type mOS struct {
var darwinVersion int
-func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32
-func bsdthread_register() int32
-
//go:noescape
func mach_msg_trap(h unsafe.Pointer, op int32, send_size, rcv_size, rcv_name, timeout, notify uint32) int32
@@ -48,7 +47,7 @@ func semacreate(mp *m) {
// BSD interface for threading.
func osinit() {
- // bsdthread_register delayed until end of goenvs so that we
+ // pthread_create delayed until end of goenvs so that we
// can look at the environment first.
ncpu = getncpu()
@@ -117,43 +116,56 @@ func getRandomData(r []byte) {
func goenvs() {
goenvs_unix()
-
- // Register our thread-creation callback (see sys_darwin_{amd64,386}.s)
- // but only if we're not using cgo. If we are using cgo we need
- // to let the C pthread library install its own thread-creation callback.
- if !iscgo {
- if bsdthread_register() != 0 {
- if gogetenv("DYLD_INSERT_LIBRARIES") != "" {
- throw("runtime: bsdthread_register error (unset DYLD_INSERT_LIBRARIES)")
- }
- throw("runtime: bsdthread_register error")
- }
- }
}
// May run with m.p==nil, so write barriers are not allowed.
-//go:nowritebarrier
-func newosproc(mp *m, stk unsafe.Pointer) {
+//go:nowritebarrierrec
+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")
}
+ // Initialize an attribute object.
+ var attr pthreadattr
+ var err int32
+ err = pthread_attr_init(&attr)
+ if err != 0 {
+ write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
+ exit(1)
+ }
+
+ // Set the stack we want to use.
+ if pthread_attr_setstack(&attr, unsafe.Pointer(mp.g0.stack.lo), mp.g0.stack.hi-mp.g0.stack.lo) != 0 {
+ write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
+ exit(1)
+ }
+
+ // 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)
- errno := bsdthread_create(stk, unsafe.Pointer(mp), funcPC(mstart))
+ _, err = pthread_create(&attr, funcPC(mstart_stub), unsafe.Pointer(mp))
sigprocmask(_SIG_SETMASK, &oset, nil)
-
- if errno < 0 {
- print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", -errno, ")\n")
- throw("runtime.newosproc")
+ if err != 0 {
+ write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
+ exit(1)
}
}
+// glue code to call mstart from pthread_create.
+func mstart_stub()
+
// newosproc0 is a version of newosproc that can be called before the runtime
// is initialized.
//
-// As Go uses bsdthread_register when running without cgo, this function is
-// not safe to use after initialization as it does not pass an M as fnarg.
+// This function is not safe to use after initialization as it does not pass an M as fnarg.
//
//go:nosplit
func newosproc0(stacksize uintptr, fn uintptr) {
@@ -162,14 +174,36 @@ func newosproc0(stacksize uintptr, fn uintptr) {
write(2, unsafe.Pointer(&failallocatestack[0]), int32(len(failallocatestack)))
exit(1)
}
- stk := unsafe.Pointer(uintptr(stack) + stacksize)
+ // Initialize an attribute object.
+ var attr pthreadattr
+ var err int32
+ err = pthread_attr_init_trampoline(&attr)
+ if err != 0 {
+ write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
+ exit(1)
+ }
+
+ // Set the stack we want to use.
+ if pthread_attr_setstack_trampoline(&attr, stack, stacksize) != 0 {
+ write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
+ exit(1)
+ }
+
+ // Tell the pthread library we won't join with this thread.
+ if pthread_attr_setdetachstate_trampoline(&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)
- errno := bsdthread_create(stk, nil, fn)
+ var t pthread
+ err = pthread_create_trampoline(&t, &attr, fn, nil)
sigprocmask(_SIG_SETMASK, &oset, nil)
-
- if errno < 0 {
+ if err != 0 {
write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
exit(1)
}