rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/runtime/os1_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 "unsafe" 8 9 const ( 10 _ESRCH = 3 11 _EAGAIN = 35 12 _EWOULDBLOCK = _EAGAIN 13 _ENOTSUP = 91 14 15 // From OpenBSD's sys/time.h 16 _CLOCK_REALTIME = 0 17 _CLOCK_VIRTUAL = 1 18 _CLOCK_PROF = 2 19 _CLOCK_MONOTONIC = 3 20 ) 21 22 const ( 23 sigset_none = uint32(0) 24 sigset_all = ^uint32(0) 25 ) 26 27 // From OpenBSD's <sys/sysctl.h> 28 const ( 29 _CTL_HW = 6 30 _HW_NCPU = 3 31 ) 32 33 func getncpu() int32 { 34 mib := [2]uint32{_CTL_HW, _HW_NCPU} 35 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 47 func semacreate() uintptr { 48 return 1 49 } 50 51 //go:nosplit 52 func 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() 61 ts.set_sec(int64(timediv(ns, 1000000000, &nsec))) 62 ts.set_nsec(nsec) 63 tsp = &ts 64 } 65 66 for { 67 v := atomicload(&_g_.m.waitsemacount) 68 if v > 0 { 69 if cas(&_g_.m.waitsemacount, v, v-1) { 70 return 0 // semaphore acquired 71 } 72 continue 73 } 74 75 // 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) 83 if ret == _EWOULDBLOCK { 84 return -1 85 } 86 } 87 } 88 89 //go:nosplit 90 func semawakeup(mp *m) { 91 xadd(&mp.waitsemacount, 1) 92 ret := thrwakeup(uintptr(unsafe.Pointer(&mp.waitsemacount)), 1) 93 if ret != 0 && ret != _ESRCH { 94 // semawakeup can be called on signal stack. 95 systemstack(func() { 96 print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n") 97 }) 98 } 99 } 100 101 // May run with m.p==nil, so write barriers are not allowed. 102 //go:nowritebarrier 103 func 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(¶m, 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") 122 throw("runtime.newosproc") 123 } 124 } 125 126 func osinit() { 127 ncpu = getncpu() 128 } 129 130 var urandom_dev = []byte("/dev/urandom\x00") 131 132 //go:nosplit 133 func getRandomData(r []byte) { 134 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 135 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 136 closefd(fd) 137 extendRandom(r, int(n)) 138 } 139 140 func 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. 146 func mpreinit(mp *m) { 147 mp.gsignal = malg(32 * 1024) 148 mp.gsignal.m = mp 149 } 150 151 // Called to initialize a new m (including the bootstrap m). 152 // Called on the new thread, can not allocate memory. 153 func minit() { 154 _g_ := getg() 155 156 // m.procid is a uint64, but tfork writes an int32. Fix it up. 157 _g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid))) 158 159 // Initialize signal handling 160 signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024) 161 sigprocmask(_SIG_SETMASK, sigset_none) 162 } 163 164 // Called from dropm to undo the effect of an minit. 165 func unminit() { 166 signalstack(nil, 0) 167 } 168 169 func memlimit() uintptr { 170 return 0 171 } 172 173 func sigtramp() 174 175 type sigactiont struct { 176 sa_sigaction uintptr 177 sa_mask uint32 178 sa_flags int32 179 } 180 181 func setsig(i int32, fn uintptr, restart bool) { 182 var sa sigactiont 183 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK 184 if restart { 185 sa.sa_flags |= _SA_RESTART 186 } 187 sa.sa_mask = sigset_all 188 if fn == funcPC(sighandler) { 189 fn = funcPC(sigtramp) 190 } 191 sa.sa_sigaction = fn 192 sigaction(i, &sa, nil) 193 } 194 195 func setsigstack(i int32) { 196 throw("setsigstack") 197 } 198 199 func getsig(i int32) uintptr { 200 var sa sigactiont 201 sigaction(i, nil, &sa) 202 if sa.sa_sigaction == funcPC(sigtramp) { 203 return funcPC(sighandler) 204 } 205 return sa.sa_sigaction 206 } 207 208 func signalstack(p *byte, n int32) { 209 var st stackt 210 211 st.ss_sp = uintptr(unsafe.Pointer(p)) 212 st.ss_size = uintptr(n) 213 st.ss_flags = 0 214 if p == nil { 215 st.ss_flags = _SS_DISABLE 216 } 217 sigaltstack(&st, nil) 218 } 219 220 func unblocksignals() { 221 sigprocmask(_SIG_SETMASK, sigset_none) 222 }