[runtime] Remove explicit dependency on syscall/zx
The runtime dependency on syscall/zx makes it difficult to use
syscall/zx without causing import loops. This is also the first step in
consolidating the VDSO "syscall" entrypoint duplication between runtime
and syscall/zx.
Change-Id: I8252bc426cf2be7df7cce72ed1e1fa1984e85ca4
diff --git a/src/runtime/mem_fuchsia.go b/src/runtime/mem_fuchsia.go
index eee26bc..bb91252 100644
--- a/src/runtime/mem_fuchsia.go
+++ b/src/runtime/mem_fuchsia.go
@@ -5,14 +5,42 @@
package runtime
import (
- "syscall/zx"
"unsafe"
)
+const (
+ permRead = 1 << 0
+ permWrite = 1 << 1
+
+ propName = 3
+)
+
+//go:linkname sys_vmar_unmap syscall/zx.Sys_vmar_unmap
+func sys_vmar_unmap(h uint32, addr unsafe.Pointer, l uint64) int32
+
+//go:linkname sys_vmo_create syscall/zx.Sys_vmo_create
+//go:noescape
+func sys_vmo_create(size uint64, options uint32, out *uint32) int32
+
+//go:linkname sys_object_set_property syscall/zx.Sys_object_set_property
+//go:noescape
+func sys_object_set_property(handle uint32, property uint32, value unsafe.Pointer, value_size uint) int32
+
+//go:linkname sys_vmar_map syscall/zx.Sys_vmar_map
+//go:noescape
+func sys_vmar_map(handle uint32, options uint32, vmar_offset uint64, vmo uint32, vmo_offset uint64, len uint64, mapped_addr *unsafe.Pointer) int32
+
+//go:linkname sys_handle_close syscall/zx.Sys_handle_close
+//go:noescape
+func sys_handle_close(handle uint32) int32
+
+//go:linkname sys_vmar_protect syscall/zx.Sys_vmar_protect
+func sys_vmar_protect(handle uint32, options uint32, addr unsafe.Pointer, len uint64) int32
+
//go:nosplit
func sysAlloc(n uintptr, sysStat *uint64) unsafe.Pointer {
var p unsafe.Pointer
- sysMmap(unsafe.Pointer(&p), n, zx.VMFlagPermRead|zx.VMFlagPermWrite)
+ sysMmap(unsafe.Pointer(&p), n, permRead|permWrite)
if uintptr(p) < 4096 {
println("runtime: sysMmap failed n=", n)
exit(2)
@@ -32,31 +60,31 @@
//go:nosplit
func sysFree(v unsafe.Pointer, n uintptr, sysStat *uint64) {
mSysStatDec(sysStat, n)
- if status := zx.Sys_vmar_unmap(zx.Handle(zx.VMARRoot), zx.Vaddr(v), uint64(n)); status != zx.ErrOk {
- println("runtime: zx.Sys_vmar_unmap failed: ", status.String())
+ if status := sys_vmar_unmap(fdioHandles.vmarRootSelf, v, uint64(n)); status != 0 {
+ println("runtime: sys_vmar_unmap failed: ", status)
}
}
-func sysMmap(ptr unsafe.Pointer, sz uintptr, flags zx.VMFlag) {
- var h zx.Handle
- if status := zx.Sys_vmo_create(uint64(sz), 0, &h); status != zx.ErrOk {
- println("runtime: zx.Sys_vmo_create failed: ", status.String())
+func sysMmap(ptr unsafe.Pointer, sz uintptr, flags uint32) {
+ var h uint32
+ if status := sys_vmo_create(uint64(sz), 0, &h); status != 0 {
+ println("runtime: sys_vmo_create failed: ", status)
exit(2)
}
prop := []byte("go-sys-mmap")
- if status := zx.Sys_object_set_property(h, zx.PropName, unsafe.Pointer(&prop[0]), uint(len(prop))); status != zx.ErrOk {
- println("runtime: zx.Sys_object_set_property failed: ", status.String())
+ if status := sys_object_set_property(h, propName, unsafe.Pointer(&prop[0]), uint(len(prop))); status != 0 {
+ println("runtime: sys_object_set_property failed: ", status)
exit(2)
}
- if status := zx.Sys_vmar_map(zx.Handle(zx.VMARRoot), flags, 0, h, 0, uint64(sz), (*zx.Vaddr)(ptr)); status != zx.ErrOk {
- println("runtime: zx.Sys_vmar_map failed: ", status.String())
+ if status := sys_vmar_map(fdioHandles.vmarRootSelf, flags, 0, h, 0, uint64(sz), (*unsafe.Pointer)(ptr)); status != 0 {
+ println("runtime: sys_vmar_map failed: ", status)
exit(2)
}
- if status := zx.Sys_handle_close(h); status != zx.ErrOk {
- println("runtime: zx.Sys_handle_close failed: ", status.String())
+ if status := sys_handle_close(h); status != 0 {
+ println("runtime: sys_handle_close failed: ", status)
exit(2)
}
}
@@ -74,8 +102,8 @@
func sysMap(v unsafe.Pointer, n uintptr, sysStat *uint64) {
mSysStatInc(sysStat, n)
- if status := zx.Sys_vmar_protect(zx.Handle(zx.VMARRoot), zx.VMFlagPermRead|zx.VMFlagPermWrite, zx.Vaddr(v), uint64(n)); status != zx.ErrOk {
- println("runtime: zx.Sys_vmar_protect failed: ", status.String())
+ if status := sys_vmar_protect(fdioHandles.vmarRootSelf, permRead|permWrite, v, uint64(n)); status != 0 {
+ println("runtime: sys_vmar_protect failed: ", status)
exit(2)
}
}
diff --git a/src/runtime/os_fuchsia.go b/src/runtime/os_fuchsia.go
index a640020..219fd53 100644
--- a/src/runtime/os_fuchsia.go
+++ b/src/runtime/os_fuchsia.go
@@ -6,14 +6,73 @@
import (
"runtime/internal/atomic"
- "syscall/zx"
"unsafe"
)
-//go:nosplit
-func cputicks() int64 {
- return int64(zx.Sys_ticks_get())
-}
+const nsecInf = int64(0x7FFFFFFFFFFFFFFF)
+
+func osyield()
+
+//go:linkname cputicks syscall/zx.Sys_ticks_get
+func cputicks() int64
+
+//go:linkname sys_cprng_draw syscall/zx.Sys_cprng_draw
+//go:noescape
+func sys_cprng_draw(buffer unsafe.Pointer, size uint)
+
+//go:linkname sys_system_get_num_cpus syscall/zx.Sys_system_get_num_cpus
+func sys_system_get_num_cpus() uint32
+
+//go:linkname sys_deadline_after syscall/zx.Sys_deadline_after
+func sys_deadline_after(ns int64) int64
+
+//go:linkname sys_futex_wait syscall/zx.Sys_futex_wait
+//go:noescape
+func sys_futex_wait(v *int32, cv int32, newOwner uint32, deadline int64) int32
+
+//go:linkname sys_futex_wake syscall/zx.Sys_futex_wake
+//go:noescape
+func sys_futex_wake(v *int32, count uint32) int32
+
+//go:linkname sys_thread_create syscall/zx.Sys_thread_create
+//go:noescape
+func sys_thread_create(p uint32, name *byte, nlen uint, opts int, out *uint32) int32
+
+//go:linkname sys_thread_start syscall/zx.Sys_thread_start
+//go:noescape
+func sys_thread_start(h uint32, pc unsafe.Pointer, stk unsafe.Pointer, mp uintptr, arg2 uintptr) int32
+
+//go:linkname sys_clock_get_monotonic syscall/zx.Sys_clock_get_monotonic
+func sys_clock_get_monotonic() int64
+
+//go:linkname sys_clock_get syscall/zx.Sys_clock_get
+//go:noescape
+func sys_clock_get(clock_id uint32, out *int64) int32
+
+//go:linkname sys_debuglog_create syscall/zx.Sys_debuglog_create
+//go:noescape
+func sys_debuglog_create(resource uint32, options uint32, out *uint32) int32
+
+//go:linkname sys_debuglog_write syscall/zx.Sys_debuglog_write
+func sys_debuglog_write(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint) int32
+
+//go:linkname sys_nanosleep syscall/zx.Sys_nanosleep
+func sys_nanosleep(deadline int64) int32
+
+//go:linkname sys_process_exit syscall/zx.Sys_process_exit
+func sys_process_exit(retcode int64)
+
+//go:linkname zx_set_stdio_handle syscall/zx.set_stdio_handle
+func zx_set_stdio_handle(n int, h uint32, t uint32)
+
+//go:linkname zx_set_proc_handle syscall/zx.set_proc_handle
+func zx_set_proc_handle(h uint32)
+
+//go:linkname zx_set_vmar_root syscall/zx.set_vmar_root
+func zx_set_vmar_root(h uint32)
+
+//go:linkname zx_set_namespace syscall/zx.set_namespace
+func zx_set_namespace(m map[string]uint32)
type mOS struct{}
@@ -21,26 +80,24 @@
//go:nosplit
func getRandomData(r []byte) {
- zx.RandRead(r)
+ if len(r) == 0 {
+ return
+ }
+ sys_cprng_draw(unsafe.Pointer(&r[0]), uint(len(r)))
}
//go:nosplit
func futexsleep(addr *uint32, val uint32, ns int64) {
- deadline := zx.Sys_deadline_after(zx.Duration(ns))
+ deadline := sys_deadline_after(ns)
if ns < 0 {
- deadline = zx.Time(zx.TimensecInfinite)
+ deadline = nsecInf
}
- zx.Sys_futex_wait((*int32)(unsafe.Pointer(addr)), int32(val), zx.HandleInvalid, deadline)
+ sys_futex_wait((*int32)(unsafe.Pointer(addr)), int32(val), 0, deadline)
}
//go:nosplit
func futexwakeup(addr *uint32, cnt uint32) {
- zx.Sys_futex_wake((*int32)(unsafe.Pointer(addr)), cnt)
-}
-
-//go:nosplit
-func osyield() {
- zx.Sys_nanosleep(0)
+ sys_futex_wake((*int32)(unsafe.Pointer(addr)), cnt)
}
// cgocallm0 calls a C function on the current stack.
@@ -55,18 +112,16 @@
if _cgo_get_initial_handles != nil {
cgocallm0(_cgo_get_initial_handles, unsafe.Pointer(&fdioHandles))
for i := 0; i < 3; i = i + 1 {
- zx.StdioHandles[i] = fdioHandles.stdioClones[i]
- zx.StdioHandleTypes[i] = int(fdioHandles.stdioCloneTypes[i])
+ zx_set_stdio_handle(i, fdioHandles.stdioClones[i], fdioHandles.stdioCloneTypes[i])
}
- zx.ProcHandle = zx.Handle(fdioHandles.processSelf)
- zx.VMARRoot = zx.VMAR(fdioHandles.vmarRootSelf)
+ zx_set_proc_handle(fdioHandles.processSelf)
+ zx_set_vmar_root(fdioHandles.vmarRootSelf)
} else {
- // TODO: implement cgo-less init
- println("runtime: no fuchsia process handle without cgo yet")
+ println("runtime: fuchsia requires cgo")
exit(2)
}
- ncpu = int32(zx.Sys_system_get_num_cpus())
+ ncpu = int32(sys_system_get_num_cpus())
physPageSize = 4096
}
@@ -74,16 +129,17 @@
if fdioHandles.rootNSNumHandles > 0 {
const maxHandleCount = 1 << 20 // arbitrary
paths := (*(*[maxHandleCount]*byte)(unsafe.Pointer(fdioHandles.rootNSPaths)))[:fdioHandles.rootNSNumHandles]
- handles := (*(*[maxHandleCount]zx.Handle)(unsafe.Pointer(fdioHandles.rootNSHandles)))[:fdioHandles.rootNSNumHandles]
- zx.RootNSMap = make(map[string]zx.Handle)
+ handles := (*(*[maxHandleCount]uint32)(unsafe.Pointer(fdioHandles.rootNSHandles)))[:fdioHandles.rootNSNumHandles]
+ m := make(map[string]uint32)
for i, p := range paths {
- zx.RootNSMap[gostring(p)] = handles[i]
+ m[gostring(p)] = handles[i]
}
+
+ zx_set_namespace(m)
}
}
// Filled in by runtime/cgo when linked into binary.
-
var (
_cgo_get_initial_handles unsafe.Pointer
_cgo_get_thread_self_handle unsafe.Pointer
@@ -91,7 +147,7 @@
//go:nosplit
func minit() {
- var h zx.Handle
+ var h uint32
asmcgocall(_cgo_get_thread_self_handle, unsafe.Pointer(&h))
atomic.Storeuintptr(&getg().m.thread, uintptr(h))
}
@@ -151,19 +207,19 @@
//go:nowritebarrier
func newosproc(mp *m) {
stk := unsafe.Pointer(mp.g0.stack.hi)
- p := zx.Handle(0) // TODO: only works due to temporary hack in zircon
- var h zx.Handle
- status := zx.Sys_thread_create(p, &gothreadname[0], uint(len(gothreadname)), 0, &h)
+ p := uint32(0) // TODO: only works due to temporary hack in zircon
+ var h uint32
+ status := sys_thread_create(p, &gothreadname[0], uint(len(gothreadname)), 0, &h)
if status < 0 {
- println("runtime: newosproc zx.Sys_thread_create failed:", h)
+ println("runtime: newosproc sys_thread_create failed:", h)
exit(2)
}
mp.thread = uintptr(h)
- status = zx.Sys_thread_start(h, zx.Vaddr(funcPC(threadinit)), zx.Vaddr(stk), uintptr(unsafe.Pointer(mp)), 0)
+ status = sys_thread_start(h, unsafe.Pointer(funcPC(threadinit)), stk, uintptr(unsafe.Pointer(mp)), 0)
if status < 0 {
- println("runtime: newosproc zx.Sys_thread_start failed:", h)
+ println("runtime: newosproc sys_thread_start failed:", h)
exit(2)
}
}
@@ -181,7 +237,7 @@
version uint32
next_tls_slot uint32
proc_args *zx_proc_args
- handle *zx.Handle
+ handle *uint32
handle_info *uint32
handle_count int32
argv **byte
@@ -203,16 +259,16 @@
// fdio_init matches a Go struct of the same name in gcc_fdio.c.
type fdio_init struct {
- stdioClones [3]zx.Handle
+ stdioClones [3]uint32
stdioCloneNumHandles [3]uint32
stdioCloneTypes [3]uint32
- processSelf zx.Handle
- vmarRootSelf zx.Handle
+ processSelf uint32
+ vmarRootSelf uint32
envlen int32
environ **byte
_ [4]byte
rootNSNumHandles int32
- rootNSHandles *zx.Handle
+ rootNSHandles *uint32
rootNSPaths **byte
}
@@ -253,15 +309,15 @@
//go:nosplit
func nanotime() int64 {
- return int64(zx.Sys_clock_get_monotonic())
+ return sys_clock_get_monotonic()
}
//go:linkname time_now time.now
//go:nosplit
func time_now() (sec int64, nsec int32, mono int64) {
const ZX_CLOCK_UTC = 1
- var x zx.Time
- zx.Sys_clock_get(ZX_CLOCK_UTC, &x)
+ var x int64
+ sys_clock_get(ZX_CLOCK_UTC, &x)
return int64(x / 1e9), int32(x % 1e9), nanotime()
}
@@ -272,7 +328,7 @@
// #define LOGBUF_MAX (ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t))
const logBufMax = 224
-var logger zx.Handle
+var logger uint32
var logBufferArray [logBufMax]byte
var logBufferN int
@@ -286,7 +342,7 @@
// these file descriptors come from print, they will already be serialized by a lock in
// print's implementation.
if logger <= 0 {
- zx.Sys_debuglog_create(0, 0, &logger)
+ sys_debuglog_create(0, 0, &logger)
logBufferN = 0
}
// Ideally this should panic, but that would go down "blind", which is arguably worse.
@@ -298,7 +354,7 @@
c := *(*byte)(unsafe.Pointer(uintptr(buf) + uintptr(i)))
if c == '\n' {
- zx.Sys_debuglog_write(logger, 0, unsafe.Pointer(&logBufferArray[0]), uint(logBufferN))
+ sys_debuglog_write(logger, 0, unsafe.Pointer(&logBufferArray[0]), uint(logBufferN))
logBufferN = 0
continue
}
@@ -311,7 +367,7 @@
logBufferN++
if logBufferN == len(logBufferArray) {
- zx.Sys_debuglog_write(logger, 0, unsafe.Pointer(&logBufferArray[0]), uint(logBufferN))
+ sys_debuglog_write(logger, 0, unsafe.Pointer(&logBufferArray[0]), uint(logBufferN))
logBufferN = 0
}
}
@@ -321,12 +377,12 @@
//go:nosplit
func exit(code int32) {
- zx.Sys_process_exit(int64(code))
+ sys_process_exit(int64(code))
}
//go:nosplit
func usleep(usec uint32) {
- zx.Sys_nanosleep(zx.Sys_deadline_after(zx.Duration(usec * 1000)))
+ sys_nanosleep(sys_deadline_after(int64(usec * 1000)))
}
func signame(sig uint32) string {
diff --git a/src/runtime/sys_fuchsia_amd64.s b/src/runtime/sys_fuchsia_amd64.s
index e909874..ef752c5 100644
--- a/src/runtime/sys_fuchsia_amd64.s
+++ b/src/runtime/sys_fuchsia_amd64.s
@@ -85,3 +85,9 @@
CALL AX
MOVL AX, ret+24(FP)
RET
+
+TEXT runtime·osyield(SB),NOSPLIT,$0
+ MOVQ $0, DI
+ MOVQ vdso_zx_nanosleep(SB), AX
+ CALL AX
+ RET
diff --git a/src/runtime/sys_fuchsia_arm64.s b/src/runtime/sys_fuchsia_arm64.s
index a391e7d..5055bc3 100644
--- a/src/runtime/sys_fuchsia_arm64.s
+++ b/src/runtime/sys_fuchsia_arm64.s
@@ -51,3 +51,8 @@
BL vdso_zx_object_wait_one(SB)
MOVW R0, ret+24(FP)
RET
+
+TEXT runtime·osyield(SB),NOSPLIT,$0
+ MOVD $0, R0
+ BL vdso_zx_nanosleep(SB)
+ RET
diff --git a/src/syscall/zx/handle.go b/src/syscall/zx/handle.go
index 66bc050..28e2005 100644
--- a/src/syscall/zx/handle.go
+++ b/src/syscall/zx/handle.go
@@ -25,6 +25,29 @@
type HandleInfo uint32
+func set_stdio_handle(n int, h uint32, t uint32) {
+ StdioHandles[n] = Handle(h)
+ StdioHandleTypes[n] = int(t)
+}
+
+func set_proc_handle(h uint32) {
+ ProcHandle = Handle(h)
+}
+
+func set_vmar_root(h uint32) {
+ VMARRoot = VMAR(h)
+}
+
+func set_namespace(ns map[string]uint32) {
+ if RootNSMap == nil {
+ RootNSMap = make(map[string]Handle)
+ }
+
+ for k, v := range ns {
+ RootNSMap[k] = Handle(v)
+ }
+}
+
func NewHandleInfo(t, arg uint32) HandleInfo {
return HandleInfo((t & 0xFFFF) | ((arg & 0xFFFF) << 16))
}