Skip to content

Commit 4a0115c

Browse files
committed
runtime,syscall: implement and use syscalln on darwin
All darwin syscall implementations can be consolidated into a single syscalln function, as already happens on Windows. This reduces duplication and allows moving some logic from runtime to syscall. Updates #699135 Cq-Include-Trybots: luci.golang.try:gotip-darwin-arm64-longtest,gotip-darwin-amd64-longtest,x_sys-gotip-darwin-arm64-longtest,x_sys-gotip-darwin-amd64-longtest Change-Id: If5de80442b1d4a1123258401a3ae21695e7c8f6b Reviewed-on: https://go-review.googlesource.com/c/go/+/699177 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Michael Pratt <mpratt@google.com>
1 parent 261c561 commit 4a0115c

File tree

8 files changed

+304
-381
lines changed

8 files changed

+304
-381
lines changed

src/internal/trace/trace_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,9 @@ func TestTraceStacks(t *testing.T) {
448448
{"main.main.func11", 0},
449449
}},
450450
}...)
451+
if runtime.GOOS == "darwin" {
452+
want[len(want)-1].frames = append([]frame{{"syscall.syscall", 0}}, want[len(want)-1].frames...)
453+
}
451454
}
452455
stackMatches := func(stk trace.Stack, frames []frame) bool {
453456
for i, f := range slices.Collect(stk.Frames()) {

src/runtime/os_darwin.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ type mOS struct {
1515
mutex pthreadmutex
1616
cond pthreadcond
1717
count int
18+
19+
// address of errno variable for this thread.
20+
// This is an optimization to avoid calling libc_error
21+
// on every syscall_rawsyscalln.
22+
errnoAddr *int32
1823
}
1924

2025
func unimplemented(name string) {
@@ -330,6 +335,7 @@ func minit() {
330335
}
331336
minitSignalMask()
332337
getg().m.procid = uint64(pthread_self())
338+
libc_error_addr(&getg().m.errnoAddr)
333339
}
334340

335341
// Called from dropm to undo the effect of an minit.

src/runtime/sys_darwin.go

Lines changed: 37 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -10,186 +10,65 @@ import (
1010
"unsafe"
1111
)
1212

13-
//go:nosplit
14-
func libcError() uintptr {
15-
errPtr, _ := syscall(abi.FuncPCABI0(libc_error_trampoline), 0, 0, 0)
16-
return errPtr
17-
}
1813
func libc_error_trampoline()
1914

20-
// The X versions of syscall expect the libc call to return a 64-bit result.
21-
// Otherwise (the non-X version) expects a 32-bit result.
22-
// This distinction is required because an error is indicated by returning -1,
23-
// and we need to know whether to check 32 or 64 bits of the result.
24-
// (Some libc functions that return 32 bits put junk in the upper 32 bits of AX.)
25-
26-
//go:nosplit
27-
func syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr) {
28-
args := struct{ fn, a1, a2, a3, r1, r2 uintptr }{fn, a1, a2, a3, r1, r2}
29-
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall_trampoline)), unsafe.Pointer(&args))
30-
return args.r1, args.r2
31-
}
32-
func syscall_trampoline()
33-
34-
// golang.org/x/sys linknames syscall_syscall
35-
// (in addition to standard package syscall).
36-
// Do not remove or change the type signature.
37-
//
38-
//go:linkname syscall_syscall syscall.syscall
39-
//go:nosplit
40-
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
41-
entersyscall()
42-
r1, r2, err = syscall_rawSyscall(fn, a1, a2, a3)
43-
exitsyscall()
44-
return r1, r2, err
45-
}
46-
47-
//go:linkname syscall_syscallX syscall.syscallX
48-
//go:nosplit
49-
func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
50-
entersyscall()
51-
r1, r2, err = syscall_rawSyscallX(fn, a1, a2, a3)
52-
exitsyscall()
53-
return r1, r2, err
54-
}
55-
56-
//go:nosplit
57-
func syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr) {
58-
args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2 uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2}
59-
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6_trampoline)), unsafe.Pointer(&args))
60-
return args.r1, args.r2
61-
}
62-
func syscall6_trampoline()
63-
64-
// golang.org/x/sys linknames syscall.syscall6
65-
// (in addition to standard package syscall).
66-
// Do not remove or change the type signature.
67-
//
68-
// syscall.syscall6 is meant for package syscall (and x/sys),
69-
// but widely used packages access it using linkname.
70-
// Notable members of the hall of shame include:
71-
// - github.com/tetratelabs/wazero
72-
//
73-
// See go.dev/issue/67401.
15+
// libc_error_addr puts the libc error
16+
// address into addr.
7417
//
75-
//go:linkname syscall_syscall6 syscall.syscall6
7618
//go:nosplit
77-
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
78-
entersyscall()
79-
r1, r2, err = syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6)
80-
exitsyscall()
81-
return r1, r2, err
82-
}
83-
84-
//go:linkname syscall_syscall6X syscall.syscall6X
85-
//go:nosplit
86-
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
87-
entersyscall()
88-
r1, r2, err = syscall_rawSyscall6X(fn, a1, a2, a3, a4, a5, a6)
89-
exitsyscall()
90-
return r1, r2, err
19+
//go:cgo_unsafe_args
20+
func libc_error_addr(addr **int32) {
21+
libcCall(unsafe.Pointer(abi.FuncPCABI0(libc_error_trampoline)), unsafe.Pointer(&addr))
9122
}
9223

