diff options
author | Keith Randall <khr@golang.org> | 2018-04-23 07:30:32 -0700 |
---|---|---|
committer | Keith Randall <khr@golang.org> | 2018-04-30 02:41:03 +0000 |
commit | b7f1777a709e575cb6aa03c25a976d06d36cb6a6 (patch) | |
tree | 4620a0bfb1fdc25cca0d09f148c6b964eb7b0643 /src/runtime/os_darwin.go | |
parent | 743fd9171fe82045a2f25e6910d919322010c59a (diff) | |
download | go-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.go | 92 |
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) } |