Skip to content

Commit a3b0144

Browse files
committed
syscall: implement syscalls on Darwin using libSystem
There are still some references to the bare Syscall functions in the stdlib. I will root those out in a following CL. (This CL is big enough as it is.) Most are in vendor directories: cmd/vendor/golang.org/x/sys/unix/ vendor/golang_org/x/net/route/syscall.go syscall/bpf_bsd.go syscall/exec_unix.go syscall/flock.go Update #17490 Change-Id: I69ab707811530c26b652b291cadee92f5bf5c1a4 Reviewed-on: https://go-review.googlesource.com/c/141639 Run-TryBot: Keith Randall <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Elias Naur <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 0fcd405 commit a3b0144

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+4996
-689
lines changed

src/cmd/internal/obj/x86/asm6.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -4704,7 +4704,9 @@ func (ab *AsmBuf) doasm(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog) {
47044704
r = obj.Addrel(cursym)
47054705
r.Off = int32(p.Pc + int64(ab.Len()))
47064706
r.Sym = p.To.Sym
4707-
r.Type = objabi.R_PCREL
4707+
// Note: R_CALL instead of R_PCREL. R_CALL is more permissive in that
4708+
// it can point to a trampoline instead of the destination itself.
4709+
r.Type = objabi.R_CALL
47084710
r.Siz = 4
47094711
ab.PutInt32(0)
47104712
break

src/internal/poll/fd_fsync_darwin.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
package poll
66

7-
import "syscall"
7+
import (
8+
"syscall"
9+
_ "unsafe" // for go:linkname
10+
)
811

912
// Fsync invokes SYS_FCNTL with SYS_FULLFSYNC because
1013
// on OS X, SYS_FSYNC doesn't fully flush contents to disk.
@@ -15,9 +18,10 @@ func (fd *FD) Fsync() error {
1518
}
1619
defer fd.decref()
1720

18-
_, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd.Sysfd), syscall.F_FULLFSYNC, 0)
19-
if e1 != 0 {
20-
return e1
21-
}
22-
return nil
21+
_, e1 := fcntl(fd.Sysfd, syscall.F_FULLFSYNC, 0)
22+
return e1
2323
}
24+
25+
// Implemented in syscall/syscall_darwin.go.
26+
//go:linkname fcntl syscall.fcntl
27+
func fcntl(fd int, cmd int, arg int) (int, error)

src/internal/poll/fd_fsync_posix.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build aix dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
5+
// +build aix dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
66

77
package poll
88

@@ -16,3 +16,11 @@ func (fd *FD) Fsync() error {
1616
defer fd.decref()
1717
return syscall.Fsync(fd.Sysfd)
1818
}
19+
20+
func fcntl(fd int, cmd int, arg int) (int, error) {
21+
r, _, e := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
22+
if e != 0 {
23+
return int(r), syscall.Errno(e)
24+
}
25+
return int(r), nil
26+
}

src/internal/poll/fd_fsync_windows.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2018 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package poll
6+
7+
import "syscall"
8+
9+
// Fsync wraps syscall.Fsync.
10+
func (fd *FD) Fsync() error {
11+
if err := fd.incref(); err != nil {
12+
return err
13+
}
14+
defer fd.decref()
15+
return syscall.Fsync(fd.Sysfd)
16+
}

