]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/os_openbsd.go
runtime: remove unused getOSRev on openbsd
[gostls13.git] / src / runtime / os_openbsd.go
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.
4
5 package runtime
6
7 import (
8         "internal/abi"
9         "runtime/internal/atomic"
10         "unsafe"
11 )
12
13 type mOS struct {
14         waitsemacount uint32
15 }
16
17 const (
18         _ESRCH       = 3
19         _EWOULDBLOCK = _EAGAIN
20         _ENOTSUP     = 91
21
22         // From OpenBSD's sys/time.h
23         _CLOCK_REALTIME  = 0
24         _CLOCK_VIRTUAL   = 1
25         _CLOCK_PROF      = 2
26         _CLOCK_MONOTONIC = 3
27 )
28
29 type sigset uint32
30
31 var sigset_all = ^sigset(0)
32
33 // From OpenBSD's <sys/sysctl.h>
34 const (
35         _CTL_KERN = 1
36
37         _CTL_HW        = 6
38         _HW_NCPU       = 3
39         _HW_PAGESIZE   = 7
40         _HW_NCPUONLINE = 25
41 )
42
43 func sysctlInt(mib []uint32) (int32, bool) {
44         var out int32
45         nout := unsafe.Sizeof(out)
46         ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
47         if ret < 0 {
48                 return 0, false
49         }
50         return out, true
51 }
52
53 func sysctlUint64(mib []uint32) (uint64, bool) {
54         var out uint64
55         nout := unsafe.Sizeof(out)
56         ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
57         if ret < 0 {
58                 return 0, false
59         }
60         return out, true
61 }
62
63 //go:linkname internal_cpu_sysctlUint64 internal/cpu.sysctlUint64
64 func internal_cpu_sysctlUint64(mib []uint32) (uint64, bool) {
65         return sysctlUint64(mib)
66 }
67
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 {
73                 return int32(n)
74         }
75         if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPU}); ok {
76                 return int32(n)
77         }
78         return 1
79 }
80
81 func getPageSize() uintptr {
82         if ps, ok := sysctlInt([]uint32{_CTL_HW, _HW_PAGESIZE}); ok {
83                 return uintptr(ps)
84         }
85         return 0
86 }
87
88 //go:nosplit
89 func semacreate(mp *m) {
90 }
91
92 //go:nosplit
93 func semasleep(ns int64) int32 {
94         gp := getg()
95
96         // Compute sleep deadline.
97         var tsp *timespec
98         if ns >= 0 {
99                 var ts timespec
100                 ts.setNsec(ns + nanotime())
101                 tsp = &ts
102         }
103
104         for {
105                 v := atomic.Load(&gp.m.waitsemacount)
106                 if v > 0 {
107                         if atomic.Cas(&gp.m.waitsemacount, v, v-1) {
108                                 return 0 // semaphore acquired
109                         }
110                         continue
111                 }
112
113                 // Sleep until woken by semawakeup or timeout; or abort if waitsemacount != 0.
114                 //
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 {
122                         return -1
123                 }
124         }
125 }
126
127 //go:nosplit
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.
133                 systemstack(func() {
134                         print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
135                 })
136         }
137 }
138
139 func osinit() {
140         ncpu = getncpu()
141         physPageSize = getPageSize()
142 }
143
144 var urandom_dev = []byte("/dev/urandom\x00")
145
146 //go:nosplit
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)))
150         closefd(fd)
151         extendRandom(r, int(n))
152 }
153
154 func goenvs() {
155         goenvs_unix()
156 }
157
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)
164         }
165         mp.gsignal = malg(gsignalSize)
166         mp.gsignal.m = mp
167 }
168
169 // Called to initialize a new m (including the bootstrap m).
170 // Called on the new thread, can not allocate memory.
171 func minit() {
172         getg().m.procid = uint64(getthrid())
173         minitSignals()
174 }
175
176 // Called from dropm to undo the effect of an minit.
177 //
178 //go:nosplit
179 func unminit() {
180         unminitSignals()
181         getg().m.procid = 0
182 }
183
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) {
187 }
188
189 func sigtramp()
190
191 type sigactiont struct {
192         sa_sigaction uintptr
193         sa_mask      uint32
194         sa_flags     int32
195 }
196
197 //go:nosplit
198 //go:nowritebarrierrec
199 func setsig(i uint32, fn uintptr) {
200         var sa sigactiont
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)
205         }
206         sa.sa_sigaction = fn
207         sigaction(i, &sa, nil)
208 }
209
210 //go:nosplit
211 //go:nowritebarrierrec
212 func setsigstack(i uint32) {
213         throw("setsigstack")
214 }
215
216 //go:nosplit
217 //go:nowritebarrierrec
218 func getsig(i uint32) uintptr {
219         var sa sigactiont
220         sigaction(i, nil, &sa)
221         return sa.sa_sigaction
222 }
223
224 // setSignalstackSP sets the ss_sp field of a stackt.
225 //
226 //go:nosplit
227 func setSignalstackSP(s *stackt, sp uintptr) {
228         s.ss_sp = sp
229 }
230
231 //go:nosplit
232 //go:nowritebarrierrec
233 func sigaddset(mask *sigset, i int) {
234         *mask |= 1 << (uint32(i) - 1)
235 }
236
237 func sigdelset(mask *sigset, i int) {
238         *mask &^= 1 << (uint32(i) - 1)
239 }
240
241 //go:nosplit
242 func (c *sigctxt) fixsigcode(sig uint32) {
243 }
244
245 func setProcessCPUProfiler(hz int32) {
246         setProcessCPUProfilerTimer(hz)
247 }
248
249 func setThreadCPUProfiler(hz int32) {
250         setThreadCPUProfilerHz(hz)
251 }
252
253 //go:nosplit
254 func validSIGPROF(mp *m, c *sigctxt) bool {
255         return true
256 }
257
258 func osStackAlloc(s *mspan) {
259         osStackRemap(s, _MAP_STACK)
260 }
261
262 func osStackFree(s *mspan) {
263         // Undo MAP_STACK.
264         osStackRemap(s, 0)
265 }
266
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")
272         }
273 }
274
275 //go:nosplit
276 func raise(sig uint32) {
277         thrkill(getthrid(), int(sig))
278 }
279
280 func signalM(mp *m, sig int) {
281         thrkill(int32(mp.procid), sig)
282 }
283
284 // sigPerThreadSyscall is only used on linux, so we assign a bogus signal
285 // number.
286 const sigPerThreadSyscall = 1 << 31
287
288 //go:nosplit
289 func runPerThreadSyscall() {
290         throw("runPerThreadSyscall only valid on linux")
291 }