1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
// 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 (
"internal/abi"
"internal/goarch"
"runtime/internal/atomic"
"unsafe"
)
type mOS struct {
waitsemacount uint32
}
func getProcID() uint64 {
return uint64(lwp_self())
}
//extern-sysinfo _lwp_self
func lwp_self() int32
//go:noescape
//extern-sysinfo _lwp_park
func lwp_park(ts int32, rel int32, abstime *timespec, unpark int32, hint, unparkhint unsafe.Pointer) int32
//go:noescape
//extern-sysinfo _lwp_unpark
func lwp_unpark(lwp int32, hint unsafe.Pointer) int32
//go:noescape
//extern-sysinfo sysctl
func sysctl(*uint32, uint32, *byte, *uintptr, *byte, uintptr) int32
func sysctlInt(mib []uint32) (int32, bool) {
var out int32
nout := unsafe.Sizeof(out)
ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
if ret < 0 {
return 0, false
}
return out, true
}
func getncpu() int32 {
if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPUONLINE}); ok {
return int32(n)
}
if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPU}); ok {
return int32(n)
}
return 1
}
func getPageSize() uintptr {
mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
out := uint32(0)
nout := unsafe.Sizeof(out)
ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
if ret >= 0 {
return uintptr(out)
}
return 0
}
func getOSRev() int {
if osrev, ok := sysctlInt([]uint32{_CTL_KERN, _KERN_OSREV}); ok {
return int(osrev)
}
return 0
}
//go:nosplit
func semacreate(mp *m) {
}
//go:nosplit
func semasleep(ns int64) int32 {
_g_ := getg()
var deadline int64
if ns >= 0 {
deadline = nanotime() + ns
}
for {
v := atomic.Load(&_g_.m.waitsemacount)
if v > 0 {
if atomic.Cas(&_g_.m.waitsemacount, v, v-1) {
return 0 // semaphore acquired
}
continue
}
// Sleep until unparked by semawakeup or timeout.
var tsp *timespec
var ts timespec
if ns >= 0 {
wait := deadline - nanotime()
if wait <= 0 {
return -1
}
ts.setNsec(wait)
tsp = &ts
}
ret := lwp_park(_CLOCK_MONOTONIC, _TIMER_RELTIME, tsp, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil)
if ret != 0 && errno() == _ETIMEDOUT {
return -1
}
}
}
//go:nosplit
func semawakeup(mp *m) {
atomic.Xadd(&mp.waitsemacount, 1)
// From NetBSD's _lwp_unpark(2) manual:
// "If the target LWP is not currently waiting, it will return
// immediately upon the next call to _lwp_park()."
ret := lwp_unpark(int32(mp.procid), unsafe.Pointer(&mp.waitsemacount))
if ret != 0 && errno() != _ESRCH {
// semawakeup can be called on signal stack.
systemstack(func() {
print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " errno=", errno(), "\n")
})
}
}
func osinit() {
ncpu = getncpu()
if physPageSize == 0 {
physPageSize = getPageSize()
}
needSysmonWorkaround = getOSRev() < 902000000 // NetBSD 9.2
}
func sysargs(argc int32, argv **byte) {
n := argc + 1
// skip over argv, envp to get to auxv
for argv_index(argv, n) != nil {
n++
}
// skip NULL separator
n++
// now argv+n is auxv
auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize))
sysauxv(auxv[:])
}
const (
_AT_NULL = 0 // Terminates the vector
_AT_PAGESZ = 6 // Page size in bytes
)
func sysauxv(auxv []uintptr) {
for i := 0; auxv[i] != _AT_NULL; i += 2 {
tag, val := auxv[i], auxv[i+1]
switch tag {
case _AT_PAGESZ:
physPageSize = val
}
}
}
|