diff options
Diffstat (limited to 'src/runtime/os_solaris.go')
-rw-r--r-- | src/runtime/os_solaris.go | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/src/runtime/os_solaris.go b/src/runtime/os_solaris.go new file mode 100644 index 0000000..89129e5 --- /dev/null +++ b/src/runtime/os_solaris.go @@ -0,0 +1,266 @@ +// Copyright 2014 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 "unsafe" + +type mts struct { + tv_sec int64 + tv_nsec int64 +} + +type mscratch struct { + v [6]uintptr +} + +type mOS struct { + waitsema uintptr // semaphore for parking on locks + perrno *int32 // pointer to tls errno + // these are here because they are too large to be on the stack + // of low-level NOSPLIT functions. + //LibCall libcall; + ts mts + scratch mscratch +} + +type libcFunc uintptr + +//go:linkname asmsysvicall6x runtime.asmsysvicall6 +var asmsysvicall6x libcFunc // name to take addr of asmsysvicall6 + +func asmsysvicall6() // declared for vet; do NOT call + +//go:nosplit +func sysvicall0(fn *libcFunc) uintptr { + // Leave caller's PC/SP around for traceback. + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil // See comment in sys_darwin.go:libcCall + } + + var libcall libcall + libcall.fn = uintptr(unsafe.Pointer(fn)) + libcall.n = 0 + libcall.args = uintptr(unsafe.Pointer(fn)) // it's unused but must be non-nil, otherwise crashes + asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall)) + if mp != nil { + mp.libcallsp = 0 + } + return libcall.r1 +} + +//go:nosplit +func sysvicall1(fn *libcFunc, a1 uintptr) uintptr { + r1, _ := sysvicall1Err(fn, a1) + return r1 +} + +//go:nosplit + +// sysvicall1Err returns both the system call result and the errno value. +// This is used by sysvicall1 and pipe. +func sysvicall1Err(fn *libcFunc, a1 uintptr) (r1, err uintptr) { + // Leave caller's PC/SP around for traceback. + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil + } + + var libcall libcall + libcall.fn = uintptr(unsafe.Pointer(fn)) + libcall.n = 1 + // TODO(rsc): Why is noescape necessary here and below? + libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) + asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall)) + if mp != nil { + mp.libcallsp = 0 + } + return libcall.r1, libcall.err +} + +//go:nosplit +func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr { + r1, _ := sysvicall2Err(fn, a1, a2) + return r1 +} + +//go:nosplit +//go:cgo_unsafe_args + +// sysvicall2Err returns both the system call result and the errno value. +// This is used by sysvicall2 and pipe2. +func sysvicall2Err(fn *libcFunc, a1, a2 uintptr) (uintptr, uintptr) { + // Leave caller's PC/SP around for traceback. + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil + } + + var libcall libcall + libcall.fn = uintptr(unsafe.Pointer(fn)) + libcall.n = 2 + libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) + asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall)) + if mp != nil { + mp.libcallsp = 0 + } + return libcall.r1, libcall.err +} + +//go:nosplit +func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr { + r1, _ := sysvicall3Err(fn, a1, a2, a3) + return r1 +} + +//go:nosplit +//go:cgo_unsafe_args + +// sysvicall3Err returns both the system call result and the errno value. +// This is used by sysicall3 and write1. +func sysvicall3Err(fn *libcFunc, a1, a2, a3 uintptr) (r1, err uintptr) { + // Leave caller's PC/SP around for traceback. + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil + } + + var libcall libcall + libcall.fn = uintptr(unsafe.Pointer(fn)) + libcall.n = 3 + libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) + asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall)) + if mp != nil { + mp.libcallsp = 0 + } + return libcall.r1, libcall.err +} + +//go:nosplit +func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr { + // Leave caller's PC/SP around for traceback. + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil + } + + var libcall libcall + libcall.fn = uintptr(unsafe.Pointer(fn)) + libcall.n = 4 + libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) + asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall)) + if mp != nil { + mp.libcallsp = 0 + } + return libcall.r1 +} + +//go:nosplit +func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr { + // Leave caller's PC/SP around for traceback. + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil + } + + var libcall libcall + libcall.fn = uintptr(unsafe.Pointer(fn)) + libcall.n = 5 + libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) + asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall)) + if mp != nil { + mp.libcallsp = 0 + } + return libcall.r1 +} + +//go:nosplit +func sysvicall6(fn *libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr { + // Leave caller's PC/SP around for traceback. + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil + } + + var libcall libcall + libcall.fn = uintptr(unsafe.Pointer(fn)) + libcall.n = 6 + libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) + asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall)) + if mp != nil { + mp.libcallsp = 0 + } + return libcall.r1 +} |