blob: 7a33e8103b7a3d88506653750b77610a2e967c64 [file] [log] [blame]
// Copyright 2016 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 (
"syscall/zx"
"unsafe"
)
type mOS struct{}
type sigset struct{}
//go:nosplit
func getRandomData(r []byte) {
zx.RandRead(r)
}
//go:nosplit
func futexsleep(addr *uint32, val uint32, ns int64) {
deadline := zx.Sys_deadline_after(zx.Duration(ns))
if ns < 0 {
deadline = zx.Time(zx.TimensecInfinite)
}
zx.Sys_futex_wait((*int)(unsafe.Pointer(addr)), int32(val), deadline)
}
//go:nosplit
func futexwakeup(addr *uint32, cnt uint32) {
zx.Sys_futex_wake((*int)(unsafe.Pointer(addr)), cnt)
}
//go:nosplit
func osyield() {
zx.Sys_nanosleep(0)
}
// cgocallm0 calls a C function on the current stack.
//
// It is intended for use inside functions like osinit that run
// before mstart directly on an OS thread stack.
//
// If in doubt, do not use.
func cgocallm0(fn, arg unsafe.Pointer)
func osinit() {
if _cgo_get_initial_handles != nil {
cgocallm0(_cgo_get_initial_handles, unsafe.Pointer(&fdioHandles))
for i := 0; i < 3; i = i + 1 {
for j := 0; j < int(fdioHandles.stdioCloneNumHandles[i]); j = j + 1 {
zx.StdioHandles[i][j] = fdioHandles.stdioClones[i*3+j]
}
zx.StdioHandleTypes[i] = int(fdioHandles.stdioCloneTypes[i])
}
zx.ProcHandle = zx.Handle(fdioHandles.processSelf)
zx.VMARRoot = zx.VMAR(fdioHandles.vmarRootSelf)
} else {
// TODO: implement cgo-less init
println("runtime: no fuchsia process handle without cgo yet")
exit(2)
}
ncpu = int32(zx.Sys_system_get_num_cpus())
physPageSize = 4096
}
func parseRootNS() {
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)
for i, p := range paths {
zx.RootNSMap[gostring(p)] = handles[i]
}
}
}
// Filled in by runtime/cgo when linked into binary.
var _cgo_get_initial_handles unsafe.Pointer // pointer to C function
func minit() {
}
//go:nosplit
func unminit() {
// TODO
}
func sigpanic() {
// TODO
}
func mpreinit(mp *m) {
// TODO
}
//go:nosplit
func msigsave(mp *m) {
// TODO
}
//go:nosplit
func msigrestore(sigmask sigset) {
// TODO
}
func initsig(preinit bool) {
// TODO
}
//go:nosplit
func sigblock() {
// TODO
}
func sigenable(sig uint32) {
// TODO
}
func sigdisable(sig uint32) {
// TODO
}
func sigignore(sig uint32) {
// TODO
}
func crash() {
*(*int32)(nil) = 0
}
func threadinit(mp *m)
var gothreadname = []byte("gothread")
//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)
if status < 0 {
println("runtime: newosproc zx.Sys_thread_create failed:", h)
exit(2)
}
status = zx.Sys_thread_start(h, zx.Vaddr(funcPC(threadinit)), zx.Vaddr(stk), uintptr(unsafe.Pointer(mp)), 0)
if status < 0 {
println("runtime: newosproc zx.Sys_thread_start failed:", h)
exit(2)
}
}
type zx_proc_args struct {
protocol uint32
version uint32
handle_info_off uint32
args_off uint32
args_num uint32
}
type zx_proc_info struct {
magic uint32
version uint32
next_tls_slot uint32
proc_args *zx_proc_args
handle *zx.Handle
handle_info *uint32
handle_count int32
argv **byte
argc int32
}
type zx_tls_root struct {
self *zx_tls_root
proc *zx_proc_info
magic uint32
flags uint16
maxslots uint16
slots [8]uintptr // has length maxslots
}
func resetcpuprofiler(hz int32) {
// TODO
}
// fdio_init matches a Go struct of the same name in gcc_fdio.c.
type fdio_init struct {
stdioClones [9]zx.Handle // 3 * fdio.MaxHandles
stdioCloneNumHandles [3]uint32
stdioCloneTypes [3]uint32
processSelf zx.Handle
vmarRootSelf zx.Handle
_ int32
envlen int32
environ **byte
_ int32
rootNSNumHandles int32
rootNSHandles *zx.Handle
rootNSPaths **byte
}
var fdioHandles fdio_init
func goenvs() {
if _cgo_get_initial_handles != nil {
const maxEnvSize = 1 << 20 // arbitrary
envp := (*(*[maxEnvSize]*byte)(unsafe.Pointer(fdioHandles.environ)))[:fdioHandles.envlen]
envs = make([]string, len(envp))
for i, e := range envp {
envs[i] = gostring(e)
}
// TODO: find a better place to call this
parseRootNS()
} else {
// TODO: implement cgo-less init
println("runtime: no fuchsia process handle without cgo yet")
exit(2)
}
}
const _NSIG = 65 // TODO
//go:nosplit
func nanotime() int64 {
const ZX_CLOCK_MONOTONIC = 0
return int64(zx.Sys_clock_get(ZX_CLOCK_MONOTONIC))
}
//go:linkname time_now time.now
//go:nosplit
func time_now() (sec int64, nsec int32, mono int64) {
const ZX_CLOCK_UTC = 1
x := int64(zx.Sys_clock_get(ZX_CLOCK_UTC))
return int64(x / 1e9), int32(x % 1e9), nanotime() - startNano
}
func unixnanotime() int64 {
return nanotime()
}
var logger zx.Handle
var logBufferArray [1024]byte
var logBufferN int
//go:nosplit
func write(fd uintptr, buf unsafe.Pointer, n int32) int32 {
if fd == 1 || fd == 2 {
// This initialization mechanism is not thread-safe, but if the only calls to 'write' with
// 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)
logBufferN = 0
}
if logger > 0 {
// Sys_log_write adds a newline to output buffers. To prevent fragmented logs, we buffer
// output until a newline character is encountered.
logBufferN += copy(logBufferArray[logBufferN:], (*[1 << 30]byte)(buf)[:n])
if logBufferArray[logBufferN-1] == '\n' {
status := zx.Sys_log_write(logger, uint32(logBufferN), unsafe.Pointer(&logBufferArray[0]), 0)
// Flush buffer, regardless of status returned from write
logBufferN = 0
if status < 0 {
return int32(status)
}
}
}
}
// TODO
return n
}
//go:nosplit
func exit(code int32) {
zx.Sys_process_exit(int64(code))
}
//go:nosplit
func usleep(usec uint32) {
zx.Sys_nanosleep(zx.Sys_deadline_after(zx.Duration(usec * 1000)))
}
func signame(sig uint32) string {
return "unknown_sig" // TODO
}
// zircon_mktls
//go:nosplit
func zircon_mktls() {
// TODO
}
//go:nosplit
func zircon_settls(val uintptr) {
// TODO: should call zx_set_object_property with property ZX_PROP_REGISTER_FS in amd64 or
// ZX_PROP_REGISTER_CP15 on arm.
}
//go:linkname os_sigpipe os.sigpipe
func os_sigpipe() {
// TODO
}
// gsignalStack is unused on fuchsia
type gsignalStack struct{}
func exitThread(wait *uint32) {}
func setProcessCPUProfiler(hz int32) {}
func setThreadCPUProfiler(hz int32) {}
//go:nosplit
//go:nowritebarrierrec
func clearSignalHandlers() {}