summaryrefslogtreecommitdiffstats
path: root/src/runtime/sys_darwin_arm64.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/sys_darwin_arm64.go')
-rw-r--r--src/runtime/sys_darwin_arm64.go65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/runtime/sys_darwin_arm64.go b/src/runtime/sys_darwin_arm64.go
new file mode 100644
index 0000000..6170f4f
--- /dev/null
+++ b/src/runtime/sys_darwin_arm64.go
@@ -0,0 +1,65 @@
+// 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.
+
+package runtime
+
+import (
+ "internal/abi"
+ "internal/goarch"
+ "unsafe"
+)
+
+// libc function wrappers. Must run on system stack.
+
+//go:nosplit
+//go:cgo_unsafe_args
+func g0_pthread_key_create(k *pthreadkey, destructor uintptr) int32 {
+ ret := asmcgocall(unsafe.Pointer(abi.FuncPCABI0(pthread_key_create_trampoline)), unsafe.Pointer(&k))
+ KeepAlive(k)
+ return ret
+}
+func pthread_key_create_trampoline()
+
+//go:nosplit
+//go:cgo_unsafe_args
+func g0_pthread_setspecific(k pthreadkey, value uintptr) int32 {
+ return asmcgocall(unsafe.Pointer(abi.FuncPCABI0(pthread_setspecific_trampoline)), unsafe.Pointer(&k))
+}
+func pthread_setspecific_trampoline()
+
+//go:cgo_import_dynamic libc_pthread_key_create pthread_key_create "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_pthread_setspecific pthread_setspecific "/usr/lib/libSystem.B.dylib"
+
+// tlsinit allocates a thread-local storage slot for g.
+//
+// It finds the first available slot using pthread_key_create and uses
+// it as the offset value for runtime.tlsg.
+//
+// This runs at startup on g0 stack, but before g is set, so it must
+// not split stack (transitively). g is expected to be nil, so things
+// (e.g. asmcgocall) will skip saving or reading g.
+//
+//go:nosplit
+func tlsinit(tlsg *uintptr, tlsbase *[_PTHREAD_KEYS_MAX]uintptr) {
+ var k pthreadkey
+ err := g0_pthread_key_create(&k, 0)
+ if err != 0 {
+ abort()
+ }
+
+ const magic = 0xc476c475c47957
+ err = g0_pthread_setspecific(k, magic)
+ if err != 0 {
+ abort()
+ }
+
+ for i, x := range tlsbase {
+ if x == magic {
+ *tlsg = uintptr(i * goarch.PtrSize)
+ g0_pthread_setspecific(k, 0)
+ return
+ }
+ }
+ abort()
+}