blob: 500286ab985038801bf963dd78b5d456855d2abf [file] [log] [blame]
Joel Singba603c32014-11-14 13:01:12 +11001// 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
5package runtime
6
Michael Matloob67faca72015-11-02 14:09:24 -05007import (
Cherry Mui140cd7c2021-05-13 18:07:57 -04008 "internal/abi"
Michael Matloob67faca72015-11-02 14:09:24 -05009 "runtime/internal/atomic"
10 "unsafe"
11)
Joel Singba603c32014-11-14 13:01:12 +110012
Brad Fitzpatrick2dc68002016-05-06 08:26:37 -070013type mOS struct {
14 waitsemacount uint32
15}
16
Joel Singba603c32014-11-14 13:01:12 +110017const (
Matthew Dempsky95ab84a2015-02-16 18:18:13 +090018 _ESRCH = 3
Matthew Dempsky95ab84a2015-02-16 18:18:13 +090019 _EWOULDBLOCK = _EAGAIN
20 _ENOTSUP = 91
Joel Singba603c32014-11-14 13:01:12 +110021
22 // From OpenBSD's sys/time.h
Matthew Dempsky95ab84a2015-02-16 18:18:13 +090023 _CLOCK_REALTIME = 0
24 _CLOCK_VIRTUAL = 1
25 _CLOCK_PROF = 2
26 _CLOCK_MONOTONIC = 3
Joel Singba603c32014-11-14 13:01:12 +110027)
28
Elias Naura7383fc2015-11-17 11:41:06 +010029type sigset uint32
30
Ian Lance Taylorab552aa2016-09-23 17:54:51 -070031var sigset_all = ^sigset(0)
Joel Singba603c32014-11-14 13:01:12 +110032
33// From OpenBSD's <sys/sysctl.h>
34const (
Austin Clements955cc072018-06-29 14:56:48 -040035 _CTL_KERN = 1
36 _KERN_OSREV = 3
37
Tobias Klauserc55eeeb72019-02-08 09:25:05 +010038 _CTL_HW = 6
39 _HW_NCPU = 3
40 _HW_PAGESIZE = 7
41 _HW_NCPUONLINE = 25
Joel Singba603c32014-11-14 13:01:12 +110042)
43
Austin Clements9daa35e2018-06-29 16:09:01 -040044func sysctlInt(mib []uint32) (int32, bool) {
45 var out int32
Joel Singba603c32014-11-14 13:01:12 +110046 nout := unsafe.Sizeof(out)
Austin Clements9daa35e2018-06-29 16:09:01 -040047 ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
48 if ret < 0 {
49 return 0, false
50 }
51 return out, true
52}
Joel Singba603c32014-11-14 13:01:12 +110053
Joel Singcd54ef12022-08-05 23:39:55 +100054func sysctlUint64(mib []uint32) (uint64, bool) {
55 var out uint64
56 nout := unsafe.Sizeof(out)
57 ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
58 if ret < 0 {
59 return 0, false
60 }
61 return out, true
62}
63
64//go:linkname internal_cpu_sysctlUint64 internal/cpu.sysctlUint64
65func internal_cpu_sysctlUint64(mib []uint32) (uint64, bool) {
66 return sysctlUint64(mib)
67}
68
Austin Clements9daa35e2018-06-29 16:09:01 -040069func getncpu() int32 {
Tobias Klauserc55eeeb72019-02-08 09:25:05 +010070 // 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 {
74 return int32(n)
75 }
76 if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPU}); ok {
77 return int32(n)
Joel Singba603c32014-11-14 13:01:12 +110078 }
79 return 1
80}
81
Austin Clements276a52d2016-07-18 21:40:02 -040082func getPageSize() uintptr {
Austin Clements9daa35e2018-06-29 16:09:01 -040083 if ps, ok := sysctlInt([]uint32{_CTL_HW, _HW_PAGESIZE}); ok {
84 return uintptr(ps)
Austin Clements276a52d2016-07-18 21:40:02 -040085 }
86 return 0
87}
88
Austin Clements9daa35e2018-06-29 16:09:01 -040089func getOSRev() int {
90 if osrev, ok := sysctlInt([]uint32{_CTL_KERN, _KERN_OSREV}); ok {
91 return int(osrev)
Austin Clements955cc072018-06-29 14:56:48 -040092 }
93 return 0
94}
95
Joel Singba603c32014-11-14 13:01:12 +110096//go:nosplit
Matthew Dempskyec9aae72015-10-21 18:36:05 -070097func semacreate(mp *m) {
Joel Singba603c32014-11-14 13:01:12 +110098}
99
100//go:nosplit
101func semasleep(ns int64) int32 {
Michael Pratt5999a282022-07-20 11:43:30 -0400102 gp := getg()
Joel Singba603c32014-11-14 13:01:12 +1100103
104 // Compute sleep deadline.
105 var tsp *timespec
106 if ns >= 0 {
107 var ts timespec
Ian Lance Taylor0a7bc8f2019-03-13 18:56:37 -0700108 ts.setNsec(ns + nanotime())
Joel Singba603c32014-11-14 13:01:12 +1100109 tsp = &ts
110 }
111
112 for {
Michael Pratt5999a282022-07-20 11:43:30 -0400113 v := atomic.Load(&gp.m.waitsemacount)
Matthew Dempsky9f926e82015-02-23 17:05:30 +0900114 if v > 0 {
Michael Pratt5999a282022-07-20 11:43:30 -0400115 if atomic.Cas(&gp.m.waitsemacount, v, v-1) {
Matthew Dempsky9f926e82015-02-23 17:05:30 +0900116 return 0 // semaphore acquired
Joel Singba603c32014-11-14 13:01:12 +1100117 }
Matthew Dempsky9f926e82015-02-23 17:05:30 +0900118 continue
Joel Singba603c32014-11-14 13:01:12 +1100119 }
120
Matthew Dempsky9f926e82015-02-23 17:05:30 +0900121 // Sleep until woken by semawakeup or timeout; or abort if waitsemacount != 0.
122 //
123 // From OpenBSD's __thrsleep(2) manual:
124 // "The abort argument, if not NULL, points to an int that will
Brad Fitzpatrick5fea2cc2016-03-01 23:21:55 +0000125 // be examined [...] immediately before blocking. If that int
Matthew Dempsky9f926e82015-02-23 17:05:30 +0900126 // is non-zero then __thrsleep() will immediately return EINTR
127 // without blocking."
Michael Pratt5999a282022-07-20 11:43:30 -0400128 ret := thrsleep(uintptr(unsafe.Pointer(&gp.m.waitsemacount)), _CLOCK_MONOTONIC, tsp, 0, &gp.m.waitsemacount)
Matthew Dempsky95ab84a2015-02-16 18:18:13 +0900129 if ret == _EWOULDBLOCK {
Joel Singba603c32014-11-14 13:01:12 +1100130 return -1
131 }
132 }
133}
134
135//go:nosplit
136func semawakeup(mp *m) {
Michael Matloob67faca72015-11-02 14:09:24 -0500137 atomic.Xadd(&mp.waitsemacount, 1)
Joel Singba603c32014-11-14 13:01:12 +1100138 ret := thrwakeup(uintptr(unsafe.Pointer(&mp.waitsemacount)), 1)
Matthew Dempsky95ab84a2015-02-16 18:18:13 +0900139 if ret != 0 && ret != _ESRCH {
Joel Singba603c32014-11-14 13:01:12 +1100140 // semawakeup can be called on signal stack.
141 systemstack(func() {
142 print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
143 })
144 }
Joel Singba603c32014-11-14 13:01:12 +1100145}
146
Joel Singba603c32014-11-14 13:01:12 +1100147func osinit() {
148 ncpu = getncpu()
Austin Clements276a52d2016-07-18 21:40:02 -0400149 physPageSize = getPageSize()
Austin Clements955cc072018-06-29 14:56:48 -0400150 haveMapStack = getOSRev() >= 201805 // OpenBSD 6.3
Joel Singba603c32014-11-14 13:01:12 +1100151}
152
Joel Singba603c32014-11-14 13:01:12 +1100153var urandom_dev = []byte("/dev/urandom\x00")
154
155//go:nosplit
Keith Randall6820be22014-12-09 14:40:40 -0800156func getRandomData(r []byte) {
Joel Singba603c32014-11-14 13:01:12 +1100157 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
Keith Randall6820be22014-12-09 14:40:40 -0800158 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
David Crawshawcea272d2015-04-13 19:37:04 -0400159 closefd(fd)
Keith Randall6820be22014-12-09 14:40:40 -0800160 extendRandom(r, int(n))
Joel Singba603c32014-11-14 13:01:12 +1100161}
162
163func goenvs() {
164 goenvs_unix()
165}
166
167// Called to initialize a new m (including the bootstrap m).
168// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
169func mpreinit(mp *m) {
Joel Sing55f8d562020-08-25 18:04:47 +1000170 gsignalSize := int32(32 * 1024)
171 if GOARCH == "mips64" {
172 gsignalSize = int32(64 * 1024)
173 }
174 mp.gsignal = malg(gsignalSize)
Joel Singba603c32014-11-14 13:01:12 +1100175 mp.gsignal.m = mp
176}
177
178// Called to initialize a new m (including the bootstrap m).
179// Called on the new thread, can not allocate memory.
180func minit() {
Austin Clements8714e392019-10-14 17:05:56 -0400181 getg().m.procid = uint64(getthrid())
Ian Lance Taylorac243882016-09-26 11:14:41 -0700182 minitSignals()
Joel Singba603c32014-11-14 13:01:12 +1100183}
184
185// Called from dropm to undo the effect of an minit.
Russ Cox98396682022-01-30 20:13:43 -0500186//
Russ Coxf8e64182015-11-13 16:21:01 -0500187//go:nosplit
Joel Singba603c32014-11-14 13:01:12 +1100188func unminit() {
Ian Lance Taylore2e11f02016-09-26 11:35:55 -0700189 unminitSignals()
Joel Singba603c32014-11-14 13:01:12 +1100190}
191
Jason A. Donenfelddbab0792021-01-15 13:01:37 +0100192// 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.
194func mdestroy(mp *m) {
195}
196
Joel Singba603c32014-11-14 13:01:12 +1100197func sigtramp()
198
199type sigactiont struct {
200 sa_sigaction uintptr
201 sa_mask uint32
202 sa_flags int32
203}
204
Ian Lance Taylor21b4f232015-12-26 09:51:59 -0800205//go:nosplit
206//go:nowritebarrierrec
Ian Lance Tayloreb268cb2016-09-27 22:24:51 -0700207func setsig(i uint32, fn uintptr) {
Joel Singba603c32014-11-14 13:01:12 +1100208 var sa sigactiont
Ian Lance Tayloreb268cb2016-09-27 22:24:51 -0700209 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
Elias Naura7383fc2015-11-17 11:41:06 +0100210 sa.sa_mask = uint32(sigset_all)
Cherry Mui626e89c2021-05-21 13:37:19 -0400211 if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go
Cherry Mui140cd7c2021-05-13 18:07:57 -0400212 fn = abi.FuncPCABI0(sigtramp)
Joel Singba603c32014-11-14 13:01:12 +1100213 }
214 sa.sa_sigaction = fn
215 sigaction(i, &sa, nil)
216}
217
Ian Lance Taylor21b4f232015-12-26 09:51:59 -0800218//go:nosplit
219//go:nowritebarrierrec
Ian Lance Tayloreb268cb2016-09-27 22:24:51 -0700220func setsigstack(i uint32) {
Keith Randallb2a950b2014-12-27 20:58:00 -0800221 throw("setsigstack")
Austin Clements675eb722014-12-19 16:16:17 -0500222}
223
Ian Lance Taylor21b4f232015-12-26 09:51:59 -0800224//go:nosplit
225//go:nowritebarrierrec
Ian Lance Tayloreb268cb2016-09-27 22:24:51 -0700226func getsig(i uint32) uintptr {
Joel Singba603c32014-11-14 13:01:12 +1100227 var sa sigactiont
228 sigaction(i, nil, &sa)
Joel Singba603c32014-11-14 13:01:12 +1100229 return sa.sa_sigaction
230}
231
cui fliter069d1fc2022-10-03 01:32:11 +0000232// setSignalstackSP sets the ss_sp field of a stackt.
Russ Cox98396682022-01-30 20:13:43 -0500233//
Russ Coxf8e64182015-11-13 16:21:01 -0500234//go:nosplit
Ian Lance Taylord15295c2016-09-25 13:38:54 -0700235func setSignalstackSP(s *stackt, sp uintptr) {
236 s.ss_sp = sp
Joel Singba603c32014-11-14 13:01:12 +1100237}
238
Ian Lance Taylor21b4f232015-12-26 09:51:59 -0800239//go:nosplit
240//go:nowritebarrierrec
Ian Lance Taylorfdc16712016-09-27 13:42:28 -0700241func sigaddset(mask *sigset, i int) {
242 *mask |= 1 << (uint32(i) - 1)
Ian Lance Taylor872b1682015-07-21 22:34:48 -0700243}
Ian Lance Taylorc2735032016-09-25 21:33:27 -0700244
Ian Lance Taylorac243882016-09-26 11:14:41 -0700245func sigdelset(mask *sigset, i int) {
246 *mask &^= 1 << (uint32(i) - 1)
247}
248
Clément Chigot3aacfce2019-03-25 10:34:57 +0100249//go:nosplit
Ian Lance Taylorc2735032016-09-25 21:33:27 -0700250func (c *sigctxt) fixsigcode(sig uint32) {
251}
Austin Clements955cc072018-06-29 14:56:48 -0400252
Rhys Hiltnerf9e90f72021-08-13 08:51:46 -0700253func setProcessCPUProfiler(hz int32) {
254 setProcessCPUProfilerTimer(hz)
255}
256
257func setThreadCPUProfiler(hz int32) {
258 setThreadCPUProfilerHz(hz)
259}
260
261//go:nosplit
262func validSIGPROF(mp *m, c *sigctxt) bool {
263 return true
264}
265
Austin Clements955cc072018-06-29 14:56:48 -0400266var haveMapStack = false
267
268func osStackAlloc(s *mspan) {
269 // OpenBSD 6.4+ requires that stacks be mapped with MAP_STACK.
270 // It will check this on entry to system calls, traps, and
271 // when switching to the alternate system stack.
272 //
273 // This function is called before s is used for any data, so
274 // it's safe to simply re-map it.
275 osStackRemap(s, _MAP_STACK)
276}
277
278func osStackFree(s *mspan) {
279 // Undo MAP_STACK.
280 osStackRemap(s, 0)
281}
282
283func osStackRemap(s *mspan, flags int32) {
284 if !haveMapStack {
285 // OpenBSD prior to 6.3 did not have MAP_STACK and so
286 // the following mmap will fail. But it also didn't
287 // require MAP_STACK (obviously), so there's no need
288 // to do the mmap.
289 return
290 }
291 a, err := mmap(unsafe.Pointer(s.base()), s.npages*pageSize, _PROT_READ|_PROT_WRITE, _MAP_PRIVATE|_MAP_ANON|_MAP_FIXED|flags, -1, 0)
292 if err != 0 || uintptr(a) != s.base() {
293 print("runtime: remapping stack memory ", hex(s.base()), " ", s.npages*pageSize, " a=", a, " err=", err, "\n")
294 throw("remapping stack memory failed")
295 }
296}
Austin Clements8714e392019-10-14 17:05:56 -0400297
Ian Lance Taylor96990862020-07-06 14:23:26 -0700298//go:nosplit
Austin Clements8714e392019-10-14 17:05:56 -0400299func raise(sig uint32) {
300 thrkill(getthrid(), int(sig))
301}
302
303func signalM(mp *m, sig int) {
304 thrkill(int32(mp.procid), sig)
305}
Michael Pratt0a5fae22022-02-04 17:15:28 -0500306
307// sigPerThreadSyscall is only used on linux, so we assign a bogus signal
308// number.
309const sigPerThreadSyscall = 1 << 31
310
311//go:nosplit
312func runPerThreadSyscall() {
313 throw("runPerThreadSyscall only valid on linux")
314}