github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/runtime/os_openbsd.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 ( 8 "runtime/internal/atomic" 9 "runtime/internal/sys" 10 "unsafe" 11 ) 12 13 type mOS struct { 14 waitsemacount uint32 15 } 16 17 //go:noescape 18 func setitimer(mode int32, new, old *itimerval) 19 20 //go:noescape 21 func sigaction(sig uint32, new, old *sigactiont) 22 23 //go:noescape 24 func sigaltstack(new, old *stackt) 25 26 //go:noescape 27 func obsdsigprocmask(how int32, new sigset) sigset 28 29 //go:nosplit 30 //go:nowritebarrierrec 31 func sigprocmask(how int32, new, old *sigset) { 32 n := sigset(0) 33 if new != nil { 34 n = *new 35 } 36 r := obsdsigprocmask(how, n) 37 if old != nil { 38 *old = r 39 } 40 } 41 42 //go:noescape 43 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 44 45 func raise(sig uint32) 46 func raiseproc(sig uint32) 47 48 //go:noescape 49 func tfork(param *tforkt, psize uintptr, mm *m, gg *g, fn uintptr) int32 50 51 //go:noescape 52 func thrsleep(ident uintptr, clock_id int32, tsp *timespec, lock uintptr, abort *uint32) int32 53 54 //go:noescape 55 func thrwakeup(ident uintptr, n int32) int32 56 57 func osyield() 58 59 func kqueue() int32 60 61 //go:noescape 62 func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32 63 func closeonexec(fd int32) 64 65 const ( 66 _ESRCH = 3 67 _EAGAIN = 35 68 _EWOULDBLOCK = _EAGAIN 69 _ENOTSUP = 91 70 71 // From OpenBSD's sys/time.h 72 _CLOCK_REALTIME = 0 73 _CLOCK_VIRTUAL = 1 74 _CLOCK_PROF = 2 75 _CLOCK_MONOTONIC = 3 76 ) 77 78 type sigset uint32 79 80 var sigset_all = ^sigset(0) 81 82 // From OpenBSD's <sys/sysctl.h> 83 const ( 84 _CTL_KERN = 1 85 _KERN_OSREV = 3 86 87 _CTL_HW = 6 88 _HW_NCPU = 3 89 _HW_PAGESIZE = 7 90 ) 91 92 func sysctlInt(mib []uint32) (int32, bool) { 93 var out int32 94 nout := unsafe.Sizeof(out) 95 ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) 96 if ret < 0 { 97 return 0, false 98 } 99 return out, true 100 } 101 102 func getncpu() int32 { 103 // Fetch hw.ncpu via sysctl. 104 if ncpu, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPU}); ok { 105 return int32(ncpu) 106 } 107 return 1 108 } 109 110 func getPageSize() uintptr { 111 if ps, ok := sysctlInt([]uint32{_CTL_HW, _HW_PAGESIZE}); ok { 112 return uintptr(ps) 113 } 114 return 0 115 } 116 117 func getOSRev() int { 118 if osrev, ok := sysctlInt([]uint32{_CTL_KERN, _KERN_OSREV}); ok { 119 return int(osrev) 120 } 121 return 0 122 } 123 124 //go:nosplit 125 func semacreate(mp *m) { 126 } 127 128 //go:nosplit 129 func semasleep(ns int64) int32 { 130 _g_ := getg() 131 132 // Compute sleep deadline. 133 var tsp *timespec 134 if ns >= 0 { 135 var ts timespec 136 var nsec int32 137 ns += nanotime() 138 ts.set_sec(int64(timediv(ns, 1000000000, &nsec))) 139 ts.set_nsec(nsec) 140 tsp = &ts 141 } 142 143 for { 144 v := atomic.Load(&_g_.m.waitsemacount) 145 if v > 0 { 146 if atomic.Cas(&_g_.m.waitsemacount, v, v-1) { 147 return 0 // semaphore acquired 148 } 149 continue 150 } 151 152 // Sleep until woken by semawakeup or timeout; or abort if waitsemacount != 0. 153 // 154 // From OpenBSD's __thrsleep(2) manual: 155 // "The abort argument, if not NULL, points to an int that will 156 // be examined [...] immediately before blocking. If that int 157 // is non-zero then __thrsleep() will immediately return EINTR 158 // without blocking." 159 ret := thrsleep(uintptr(unsafe.Pointer(&_g_.m.waitsemacount)), _CLOCK_MONOTONIC, tsp, 0, &_g_.m.waitsemacount) 160 if ret == _EWOULDBLOCK { 161 return -1 162 } 163 } 164 } 165 166 //go:nosplit 167 func semawakeup(mp *m) { 168 atomic.Xadd(&mp.waitsemacount, 1) 169 ret := thrwakeup(uintptr(unsafe.Pointer(&mp.waitsemacount)), 1) 170 if ret != 0 && ret != _ESRCH { 171 // semawakeup can be called on signal stack. 172 systemstack(func() { 173 print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n") 174 }) 175 } 176 } 177 178 // May run with m.p==nil, so write barriers are not allowed. 179 //go:nowritebarrier 180 func newosproc(mp *m) { 181 stk := unsafe.Pointer(mp.g0.stack.hi) 182 if false { 183 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n") 184 } 185 186 // Stack pointer must point inside stack area (as marked with MAP_STACK), 187 // rather than at the top of it. 188 param := tforkt{ 189 tf_tcb: unsafe.Pointer(&mp.tls[0]), 190 tf_tid: (*int32)(unsafe.Pointer(&mp.procid)), 191 tf_stack: uintptr(stk) - sys.PtrSize, 192 } 193 194 var oset sigset 195 sigprocmask(_SIG_SETMASK, &sigset_all, &oset) 196 ret := tfork(¶m, unsafe.Sizeof(param), mp, mp.g0, funcPC(mstart)) 197 sigprocmask(_SIG_SETMASK, &oset, nil) 198 199 if ret < 0 { 200 print("runtime: failed to create new OS thread (have ", mcount()-1, " already; errno=", -ret, ")\n") 201 if ret == -_EAGAIN { 202 println("runtime: may need to increase max user processes (ulimit -p)") 203 } 204 throw("runtime.newosproc") 205 } 206 } 207 208 func osinit() { 209 ncpu = getncpu() 210 physPageSize = getPageSize() 211 haveMapStack = getOSRev() >= 201805 // OpenBSD 6.3 212 } 213 214 var urandom_dev = []byte("/dev/urandom\x00") 215 216 //go:nosplit 217 func getRandomData(r []byte) { 218 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 219 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 220 closefd(fd) 221 extendRandom(r, int(n)) 222 } 223 224 func goenvs() { 225 goenvs_unix() 226 } 227 228 // Called to initialize a new m (including the bootstrap m). 229 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 230 func mpreinit(mp *m) { 231 mp.gsignal = malg(32 * 1024) 232 mp.gsignal.m = mp 233 } 234 235 // Called to initialize a new m (including the bootstrap m). 236 // Called on the new thread, can not allocate memory. 237 func minit() { 238 // m.procid is a uint64, but tfork writes an int32. Fix it up. 239 _g_ := getg() 240 _g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid))) 241 242 minitSignals() 243 } 244 245 // Called from dropm to undo the effect of an minit. 246 //go:nosplit 247 func unminit() { 248 unminitSignals() 249 } 250 251 func sigtramp() 252 253 type sigactiont struct { 254 sa_sigaction uintptr 255 sa_mask uint32 256 sa_flags int32 257 } 258 259 //go:nosplit 260 //go:nowritebarrierrec 261 func setsig(i uint32, fn uintptr) { 262 var sa sigactiont 263 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART 264 sa.sa_mask = uint32(sigset_all) 265 if fn == funcPC(sighandler) { 266 fn = funcPC(sigtramp) 267 } 268 sa.sa_sigaction = fn 269 sigaction(i, &sa, nil) 270 } 271 272 //go:nosplit 273 //go:nowritebarrierrec 274 func setsigstack(i uint32) { 275 throw("setsigstack") 276 } 277 278 //go:nosplit 279 //go:nowritebarrierrec 280 func getsig(i uint32) uintptr { 281 var sa sigactiont 282 sigaction(i, nil, &sa) 283 return sa.sa_sigaction 284 } 285 286 // setSignaltstackSP sets the ss_sp field of a stackt. 287 //go:nosplit 288 func setSignalstackSP(s *stackt, sp uintptr) { 289 s.ss_sp = sp 290 } 291 292 //go:nosplit 293 //go:nowritebarrierrec 294 func sigaddset(mask *sigset, i int) { 295 *mask |= 1 << (uint32(i) - 1) 296 } 297 298 func sigdelset(mask *sigset, i int) { 299 *mask &^= 1 << (uint32(i) - 1) 300 } 301 302 func (c *sigctxt) fixsigcode(sig uint32) { 303 } 304 305 var haveMapStack = false 306 307 func osStackAlloc(s *mspan) { 308 // OpenBSD 6.4+ requires that stacks be mapped with MAP_STACK. 309 // It will check this on entry to system calls, traps, and 310 // when switching to the alternate system stack. 311 // 312 // This function is called before s is used for any data, so 313 // it's safe to simply re-map it. 314 osStackRemap(s, _MAP_STACK) 315 } 316 317 func osStackFree(s *mspan) { 318 // Undo MAP_STACK. 319 osStackRemap(s, 0) 320 } 321 322 func osStackRemap(s *mspan, flags int32) { 323 if !haveMapStack { 324 // OpenBSD prior to 6.3 did not have MAP_STACK and so 325 // the following mmap will fail. But it also didn't 326 // require MAP_STACK (obviously), so there's no need 327 // to do the mmap. 328 return 329 } 330 a, err := mmap(unsafe.Pointer(s.base()), s.npages*pageSize, _PROT_READ|_PROT_WRITE, _MAP_PRIVATE|_MAP_ANON|_MAP_FIXED|flags, -1, 0) 331 if err != 0 || uintptr(a) != s.base() { 332 print("runtime: remapping stack memory ", hex(s.base()), " ", s.npages*pageSize, " a=", a, " err=", err, "\n") 333 throw("remapping stack memory failed") 334 } 335 }