blob: 24a095b9d682e80d1120c113a012cde45702d7dd [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
7import "unsafe"
8
9const (
Matthew Dempsky95ab84a2015-02-16 18:18:13 +090010 _ESRCH = 3
11 _EAGAIN = 35
12 _EWOULDBLOCK = _EAGAIN
13 _ENOTSUP = 91
Joel Singba603c32014-11-14 13:01:12 +110014
15 // From OpenBSD's sys/time.h
Matthew Dempsky95ab84a2015-02-16 18:18:13 +090016 _CLOCK_REALTIME = 0
17 _CLOCK_VIRTUAL = 1
18 _CLOCK_PROF = 2
19 _CLOCK_MONOTONIC = 3
Joel Singba603c32014-11-14 13:01:12 +110020)
21
Matthew Dempsky5324cf22015-03-01 19:13:50 -080022const (
23 sigset_none = uint32(0)
24 sigset_all = ^uint32(0)
25)
Joel Singba603c32014-11-14 13:01:12 +110026
27// From OpenBSD's <sys/sysctl.h>
28const (
Matthew Dempsky95ab84a2015-02-16 18:18:13 +090029 _CTL_HW = 6
30 _HW_NCPU = 3
Joel Singba603c32014-11-14 13:01:12 +110031)
32
33func getncpu() int32 {
Matthew Dempsky95ab84a2015-02-16 18:18:13 +090034 mib := [2]uint32{_CTL_HW, _HW_NCPU}
Joel Singba603c32014-11-14 13:01:12 +110035 out := uint32(0)
36 nout := unsafe.Sizeof(out)
37
38 // Fetch hw.ncpu via sysctl.
39 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
40 if ret >= 0 {
41 return int32(out)
42 }
43 return 1
44}
45
46//go:nosplit
47func semacreate() uintptr {
48 return 1
49}
50
51//go:nosplit
52func semasleep(ns int64) int32 {
53 _g_ := getg()
54
55 // Compute sleep deadline.
56 var tsp *timespec
57 if ns >= 0 {
58 var ts timespec
59 var nsec int32
60 ns += nanotime()
Russ Cox580cba42014-11-14 14:50:00 -050061 ts.set_sec(int64(timediv(ns, 1000000000, &nsec)))
Joel Singba603c32014-11-14 13:01:12 +110062 ts.set_nsec(nsec)
63 tsp = &ts
64 }
65
66 for {
Matthew Dempsky9f926e82015-02-23 17:05:30 +090067 v := atomicload(&_g_.m.waitsemacount)
68 if v > 0 {
69 if cas(&_g_.m.waitsemacount, v, v-1) {
70 return 0 // semaphore acquired
Joel Singba603c32014-11-14 13:01:12 +110071 }
Matthew Dempsky9f926e82015-02-23 17:05:30 +090072 continue
Joel Singba603c32014-11-14 13:01:12 +110073 }
74
Matthew Dempsky9f926e82015-02-23 17:05:30 +090075 // Sleep until woken by semawakeup or timeout; or abort if waitsemacount != 0.
76 //
77 // From OpenBSD's __thrsleep(2) manual:
78 // "The abort argument, if not NULL, points to an int that will
79 // be examined [...] immediately before blocking. If that int
80 // is non-zero then __thrsleep() will immediately return EINTR
81 // without blocking."
82 ret := thrsleep(uintptr(unsafe.Pointer(&_g_.m.waitsemacount)), _CLOCK_MONOTONIC, tsp, 0, &_g_.m.waitsemacount)
Matthew Dempsky95ab84a2015-02-16 18:18:13 +090083 if ret == _EWOULDBLOCK {
Joel Singba603c32014-11-14 13:01:12 +110084 return -1
85 }
86 }
87}
88
89//go:nosplit
90func semawakeup(mp *m) {
Matthew Dempsky9f926e82015-02-23 17:05:30 +090091 xadd(&mp.waitsemacount, 1)
Joel Singba603c32014-11-14 13:01:12 +110092 ret := thrwakeup(uintptr(unsafe.Pointer(&mp.waitsemacount)), 1)
Matthew Dempsky95ab84a2015-02-16 18:18:13 +090093 if ret != 0 && ret != _ESRCH {
Joel Singba603c32014-11-14 13:01:12 +110094 // semawakeup can be called on signal stack.
95 systemstack(func() {
96 print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
97 })
98 }
Joel Singba603c32014-11-14 13:01:12 +110099}
100
Austin Clements9e6f7aa2015-03-29 10:20:54 -0400101// May run with m.p==nil, so write barriers are not allowed.
Austin Clements392336f2015-03-26 15:50:22 -0400102//go:nowritebarrier
Joel Singba603c32014-11-14 13:01:12 +1100103func newosproc(mp *m, stk unsafe.Pointer) {
104 if false {
105 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int32(mp.tls[0]), " ostk=", &mp, "\n")
106 }
107
108 mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
109
110 param := tforkt{
111 tf_tcb: unsafe.Pointer(&mp.tls[0]),
112 tf_tid: (*int32)(unsafe.Pointer(&mp.procid)),
113 tf_stack: uintptr(stk),
114 }
115
116 oset := sigprocmask(_SIG_SETMASK, sigset_all)
117 ret := tfork(&param, unsafe.Sizeof(param), mp, mp.g0, funcPC(mstart))
118 sigprocmask(_SIG_SETMASK, oset)
119
120 if ret < 0 {
121 print("runtime: failed to create new OS thread (have ", mcount()-1, " already; errno=", -ret, ")\n")
Keith Randallb2a950b2014-12-27 20:58:00 -0800122 throw("runtime.newosproc")
Joel Singba603c32014-11-14 13:01:12 +1100123 }
124}
125
126func osinit() {
127 ncpu = getncpu()
128}
129
Joel Singba603c32014-11-14 13:01:12 +1100130var urandom_dev = []byte("/dev/urandom\x00")
131
132//go:nosplit
Keith Randall6820be22014-12-09 14:40:40 -0800133func getRandomData(r []byte) {
Joel Singba603c32014-11-14 13:01:12 +1100134 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
Keith Randall6820be22014-12-09 14:40:40 -0800135 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
David Crawshawcea272d2015-04-13 19:37:04 -0400136 closefd(fd)
Keith Randall6820be22014-12-09 14:40:40 -0800137 extendRandom(r, int(n))
Joel Singba603c32014-11-14 13:01:12 +1100138}
139
140func goenvs() {
141 goenvs_unix()
142}
143
144// Called to initialize a new m (including the bootstrap m).
145// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
146func mpreinit(mp *m) {
147 mp.gsignal = malg(32 * 1024)
148 mp.gsignal.m = mp
149}
150
Elias Naur84cfba12015-05-18 11:00:24 +0200151func msigsave(mp *m) {
Elias Naur8017ace2015-05-23 11:26:22 +0200152 smask := (*uint32)(unsafe.Pointer(&mp.sigmask))
153 if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
154 throw("insufficient storage for signal mask")
155 }
156 *smask = sigprocmask(_SIG_BLOCK, 0)
Elias Naur84cfba12015-05-18 11:00:24 +0200157}
158
Joel Singba603c32014-11-14 13:01:12 +1100159// Called to initialize a new m (including the bootstrap m).
160// Called on the new thread, can not allocate memory.
161func minit() {
162 _g_ := getg()
163
164 // m.procid is a uint64, but tfork writes an int32. Fix it up.
165 _g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid)))
166
167 // Initialize signal handling
Austin Clementsc02b8912015-05-21 14:12:29 -0400168 signalstack(&_g_.m.gsignal.stack)
Elias Naur8017ace2015-05-23 11:26:22 +0200169
170 // restore signal mask from m.sigmask and unblock essential signals
171 nmask := *(*uint32)(unsafe.Pointer(&_g_.m.sigmask))
172 for i := range sigtable {
173 if sigtable[i].flags&_SigUnblock != 0 {
174 nmask &^= 1 << (uint32(i) - 1)
175 }
176 }
177 sigprocmask(_SIG_SETMASK, nmask)
Joel Singba603c32014-11-14 13:01:12 +1100178}
179
180// Called from dropm to undo the effect of an minit.
181func unminit() {
Elias Naur8017ace2015-05-23 11:26:22 +0200182 _g_ := getg()
183 smask := *(*uint32)(unsafe.Pointer(&_g_.m.sigmask))
184 sigprocmask(_SIG_SETMASK, smask)
Austin Clementsc02b8912015-05-21 14:12:29 -0400185 signalstack(nil)
Joel Singba603c32014-11-14 13:01:12 +1100186}
187
188func memlimit() uintptr {
189 return 0
190}
191
192func sigtramp()
193
194type sigactiont struct {
195 sa_sigaction uintptr
196 sa_mask uint32
197 sa_flags int32
198}
199
200func setsig(i int32, fn uintptr, restart bool) {
201 var sa sigactiont
202 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
203 if restart {
204 sa.sa_flags |= _SA_RESTART
205 }
206 sa.sa_mask = sigset_all
207 if fn == funcPC(sighandler) {
208 fn = funcPC(sigtramp)
209 }
210 sa.sa_sigaction = fn
211 sigaction(i, &sa, nil)
212}
213
Austin Clements675eb722014-12-19 16:16:17 -0500214func setsigstack(i int32) {
Keith Randallb2a950b2014-12-27 20:58:00 -0800215 throw("setsigstack")
Austin Clements675eb722014-12-19 16:16:17 -0500216}
217
Joel Singba603c32014-11-14 13:01:12 +1100218func getsig(i int32) uintptr {
219 var sa sigactiont
220 sigaction(i, nil, &sa)
221 if sa.sa_sigaction == funcPC(sigtramp) {
222 return funcPC(sighandler)
223 }
224 return sa.sa_sigaction
225}
226
Austin Clementsc02b8912015-05-21 14:12:29 -0400227func signalstack(s *stack) {
Joel Singba603c32014-11-14 13:01:12 +1100228 var st stackt
Austin Clementsc02b8912015-05-21 14:12:29 -0400229 if s == nil {
Joel Singba603c32014-11-14 13:01:12 +1100230 st.ss_flags = _SS_DISABLE
Austin Clementsc02b8912015-05-21 14:12:29 -0400231 } else {
232 st.ss_sp = s.lo
233 st.ss_size = s.hi - s.lo
234 st.ss_flags = 0
Joel Singba603c32014-11-14 13:01:12 +1100235 }
236 sigaltstack(&st, nil)
237}
238
Elias Naur84cfba12015-05-18 11:00:24 +0200239func updatesigmask(m sigmask) {
240 sigprocmask(_SIG_SETMASK, m[0])
Joel Singba603c32014-11-14 13:01:12 +1100241}
Ian Lance Taylor872b1682015-07-21 22:34:48 -0700242
243func unblocksig(sig int32) {
244 mask := uint32(1) << (uint32(sig) - 1)
245 sigprocmask(_SIG_UNBLOCK, mask)
246}