github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/runtime/os_dragonfly.go (about) 1 // Copyright 2014 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 "internal/abi" 9 "internal/goarch" 10 "unsafe" 11 ) 12 13 const ( 14 _NSIG = 33 15 _SI_USER = 0 16 _SS_DISABLE = 4 17 _SIG_BLOCK = 1 18 _SIG_UNBLOCK = 2 19 _SIG_SETMASK = 3 20 ) 21 22 type mOS struct{} 23 24 //go:noescape 25 func lwp_create(param *lwpparams) int32 26 27 //go:noescape 28 func sigaltstack(new, old *stackt) 29 30 //go:noescape 31 func sigaction(sig uint32, new, old *sigactiont) 32 33 //go:noescape 34 func sigprocmask(how int32, new, old *sigset) 35 36 //go:noescape 37 func setitimer(mode int32, new, old *itimerval) 38 39 //go:noescape 40 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 41 42 func raiseproc(sig uint32) 43 44 func lwp_gettid() int32 45 func lwp_kill(pid, tid int32, sig int) 46 47 //go:noescape 48 func sys_umtx_sleep(addr *uint32, val, timeout int32) int32 49 50 //go:noescape 51 func sys_umtx_wakeup(addr *uint32, val int32) int32 52 53 func osyield() 54 55 //go:nosplit 56 func osyield_no_g() { 57 osyield() 58 } 59 60 func kqueue() int32 61 62 //go:noescape 63 func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32 64 65 func pipe2(flags int32) (r, w int32, errno int32) 66 func closeonexec(fd int32) 67 68 // From DragonFly's <sys/sysctl.h> 69 const ( 70 _CTL_HW = 6 71 _HW_NCPU = 3 72 _HW_PAGESIZE = 7 73 ) 74 75 var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}} 76 77 func getncpu() int32 { 78 mib := [2]uint32{_CTL_HW, _HW_NCPU} 79 out := uint32(0) 80 nout := unsafe.Sizeof(out) 81 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) 82 if ret >= 0 { 83 return int32(out) 84 } 85 return 1 86 } 87 88 func getPageSize() uintptr { 89 mib := [2]uint32{_CTL_HW, _HW_PAGESIZE} 90 out := uint32(0) 91 nout := unsafe.Sizeof(out) 92 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) 93 if ret >= 0 { 94 return uintptr(out) 95 } 96 return 0 97 } 98 99 //go:nosplit 100 func futexsleep(addr *uint32, val uint32, ns int64) { 101 systemstack(func() { 102 futexsleep1(addr, val, ns) 103 }) 104 } 105 106 func futexsleep1(addr *uint32, val uint32, ns int64) { 107 var timeout int32 108 if ns >= 0 { 109 // The timeout is specified in microseconds - ensure that we 110 // do not end up dividing to zero, which would put us to sleep 111 // indefinitely... 112 timeout = timediv(ns, 1000, nil) 113 if timeout == 0 { 114 timeout = 1 115 } 116 } 117 118 // sys_umtx_sleep will return EWOULDBLOCK (EAGAIN) when the timeout 119 // expires or EBUSY if the mutex value does not match. 120 ret := sys_umtx_sleep(addr, int32(val), timeout) 121 if ret >= 0 || ret == -_EINTR || ret == -_EAGAIN || ret == -_EBUSY { 122 return 123 } 124 125 print("umtx_sleep addr=", addr, " val=", val, " ret=", ret, "\n") 126 *(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005 127 } 128 129 //go:nosplit 130 func futexwakeup(addr *uint32, cnt uint32) { 131 ret := sys_umtx_wakeup(addr, int32(cnt)) 132 if ret >= 0 { 133 return 134 } 135 136 systemstack(func() { 137 print("umtx_wake_addr=", addr, " ret=", ret, "\n") 138 *(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006 139 }) 140 } 141 142 func lwp_start(uintptr) 143 144 // May run with m.p==nil, so write barriers are not allowed. 145 // 146 //go:nowritebarrier 147 func newosproc(mp *m) { 148 stk := unsafe.Pointer(mp.g0.stack.hi) 149 if false { 150 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " lwp_start=", abi.FuncPCABI0(lwp_start), " id=", mp.id, " ostk=", &mp, "\n") 151 } 152 153 var oset sigset 154 sigprocmask(_SIG_SETMASK, &sigset_all, &oset) 155 156 params := lwpparams{ 157 start_func: abi.FuncPCABI0(lwp_start), 158 arg: unsafe.Pointer(mp), 159 stack: uintptr(stk), 160 tid1: nil, // minit will record tid 161 tid2: nil, 162 } 163 164 // TODO: Check for error. 165 lwp_create(¶ms) 166 sigprocmask(_SIG_SETMASK, &oset, nil) 167 } 168 169 func osinit() { 170 ncpu = getncpu() 171 if physPageSize == 0 { 172 physPageSize = getPageSize() 173 } 174 } 175 176 var urandom_dev = []byte("/dev/urandom\x00") 177 178 //go:nosplit 179 func getRandomData(r []byte) { 180 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 181 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 182 closefd(fd) 183 extendRandom(r, int(n)) 184 } 185 186 func goenvs() { 187 goenvs_unix() 188 } 189 190 // Called to initialize a new m (including the bootstrap m). 191 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 192 func mpreinit(mp *m) { 193 mp.gsignal = malg(32 * 1024) 194 mp.gsignal.m = mp 195 } 196 197 // Called to initialize a new m (including the bootstrap m). 198 // Called on the new thread, cannot allocate memory. 199 func minit() { 200 getg().m.procid = uint64(lwp_gettid()) 201 minitSignals() 202 } 203 204 // Called from dropm to undo the effect of an minit. 205 // 206 //go:nosplit 207 func unminit() { 208 unminitSignals() 209 } 210 211 // Called from exitm, but not from drop, to undo the effect of thread-owned 212 // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. 213 func mdestroy(mp *m) { 214 } 215 216 func sigtramp() 217 218 type sigactiont struct { 219 sa_sigaction uintptr 220 sa_flags int32 221 sa_mask sigset 222 } 223 224 //go:nosplit 225 //go:nowritebarrierrec 226 func setsig(i uint32, fn uintptr) { 227 var sa sigactiont 228 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART 229 sa.sa_mask = sigset_all 230 if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go 231 fn = abi.FuncPCABI0(sigtramp) 232 } 233 sa.sa_sigaction = fn 234 sigaction(i, &sa, nil) 235 } 236 237 //go:nosplit 238 //go:nowritebarrierrec 239 func setsigstack(i uint32) { 240 throw("setsigstack") 241 } 242 243 //go:nosplit 244 //go:nowritebarrierrec 245 func getsig(i uint32) uintptr { 246 var sa sigactiont 247 sigaction(i, nil, &sa) 248 return sa.sa_sigaction 249 } 250 251 // setSignaltstackSP sets the ss_sp field of a stackt. 252 // 253 //go:nosplit 254 func setSignalstackSP(s *stackt, sp uintptr) { 255 s.ss_sp = sp 256 } 257 258 //go:nosplit 259 //go:nowritebarrierrec 260 func sigaddset(mask *sigset, i int) { 261 mask.__bits[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31) 262 } 263 264 func sigdelset(mask *sigset, i int) { 265 mask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31) 266 } 267 268 //go:nosplit 269 func (c *sigctxt) fixsigcode(sig uint32) { 270 } 271 272 func setProcessCPUProfiler(hz int32) { 273 setProcessCPUProfilerTimer(hz) 274 } 275 276 func setThreadCPUProfiler(hz int32) { 277 setThreadCPUProfilerHz(hz) 278 } 279 280 //go:nosplit 281 func validSIGPROF(mp *m, c *sigctxt) bool { 282 return true 283 } 284 285 func sysargs(argc int32, argv **byte) { 286 n := argc + 1 287 288 // skip over argv, envp to get to auxv 289 for argv_index(argv, n) != nil { 290 n++ 291 } 292 293 // skip NULL separator 294 n++ 295 296 auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize)) 297 sysauxv(auxv[:]) 298 } 299 300 const ( 301 _AT_NULL = 0 302 _AT_PAGESZ = 6 303 ) 304 305 func sysauxv(auxv []uintptr) { 306 for i := 0; auxv[i] != _AT_NULL; i += 2 { 307 tag, val := auxv[i], auxv[i+1] 308 switch tag { 309 case _AT_PAGESZ: 310 physPageSize = val 311 } 312 } 313 } 314 315 // raise sends a signal to the calling thread. 316 // 317 // It must be nosplit because it is used by the signal handler before 318 // it definitely has a Go stack. 319 // 320 //go:nosplit 321 func raise(sig uint32) { 322 lwp_kill(-1, lwp_gettid(), int(sig)) 323 } 324 325 func signalM(mp *m, sig int) { 326 lwp_kill(-1, int32(mp.procid), sig) 327 } 328 329 // sigPerThreadSyscall is only used on linux, so we assign a bogus signal 330 // number. 331 const sigPerThreadSyscall = 1 << 31 332 333 //go:nosplit 334 func runPerThreadSyscall() { 335 throw("runPerThreadSyscall only valid on linux") 336 }