src/internal/poll/fd_unix.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -452,10 +452,11 @@ var tryDupCloexec = int32(1)
452452
// DupCloseOnExec dups fd and marks it close-on-exec.
453453
func DupCloseOnExec(fd int) (int, string, error) {
454454
if atomic.LoadInt32(&tryDupCloexec) == 1 {
455-
r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0)
456-
switch e1 {
457-
case 0:
458-
return int(r0), "", nil
455+
r0, e1 := fcntl(fd, syscall.F_DUPFD_CLOEXEC, 0)
456+
if e1 == nil {
457+
return r0, "", nil
458+
}
459+
switch e1.(syscall.Errno) {
459460
case syscall.EINVAL, syscall.ENOSYS:
460461
// Old kernel, or js/wasm (which returns
461462
// ENOSYS). Fall back to the portable way from

src/internal/poll/fd_writev_darwin.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2018 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build darwin
6+
7+
package poll
8+
9+
import (
10+
"syscall"
11+
_ "unsafe" // for go:linkname
12+
)
13+
14+
// Implemented in syscall/syscall_darwin.go.
15+
//go:linkname writev syscall.writev
16+
func writev(fd int, iovecs []syscall.Iovec) (uintptr, error)

src/internal/poll/fd_writev_unix.go

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2018 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build dragonfly freebsd linux netbsd openbsd
6+
7+
package poll
8+
9+
import (
10+
"syscall"
11+
"unsafe"
12+
)
13+
14+
func writev(fd int, iovecs []syscall.Iovec) (uintptr, error) {
15+
r, _, e := syscall.Syscall(syscall.SYS_WRITEV, uintptr(fd), uintptr(unsafe.Pointer(&iovecs[0])), uintptr(len(iovecs)))
16+
if e != 0 {
17+
return r, syscall.Errno(e)
18+
}
19+
return r, nil
20+
}

src/internal/poll/writev.go

+7-12
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ package poll
99
import (
1010
"io"
1111
"syscall"
12-
"unsafe"
1312
)
1413

1514
// Writev wraps the writev system call.
@@ -54,24 +53,20 @@ func (fd *FD) Writev(v *[][]byte) (int64, error) {
5453
}
5554
fd.iovecs = &iovecs // cache
5655

57-
wrote, _, e0 := syscall.Syscall(syscall.SYS_WRITEV,
58-
uintptr(fd.Sysfd),
59-
uintptr(unsafe.Pointer(&iovecs[0])),
60-
uintptr(len(iovecs)))
56+
var wrote uintptr
57+
wrote, err = writev(fd.Sysfd, iovecs)
6158
if wrote == ^uintptr(0) {
6259
wrote = 0
6360
}
6461
TestHookDidWritev(int(wrote))
6562
n += int64(wrote)
6663
consume(v, int64(wrote))
67-
if e0 == syscall.EAGAIN {
68-
if err = fd.pd.waitWrite(fd.isFile); err == nil {
69-
continue
70-
}
71-
} else if e0 != 0 {
72-
err = syscall.Errno(e0)
73-
}
7464
if err != nil {
65+
if err.(syscall.Errno) == syscall.EAGAIN {
66+
if err = fd.pd.waitWrite(fd.isFile); err == nil {
67+
continue
68+
}
69+
}
7570
break
7671
}
7772
if n == 0 {

src/internal/syscall/unix/empty.s

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Copyright 2018 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// This exists solely so we can linkname in symbols from syscall.

src/internal/syscall/unix/nonblocking.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
5+
// +build aix dragonfly freebsd linux netbsd openbsd solaris
66

77
package unix
88

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2018 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build darwin
6+
7+
package unix
8+
9+
import (
10+
"syscall"
11+
_ "unsafe" // for go:linkname
12+
)
13+
14+
func IsNonblock(fd int) (nonblocking bool, err error) {
15+
flag, e1 := fcntl(fd, syscall.F_GETFL, 0)
16+
if e1 != nil {
17+
return false, e1
18+
}
19+
return flag&syscall.O_NONBLOCK != 0, nil
20+
}
21+
22+
// Implemented in syscall/syscall_darwin.go.
23+
//go:linkname fcntl syscall.fcntl
24+
func fcntl(fd int, cmd int, arg int) (int, error)

src/runtime/sys_darwin.go

+55
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,61 @@ func libcCall(fn, arg unsafe.Pointer) int32 {
5050
return res
5151
}
5252

53+
// The X versions of syscall expect the libc call to return a 64-bit result.
54+
// Otherwise (the non-X version) expects a 32-bit result.
55+
// This distinction is required because an error is indicated by returning -1,
56+
// and we need to know whether to check 32 or 64 bits of the result.
57+
// (Some libc functions that return 32 bits put junk in the upper 32 bits of AX.)
58+
59+
//go:linkname syscall_syscall syscall.syscall
60+
//go:nosplit
61+
//go:cgo_unsafe_args
62+
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
63+
entersyscallblock()
64+
libcCall(unsafe.Pointer(funcPC(syscall)), unsafe.Pointer(&fn))
65+
exitsyscall()
66+
return
67+
}
68+
func syscall()
69+
70+
//go:linkname syscall_syscall6 syscall.syscall6
71+
//go:nosplit
72+
//go:cgo_unsafe_args
73+
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
74+
entersyscallblock()
75+
libcCall(unsafe.Pointer(funcPC(syscall6)), unsafe.Pointer(&fn))
76+
exitsyscall()
77+
return
78+
}
79+
func syscall6()
80+
81+
//go:linkname syscall_syscall6X syscall.syscall6X
82+
//go:nosplit
83+
//go:cgo_unsafe_args
84+
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
85+
entersyscallblock()
86+
libcCall(unsafe.Pointer(funcPC(syscall6X)), unsafe.Pointer(&fn))
87+
exitsyscall()
88+
return
89+
}
90+
func syscall6X()
91+
92+
//go:linkname syscall_rawSyscall syscall.rawSyscall
93+
//go:nosplit
94+
//go:cgo_unsafe_args
95+
func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
96+
libcCall(unsafe.Pointer(funcPC(syscall)), unsafe.Pointer(&fn))
97+
return
98+
}
99+
100+
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
101+
//go:nosplit
102+
//go:cgo_unsafe_args
103+
func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
104+
libcCall(unsafe.Pointer(funcPC(syscall6)), unsafe.Pointer(&fn))
105+
return
106+
}
107+
53108
// The *_trampoline functions convert from the Go calling convention to the C calling convention
54109
// and then call the underlying libc function. They are defined in sys_darwin_$ARCH.s.
55110

src/runtime/sys_darwin_32.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2018 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build darwin
6+
// +build 386 arm
7+
8+
package runtime
9+
10+
import "unsafe"
11+
12+
//go:linkname syscall_syscall9 syscall.syscall9
13+
//go:nosplit
14+
//go:cgo_unsafe_args
15+
func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
16+
entersyscallblock()
17+
libcCall(unsafe.Pointer(funcPC(syscall9)), unsafe.Pointer(&fn))
18+
exitsyscall()
19+
return
20+
}
21+
func syscall9()

0 commit comments

Comments
 (0)