github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/runtime/os1_netbsd.go (about) 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 "unsafe" 8 9 const ( 10 _ESRCH = 3 11 _ETIMEDOUT = 60 12 13 // From NetBSD's <sys/time.h> 14 _CLOCK_REALTIME = 0 15 _CLOCK_VIRTUAL = 1 16 _CLOCK_PROF = 2 17 _CLOCK_MONOTONIC = 3 18 ) 19 20 var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}} 21 22 // From NetBSD's <sys/sysctl.h> 23 const ( 24 _CTL_HW = 6 25 _HW_NCPU = 3 26 ) 27 28 func getncpu() int32 { 29 mib := [2]uint32{_CTL_HW, _HW_NCPU} 30 out := uint32(0) 31 nout := unsafe.Sizeof(out) 32 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) 33 if ret >= 0 { 34 return int32(out) 35 } 36 return 1 37 } 38 39 //go:nosplit 40 func semacreate() uintptr { 41 return 1 42 } 43 44 //go:nosplit 45 func semasleep(ns int64) int32 { 46 _g_ := getg() 47 48 // Compute sleep deadline. 49 var tsp *timespec 50 if ns >= 0 { 51 var ts timespec 52 var nsec int32 53 ns += nanotime() 54 ts.set_sec(timediv(ns, 1000000000, &nsec)) 55 ts.set_nsec(nsec) 56 tsp = &ts 57 } 58 59 for { 60 v := atomicload(&_g_.m.waitsemacount) 61 if v > 0 { 62 if cas(&_g_.m.waitsemacount, v, v-1) { 63 return 0 // semaphore acquired 64 } 65 continue 66 } 67 68 // Sleep until unparked by semawakeup or timeout. 69 ret := lwp_park(tsp, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil) 70 if ret == _ETIMEDOUT { 71 return -1 72 } 73 } 74 } 75 76 //go:nosplit 77 func semawakeup(mp *m) { 78 xadd(&mp.waitsemacount, 1) 79 // From NetBSD's _lwp_unpark(2) manual: 80 // "If the target LWP is not currently waiting, it will return 81 // immediately upon the next call to _lwp_park()." 82 ret := lwp_unpark(int32(mp.procid), unsafe.Pointer(&mp.waitsemacount)) 83 if ret != 0 && ret != _ESRCH { 84 // semawakeup can be called on signal stack. 85 systemstack(func() { 86 print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n") 87 }) 88 } 89 } 90 91 // May run with m.p==nil, so write barriers are not allowed. 92 //go:nowritebarrier 93 func newosproc(mp *m, stk unsafe.Pointer) { 94 if false { 95 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int32(mp.tls[0]), " ostk=", &mp, "\n") 96 } 97 98 mp.tls[0] = uintptr(mp.id) // so 386 asm can find it 99 100 var uc ucontextt 101 getcontext(unsafe.Pointer(&uc)) 102 103 uc.uc_flags = _UC_SIGMASK | _UC_CPU 104 uc.uc_link = nil 105 uc.uc_sigmask = sigset_all 106 107 lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp.g0, funcPC(mstart)) 108 109 ret := lwp_create(unsafe.Pointer(&uc), 0, unsafe.Pointer(&mp.procid)) 110 if ret < 0 { 111 print("runtime: failed to create new OS thread (have ", mcount()-1, " already; errno=", -ret, ")\n") 112 throw("runtime.newosproc") 113 } 114 } 115 116 func osinit() { 117 ncpu = getncpu() 118 } 119 120 var urandom_dev = []byte("/dev/urandom\x00") 121 122 //go:nosplit 123 func getRandomData(r []byte) { 124 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 125 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 126 closefd(fd) 127 extendRandom(r, int(n)) 128 } 129 130 func goenvs() { 131 goenvs_unix() 132 } 133 134 // Called to initialize a new m (including the bootstrap m). 135 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 136 func mpreinit(mp *m) { 137 mp.gsignal = malg(32 * 1024) 138 mp.gsignal.m = mp 139 } 140 141 func msigsave(mp *m) { 142 smask := (*sigset)(unsafe.Pointer(&mp.sigmask)) 143 if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) { 144 throw("insufficient storage for signal mask") 145 } 146 sigprocmask(_SIG_SETMASK, nil, smask) 147 } 148 149 // Called to initialize a new m (including the bootstrap m). 150 // Called on the new thread, can not allocate memory. 151 func minit() { 152 _g_ := getg() 153 _g_.m.procid = uint64(lwp_self()) 154 155 // Initialize signal handling 156 signalstack(&_g_.m.gsignal.stack) 157 158 // restore signal mask from m.sigmask and unblock essential signals 159 nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask)) 160 for i := range sigtable { 161 if sigtable[i].flags&_SigUnblock != 0 { 162 nmask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31) 163 } 164 } 165 sigprocmask(_SIG_SETMASK, &nmask, nil) 166 } 167 168 // Called from dropm to undo the effect of an minit. 169 func unminit() { 170 _g_ := getg() 171 smask := (*sigset)(unsafe.Pointer(&_g_.m.sigmask)) 172 sigprocmask(_SIG_SETMASK, smask, nil) 173 174 signalstack(nil) 175 } 176 177 func memlimit() uintptr { 178 return 0 179 } 180 181 func sigtramp() 182 183 type sigactiont struct { 184 sa_sigaction uintptr 185 sa_mask sigset 186 sa_flags int32 187 } 188 189 func setsig(i int32, fn uintptr, restart bool) { 190 var sa sigactiont 191 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK 192 if restart { 193 sa.sa_flags |= _SA_RESTART 194 } 195 sa.sa_mask = sigset_all 196 if fn == funcPC(sighandler) { 197 fn = funcPC(sigtramp) 198 } 199 sa.sa_sigaction = fn 200 sigaction(i, &sa, nil) 201 } 202 203 func setsigstack(i int32) { 204 throw("setsigstack") 205 } 206 207 func getsig(i int32) uintptr { 208 var sa sigactiont 209 sigaction(i, nil, &sa) 210 if sa.sa_sigaction == funcPC(sigtramp) { 211 return funcPC(sighandler) 212 } 213 return sa.sa_sigaction 214 } 215 216 func signalstack(s *stack) { 217 var st sigaltstackt 218 if s == nil { 219 st.ss_flags = _SS_DISABLE 220 } else { 221 st.ss_sp = s.lo 222 st.ss_size = s.hi - s.lo 223 st.ss_flags = 0 224 } 225 sigaltstack(&st, nil) 226 } 227 228 func updatesigmask(m sigmask) { 229 var mask sigset 230 copy(mask.__bits[:], m[:]) 231 sigprocmask(_SIG_SETMASK, &mask, nil) 232 } 233 234 func unblocksig(sig int32) { 235 var mask sigset 236 mask.__bits[(sig-1)/32] |= 1 << ((uint32(sig) - 1) & 31) 237 sigprocmask(_SIG_UNBLOCK, &mask, nil) 238 }