Source file
src/runtime/os_netbsd.go
1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "internal/goarch"
10 "runtime/internal/atomic"
11 "unsafe"
12 )
13
14 const (
15 _SS_DISABLE = 4
16 _SIG_BLOCK = 1
17 _SIG_UNBLOCK = 2
18 _SIG_SETMASK = 3
19 _NSIG = 33
20 _SI_USER = 0
21
22
23 _UC_SIGMASK = 0x01
24 _UC_CPU = 0x04
25
26
27 _LWP_DETACHED = 0x00000040
28 )
29
30 type mOS struct {
31 waitsemacount uint32
32 }
33
34
35 func setitimer(mode int32, new, old *itimerval)
36
37
38 func sigaction(sig uint32, new, old *sigactiont)
39
40
41 func sigaltstack(new, old *stackt)
42
43
44 func sigprocmask(how int32, new, old *sigset)
45
46
47 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
48
49 func lwp_tramp()
50
51 func raiseproc(sig uint32)
52
53 func lwp_kill(tid int32, sig int)
54
55
56 func getcontext(ctxt unsafe.Pointer)
57
58
59 func lwp_create(ctxt unsafe.Pointer, flags uintptr, lwpid unsafe.Pointer) int32
60
61
62 func lwp_park(clockid, flags int32, ts *timespec, unpark int32, hint, unparkhint unsafe.Pointer) int32
63
64
65 func lwp_unpark(lwp int32, hint unsafe.Pointer) int32
66
67 func lwp_self() int32
68
69 func osyield()
70
71
72 func osyield_no_g() {
73 osyield()
74 }
75
76 func kqueue() int32
77
78
79 func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
80
81 func pipe2(flags int32) (r, w int32, errno int32)
82 func closeonexec(fd int32)
83
84 const (
85 _ESRCH = 3
86 _ETIMEDOUT = 60
87
88
89 _CLOCK_REALTIME = 0
90 _CLOCK_VIRTUAL = 1
91 _CLOCK_PROF = 2
92 _CLOCK_MONOTONIC = 3
93
94 _TIMER_RELTIME = 0
95 _TIMER_ABSTIME = 1
96 )
97
98 var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
99
100
101 const (
102 _CTL_KERN = 1
103 _KERN_OSREV = 3
104
105 _CTL_HW = 6
106 _HW_NCPU = 3
107 _HW_PAGESIZE = 7
108 _HW_NCPUONLINE = 16
109 )
110
111 func sysctlInt(mib []uint32) (int32, bool) {
112 var out int32
113 nout := unsafe.Sizeof(out)
114 ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
115 if ret < 0 {
116 return 0, false
117 }
118 return out, true
119 }
120
121 func getncpu() int32 {
122 if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPUONLINE}); ok {
123 return int32(n)
124 }
125 if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPU}); ok {
126 return int32(n)
127 }
128 return 1
129 }
130
131 func getPageSize() uintptr {
132 mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
133 out := uint32(0)
134 nout := unsafe.Sizeof(out)
135 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
136 if ret >= 0 {
137 return uintptr(out)
138 }
139 return 0
140 }
141
142 func getOSRev() int {
143 if osrev, ok := sysctlInt([]uint32{_CTL_KERN, _KERN_OSREV}); ok {
144 return int(osrev)
145 }
146 return 0
147 }
148
149
150 func semacreate(mp *m) {
151 }
152
153
154 func semasleep(ns int64) int32 {
155 _g_ := getg()
156 var deadline int64
157 if ns >= 0 {
158 deadline = nanotime() + ns
159 }
160
161 for {
162 v := atomic.Load(&_g_.m.waitsemacount)
163 if v > 0 {
164 if atomic.Cas(&_g_.m.waitsemacount, v, v-1) {
165 return 0
166 }
167 continue
168 }
169
170
171 var tsp *timespec
172 var ts timespec
173 if ns >= 0 {
174 wait := deadline - nanotime()
175 if wait <= 0 {
176 return -1
177 }
178 ts.setNsec(wait)
179 tsp = &ts
180 }
181 ret := lwp_park(_CLOCK_MONOTONIC, _TIMER_RELTIME, tsp, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil)
182 if ret == _ETIMEDOUT {
183 return -1
184 }
185 }
186 }
187
188
189 func semawakeup(mp *m) {
190 atomic.Xadd(&mp.waitsemacount, 1)
191
192
193
194 ret := lwp_unpark(int32(mp.procid), unsafe.Pointer(&mp.waitsemacount))
195 if ret != 0 && ret != _ESRCH {
196
197 systemstack(func() {
198 print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
199 })
200 }
201 }
202
203
204
205
206 func newosproc(mp *m) {
207 stk := unsafe.Pointer(mp.g0.stack.hi)
208 if false {
209 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
210 }
211
212 var uc ucontextt
213 getcontext(unsafe.Pointer(&uc))
214
215
216
217
218
219
220
221 uc.uc_flags = _UC_SIGMASK | _UC_CPU
222 uc.uc_link = nil
223 uc.uc_sigmask = sigset_all
224
225 var oset sigset
226 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
227
228 lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp.g0, abi.FuncPCABI0(netbsdMstart))
229
230 ret := lwp_create(unsafe.Pointer(&uc), _LWP_DETACHED, unsafe.Pointer(&mp.procid))
231 sigprocmask(_SIG_SETMASK, &oset, nil)
232 if ret < 0 {
233 print("runtime: failed to create new OS thread (have ", mcount()-1, " already; errno=", -ret, ")\n")
234 if ret == -_EAGAIN {
235 println("runtime: may need to increase max user processes (ulimit -p)")
236 }
237 throw("runtime.newosproc")
238 }
239 }
240
241
242
243 func netbsdMstart()
244
245
246
247
248
249
250
251
252
253
254 func netbsdMstart0() {
255 st := stackt{ss_flags: _SS_DISABLE}
256 sigaltstack(&st, nil)
257 mstart0()
258 }
259
260 func osinit() {
261 ncpu = getncpu()
262 if physPageSize == 0 {
263 physPageSize = getPageSize()
264 }
265 needSysmonWorkaround = getOSRev() < 902000000
266 }
267
268 var urandom_dev = []byte("/dev/urandom\x00")
269
270
271 func getRandomData(r []byte) {
272 fd := open(&urandom_dev[0], 0 , 0)
273 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
274 closefd(fd)
275 extendRandom(r, int(n))
276 }
277
278 func goenvs() {
279 goenvs_unix()
280 }
281
282
283
284 func mpreinit(mp *m) {
285 mp.gsignal = malg(32 * 1024)
286 mp.gsignal.m = mp
287 }
288
289
290
291 func minit() {
292 _g_ := getg()
293 _g_.m.procid = uint64(lwp_self())
294
295
296
297
298
299
300
301
302 signalstack(&_g_.m.gsignal.stack)
303 _g_.m.newSigstack = true
304
305 minitSignalMask()
306 }
307
308
309
310
311 func unminit() {
312 unminitSignals()
313 }
314
315
316
317 func mdestroy(mp *m) {
318 }
319
320 func sigtramp()
321
322 type sigactiont struct {
323 sa_sigaction uintptr
324 sa_mask sigset
325 sa_flags int32
326 }
327
328
329
330 func setsig(i uint32, fn uintptr) {
331 var sa sigactiont
332 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
333 sa.sa_mask = sigset_all
334 if fn == abi.FuncPCABIInternal(sighandler) {
335 fn = abi.FuncPCABI0(sigtramp)
336 }
337 sa.sa_sigaction = fn
338 sigaction(i, &sa, nil)
339 }
340
341
342
343 func setsigstack(i uint32) {
344 throw("setsigstack")
345 }
346
347
348
349 func getsig(i uint32) uintptr {
350 var sa sigactiont
351 sigaction(i, nil, &sa)
352 return sa.sa_sigaction
353 }
354
355
356
357
358 func setSignalstackSP(s *stackt, sp uintptr) {
359 s.ss_sp = sp
360 }
361
362
363
364 func sigaddset(mask *sigset, i int) {
365 mask.__bits[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31)
366 }
367
368 func sigdelset(mask *sigset, i int) {
369 mask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
370 }
371
372
373 func (c *sigctxt) fixsigcode(sig uint32) {
374 }
375
376 func setProcessCPUProfiler(hz int32) {
377 setProcessCPUProfilerTimer(hz)
378 }
379
380 func setThreadCPUProfiler(hz int32) {
381 setThreadCPUProfilerHz(hz)
382 }
383
384
385 func validSIGPROF(mp *m, c *sigctxt) bool {
386 return true
387 }
388
389 func sysargs(argc int32, argv **byte) {
390 n := argc + 1
391
392
393 for argv_index(argv, n) != nil {
394 n++
395 }
396
397
398 n++
399
400
401 auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize))
402 sysauxv(auxv[:])
403 }
404
405 const (
406 _AT_NULL = 0
407 _AT_PAGESZ = 6
408 )
409
410 func sysauxv(auxv []uintptr) {
411 for i := 0; auxv[i] != _AT_NULL; i += 2 {
412 tag, val := auxv[i], auxv[i+1]
413 switch tag {
414 case _AT_PAGESZ:
415 physPageSize = val
416 }
417 }
418 }
419
420
421
422
423
424
425
426 func raise(sig uint32) {
427 lwp_kill(lwp_self(), int(sig))
428 }
429
430 func signalM(mp *m, sig int) {
431 lwp_kill(int32(mp.procid), sig)
432 }
433
434
435
436 const sigPerThreadSyscall = 1 << 31
437
438
439 func runPerThreadSyscall() {
440 throw("runPerThreadSyscall only valid on linux")
441 }
442
View as plain text