1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
9 "runtime/internal/atomic"
19 _EWOULDBLOCK = _EAGAIN
22 // From OpenBSD's sys/time.h
31 var sigset_all = ^sigset(0)
33 // From OpenBSD's <sys/sysctl.h>
44 func sysctlInt(mib []uint32) (int32, bool) {
46 nout := unsafe.Sizeof(out)
47 ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
54 func sysctlUint64(mib []uint32) (uint64, bool) {
56 nout := unsafe.Sizeof(out)
57 ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
64 //go:linkname internal_cpu_sysctlUint64 internal/cpu.sysctlUint64
65 func internal_cpu_sysctlUint64(mib []uint32) (uint64, bool) {
66 return sysctlUint64(mib)
69 func getncpu() int32 {
70 // Try hw.ncpuonline first because hw.ncpu would report a number twice as
71 // high as the actual CPUs running on OpenBSD 6.4 with hyperthreading
72 // disabled (hw.smt=0). See https://golang.org/issue/30127
73 if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPUONLINE}); ok {
76 if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPU}); ok {
82 func getPageSize() uintptr {
83 if ps, ok := sysctlInt([]uint32{_CTL_HW, _HW_PAGESIZE}); ok {
90 if osrev, ok := sysctlInt([]uint32{_CTL_KERN, _KERN_OSREV}); ok {
97 func semacreate(mp *m) {
101 func semasleep(ns int64) int32 {
104 // Compute sleep deadline.
108 ts.setNsec(ns + nanotime())
113 v := atomic.Load(&gp.m.waitsemacount)
115 if atomic.Cas(&gp.m.waitsemacount, v, v-1) {
116 return 0 // semaphore acquired
121 // Sleep until woken by semawakeup or timeout; or abort if waitsemacount != 0.
123 // From OpenBSD's __thrsleep(2) manual:
124 // "The abort argument, if not NULL, points to an int that will
125 // be examined [...] immediately before blocking. If that int
126 // is non-zero then __thrsleep() will immediately return EINTR
127 // without blocking."
128 ret := thrsleep(uintptr(unsafe.Pointer(&gp.m.waitsemacount)), _CLOCK_MONOTONIC, tsp, 0, &gp.m.waitsemacount)
129 if ret == _EWOULDBLOCK {
136 func semawakeup(mp *m) {
137 atomic.Xadd(&mp.waitsemacount, 1)
138 ret := thrwakeup(uintptr(unsafe.Pointer(&mp.waitsemacount)), 1)
139 if ret != 0 && ret != _ESRCH {
140 // semawakeup can be called on signal stack.
142 print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
149 physPageSize = getPageSize()
152 var urandom_dev = []byte("/dev/urandom\x00")
155 func getRandomData(r []byte) {
156 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
157 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
159 extendRandom(r, int(n))
166 // Called to initialize a new m (including the bootstrap m).
167 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
168 func mpreinit(mp *m) {
169 gsignalSize := int32(32 * 1024)
170 if GOARCH == "mips64" {
171 gsignalSize = int32(64 * 1024)
173 mp.gsignal = malg(gsignalSize)
177 // Called to initialize a new m (including the bootstrap m).
178 // Called on the new thread, can not allocate memory.
180 getg().m.procid = uint64(getthrid())
184 // Called from dropm to undo the effect of an minit.
192 // Called from exitm, but not from drop, to undo the effect of thread-owned
193 // resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
194 func mdestroy(mp *m) {
199 type sigactiont struct {
206 //go:nowritebarrierrec
207 func setsig(i uint32, fn uintptr) {
209 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
210 sa.sa_mask = uint32(sigset_all)
211 if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go
212 fn = abi.FuncPCABI0(sigtramp)
215 sigaction(i, &sa, nil)
219 //go:nowritebarrierrec
220 func setsigstack(i uint32) {
225 //go:nowritebarrierrec
226 func getsig(i uint32) uintptr {
228 sigaction(i, nil, &sa)
229 return sa.sa_sigaction
232 // setSignalstackSP sets the ss_sp field of a stackt.
235 func setSignalstackSP(s *stackt, sp uintptr) {
240 //go:nowritebarrierrec
241 func sigaddset(mask *sigset, i int) {
242 *mask |= 1 << (uint32(i) - 1)
245 func sigdelset(mask *sigset, i int) {
246 *mask &^= 1 << (uint32(i) - 1)
250 func (c *sigctxt) fixsigcode(sig uint32) {
253 func setProcessCPUProfiler(hz int32) {
254 setProcessCPUProfilerTimer(hz)
257 func setThreadCPUProfiler(hz int32) {
258 setThreadCPUProfilerHz(hz)
262 func validSIGPROF(mp *m, c *sigctxt) bool {
266 func osStackAlloc(s *mspan) {
267 osStackRemap(s, _MAP_STACK)
270 func osStackFree(s *mspan) {
275 func osStackRemap(s *mspan, flags int32) {
276 a, err := mmap(unsafe.Pointer(s.base()), s.npages*pageSize, _PROT_READ|_PROT_WRITE, _MAP_PRIVATE|_MAP_ANON|_MAP_FIXED|flags, -1, 0)
277 if err != 0 || uintptr(a) != s.base() {
278 print("runtime: remapping stack memory ", hex(s.base()), " ", s.npages*pageSize, " a=", a, " err=", err, "\n")
279 throw("remapping stack memory failed")
284 func raise(sig uint32) {
285 thrkill(getthrid(), int(sig))
288 func signalM(mp *m, sig int) {
289 thrkill(int32(mp.procid), sig)
292 // sigPerThreadSyscall is only used on linux, so we assign a bogus signal
294 const sigPerThreadSyscall = 1 << 31
297 func runPerThreadSyscall() {
298 throw("runPerThreadSyscall only valid on linux")