93-
//go:nosplit
94-
func syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr) {
95-
args := struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2 uintptr }{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2}
96-
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall9_trampoline)), unsafe.Pointer(&args))
97-
return args.r1, args.r2
24+
// libcCallInfo is a structure used to pass parameters to the system call.
25+
type libcCallInfo struct {
26+
fn uintptr
27+
n uintptr // number of parameters
28+
args uintptr // parameters
29+
r1, r2 uintptr // return values
9830
}
99-
func syscall9_trampoline()
10031

101-
// golang.org/x/sys linknames syscall.syscall9
102-
// (in addition to standard package syscall).
103-
// Do not remove or change the type signature.
32+
// syscall_syscalln is a wrapper around the libc call with variable arguments.
10433
//
105-
//go:linkname syscall_syscall9 syscall.syscall9
34+
//go:linkname syscall_syscalln syscall.syscalln
10635
//go:nosplit
107-
func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
36+
//go:uintptrkeepalive
37+
func syscall_syscalln(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
10838
entersyscall()
109-
r1, r2, err = syscall_rawSyscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
39+
r1, r2, err = syscall_rawsyscalln(fn, args...)
11040
exitsyscall()
11141
return r1, r2, err
11242
}
11343

114-
// golang.org/x/sys linknames syscall.syscallPtr
115-
// (in addition to standard package syscall).
116-
// Do not remove or change the type signature.
44+
// syscall_rawsyscalln is a wrapper around the libc call with variable arguments.
45+
// The scheduler is not notified about the system call.
46+
// The syscall is executed on the current goroutine thread rather than on a
47+
// dedicated syscall thread.
11748
//
118-
//go:linkname syscall_syscallPtr syscall.syscallPtr
49+
//go:linkname syscall_rawsyscalln syscall.rawsyscalln
11950
//go:nosplit
120-
func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
121-
entersyscall()
122-
r1, r2, err = syscall_rawSyscallPtr(fn, a1, a2, a3)
123-
exitsyscall()
124-
return r1, r2, err
125-
}
126-
127-
// golang.org/x/sys linknames syscall_rawSyscall
128-
// (in addition to standard package syscall).
129-
// Do not remove or change the type signature.
130-
//
131-
//go:linkname syscall_rawSyscall syscall.rawSyscall
132-
//go:nosplit
133-
func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
134-
r1, r2 = syscall(fn, a1, a2, a3)
135-
// Check if r1 low 32 bits is -1, indicating an error.
136-
if int32(r1) == -1 {
137-
err = libcError()
51+
//go:uintptrkeepalive
52+
func syscall_rawsyscalln(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
53+
c := &libcCallInfo{
54+
fn: fn,
55+
n: uintptr(len(args)),
13856
}
139-
return r1, r2, err
140-
}
141-
142-
//go:nosplit
143-
func syscall_rawSyscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
144-
r1, r2 = syscall(fn, a1, a2, a3)
145-
if r1 == ^uintptr(0) {
146-
err = libcError()
57+
if c.n != 0 {
58+
c.args = uintptr(noescape(unsafe.Pointer(&args[0])))
14759
}
148-
return r1, r2, err
149-
}
150-
151-
//go:nosplit
152-
func syscall_rawSyscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
153-
r1, r2 = syscall(fn, a1, a2, a3)
154-
if r1 == 0 {
155-
err = libcError()
156-
}
157-
return r1, r2, err
158-
}
159-
160-
// golang.org/x/sys linknames syscall_rawSyscall6
161-
// (in addition to standard package syscall).
162-
// Do not remove or change the type signature.
163-
//
164-
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
165-
//go:nosplit
166-
func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
167-
r1, r2 = syscall6(fn, a1, a2, a3, a4, a5, a6)
168-
// Check if r1 low 32 bits is -1, indicating an error.
169-
if int32(r1) == -1 {
170-
err = libcError()
171-
}
172-
return r1, r2, err
173-
}
174-
175-
//go:nosplit
176-
func syscall_rawSyscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
177-
r1, r2 = syscall6(fn, a1, a2, a3, a4, a5, a6)
178-
if r1 == ^uintptr(0) {
179-
err = libcError()
60+
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallN_trampoline)), unsafe.Pointer(c))
61+
if gp := getg(); gp != nil && gp.m != nil && gp.m.errnoAddr != nil {
62+
err = uintptr(*gp.m.errnoAddr)
63+
} else {
64+
var errnoAddr *int32
65+
libc_error_addr(&errnoAddr)
66+
err = uintptr(*errnoAddr)
18067
}
181-
return r1, r2, err
68+
return c.r1, c.r2, err
18269
}
18370

184-
//go:nosplit
185-
func syscall_rawSyscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
186-
r1, r2 = syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
187-
// Check if r1 low 32 bits is -1, indicating an error.
188-
if int32(r1) == -1 {
189-
err = libcError()
190-
}
191-
return r1, r2, err
192-
}
71+
func syscallN_trampoline()
19372

19473
// crypto_x509_syscall is used in crypto/x509/internal/macos to call into Security.framework and CF.
19574

0 commit comments

Comments
 (0)