platform: adds notes about darwin and CGO (#1212)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
20
RATIONALE.md
20
RATIONALE.md
@@ -25,6 +25,26 @@ At some point, we may allow extensions to supply their own platform-specific
|
||||
hooks. Until then, one end user impact/tradeoff is some glitches trying
|
||||
untested platforms (with the Compiler runtime).
|
||||
|
||||
### Why do we use CGO to implement system calls on darwin?
|
||||
|
||||
wazero is dependency and CGO free by design. In some cases, we have code that
|
||||
can optionally use CGO, but retain a fallback for when that's disabled. The only
|
||||
operating system (`GOOS`) we use CGO by default in is `darwin`.
|
||||
|
||||
Unlike other operating systems, regardless of `CGO_ENABLED`, Go always uses
|
||||
"CGO" mechanisms in the runtime layer of `darwin`. This is explained in
|
||||
[Statically linked binaries on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html#//apple_ref/doc/uid/DTS10001666):
|
||||
|
||||
> Apple does not support statically linked binaries on Mac OS X. A statically
|
||||
> linked binary assumes binary compatibility at the kernel system call
|
||||
> interface, and we do not make any guarantees on that front. Rather, we strive
|
||||
> to ensure binary compatibility in each dynamically linked system library and
|
||||
> framework.
|
||||
|
||||
This plays to our advantage for system calls that aren't yet exposed in the Go
|
||||
standard library, notably `futimens` for nanosecond-precision timestamp
|
||||
manipulation.
|
||||
|
||||
### Why not x/sys
|
||||
|
||||
Going beyond Go's SDK limitations can be accomplished with their [x/sys library](https://pkg.go.dev/golang.org/x/sys/unix).
|
||||
|
||||
@@ -2,6 +2,7 @@ package platform
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -10,3 +11,19 @@ func Benchmark_IsTerminal(b *testing.B) {
|
||||
IsTerminal(os.Stdout.Fd())
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_UtimesNano(b *testing.B) {
|
||||
tmpDir := b.TempDir()
|
||||
f, err := os.Create(path.Join(tmpDir, "file"))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err := UtimesNanoFile(f, 1, 1); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,16 +19,21 @@ func futimens(fd uintptr, atimeNsec, mtimeNsec int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// libc_futimens_trampoline_addr is the address of the libc_futimens_trampoline symbol, defined in utimes_darwin.s
|
||||
// we use this value to invoke the syscall through syscall_syscall6 imported below
|
||||
// libc_futimens_trampoline_addr is the address of the
|
||||
// `libc_futimens_trampoline` symbol, defined in `utimes_darwin.s`.
|
||||
//
|
||||
// We use this to invoke the syscall through syscall_syscall6 imported below.
|
||||
var libc_futimens_trampoline_addr uintptr
|
||||
|
||||
// Imports the futimens symbol from libc as libc_futimens
|
||||
// Imports the futimens symbol from libc as `libc_futimens`.
|
||||
//
|
||||
// Note: CGO mechanisms are used in darwin regardless of the CGO_ENABLED value
|
||||
// or the "cgo" build flag. See /RATIONALE.md for why.
|
||||
//go:cgo_import_dynamic libc_futimens futimens "/usr/lib/libSystem.B.dylib"
|
||||
|
||||
// syscall_syscall6 is a private symbol that we link below. We need to use this instead of syscall.Syscall6
|
||||
// because the public syscall.Syscall6 won't work when fn is an address
|
||||
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
// Import syscall.syscall6 as syscall_syscall6.
|
||||
// syscall_syscall6 is a private symbol that we link below. We need to use this
|
||||
// instead of syscall.Syscall6 because the public syscall.Syscall6 won't work
|
||||
// when fn is an address.
|
||||
//
|
||||
//go:linkname syscall_syscall6 syscall.syscall6
|
||||
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
@@ -73,8 +73,15 @@ func TestUtimesNano(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUtimesNanoFile(t *testing.T) {
|
||||
if !IsGo120 {
|
||||
t.Skip("TODO: implement futimens on darwin, freebsd, linux w/o CGO")
|
||||
switch runtime.GOOS {
|
||||
case "linux", "darwin": // supported
|
||||
case "freebsd": // TODO: support freebsd w/o CGO
|
||||
case "windows":
|
||||
if !IsGo120 {
|
||||
t.Skip("windows only works after Go 1.20") // TODO: possibly 1.19 ;)
|
||||
}
|
||||
default: // expect ENOSYS and callers need to fall back to UtimesNano
|
||||
t.Skip("unsupported GOOS", runtime.GOOS)
|
||||
}
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
Reference in New Issue
Block a user