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>
43 func sysctlInt(mib []uint32) (int32, bool) {
45 nout := unsafe.Sizeof(out)
46 ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
53 func sysctlUint64(mib []uint32) (uint64, bool) {
55 nout := unsafe.Sizeof(out)
56 ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
63 //go:linkname internal_cpu_sysctlUint64 internal/cpu.sysctlUint64
64 func internal_cpu_sysctlUint64(mib []uint32) (uint64, bool) {
65 return sysctlUint64(mib)
68 func getncpu() int32 {
69 // Try hw.ncpuonline first because hw.ncpu would report a number twice as
70 // high as the actual CPUs running on OpenBSD 6.4 with hyperthreading
71 // disabled (hw.smt=0). See https://golang.org/issue/30127
72 if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPUONLINE}); ok {
75 if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPU}); ok {
81 func getPageSize() uintptr {
82 if ps, ok := sysctlInt([]uint32{_CTL_HW, _HW_PAGESIZE}); ok {
89 func semacreate(mp *m) {
93 func semasleep(ns int64) int32 {
96 // Compute sleep deadline.
100 ts.setNsec(ns + nanotime())
105 v := atomic.Load(&gp.m.waitsemacount)
107 if atomic.Cas(&gp.m.waitsemacount, v, v-1) {
108 return 0 // semaphore acquired
113 // Sleep until woken by semawakeup or timeout; or abort if waitsemacount != 0.
115 // From OpenBSD's __thrsleep(2) manual:
116 // "The abort argument, if not NULL, points to an int that will
117 // be examined [...] immediately before blocking. If that int
118 // is non-zero then __thrsleep() will immediately return EINTR
119 // without blocking."
120 ret := thrsleep(uintptr(unsafe.Pointer(&gp.m.waitsemacount)), _CLOCK_MONOTONIC, tsp, 0, &gp.m.waitsemacount)
121 if ret == _EWOULDBLOCK {
128 func semawakeup(mp *m) {
129 atomic.Xadd(&mp.waitsemacount, 1)
130 ret := thrwakeup(uintptr(unsafe.Pointer(&mp.waitsemacount)), 1)
131 if ret != 0 && ret != _ESRCH {
132 // semawakeup can be called on signal stack.
134 print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
141 physPageSize = getPageSize()
144 var urandom_dev = []byte("/dev/urandom\x00")
147 func getRandomData(r []byte) {
148 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
149 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
151 extendRandom(r, int(n))
158 // Called to initialize a new m (including the bootstrap m).
159 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
160 func mpreinit(mp *m) {
161 gsignalSize := int32(32 * 1024)
162 if GOARCH == "mips64" {
163 gsignalSize = int32(64 * 1024)
165 mp.gsignal = malg(gsignalSize)
169 // Called to initialize a new m (including the bootstrap m).
170 // Called on the new thread, can not allocate memory.
172 getg().m.procid = uint64(getthrid())
176 // Called from dropm to undo the effect of an minit.
184 // Called from exitm, but not from drop, to undo the effect of thread-owned
185 // resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
186 func mdestroy(mp *m) {
191 type sigactiont struct {
198 //go:nowritebarrierrec
199 func setsig(i uint32, fn uintptr) {
201 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
202 sa.sa_mask = uint32(sigset_all)
203 if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go
204 fn = abi.FuncPCABI0(sigtramp)
207 sigaction(i, &sa, nil)
211 //go:nowritebarrierrec
212 func setsigstack(i uint32) {
217 //go:nowritebarrierrec
218 func getsig(i uint32) uintptr {
220 sigaction(i, nil, &sa)
221 return sa.sa_sigaction
224 // setSignalstackSP sets the ss_sp field of a stackt.
227 func setSignalstackSP(s *stackt, sp uintptr) {
232 //go:nowritebarrierrec
233 func sigaddset(mask *sigset, i int) {
234 *mask |= 1 << (uint32(i) - 1)
237 func sigdelset(mask *sigset, i int) {
238 *mask &^= 1 << (uint32(i) - 1)
242 func (c *sigctxt) fixsigcode(sig uint32) {
245 func setProcessCPUProfiler(hz int32) {
246 setProcessCPUProfilerTimer(hz)
249 func setThreadCPUProfiler(hz int32) {
250 setThreadCPUProfilerHz(hz)
254 func validSIGPROF(mp *m, c *sigctxt) bool {
258 func osStackAlloc(s *mspan) {
259 osStackRemap(s, _MAP_STACK)
262 func osStackFree(s *mspan) {
267 func osStackRemap(s *mspan, flags int32) {
268 a, err := mmap(unsafe.Pointer(s.base()), s.npages*pageSize, _PROT_READ|_PROT_WRITE, _MAP_PRIVATE|_MAP_ANON|_MAP_FIXED|flags, -1, 0)
269 if err != 0 || uintptr(a) != s.base() {
270 print("runtime: remapping stack memory ", hex(s.base()), " ", s.npages*pageSize, " a=", a, " err=", err, "\n")
271 throw("remapping stack memory failed")
276 func raise(sig uint32) {
277 thrkill(getthrid(), int(sig))
280 func signalM(mp *m, sig int) {
281 thrkill(int32(mp.procid), sig)
284 // sigPerThreadSyscall is only used on linux, so we assign a bogus signal
286 const sigPerThreadSyscall = 1 << 31
289 func runPerThreadSyscall() {
290 throw("runPerThreadSyscall only valid on linux")