github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/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 retryOnEAGAIN(func() int32 { 166 lwp_create(¶ms) 167 return 0 168 }) 169 sigprocmask(_SIG_SETMASK, &oset, nil) 170 } 171 172 func osinit() { 173 ncpu = getncpu() 174 if physPageSize == 0 { 175 physPageSize = getPageSize() 176 } 177 } 178 179 var urandom_dev = []byte("/dev/urandom\x00") 180 181 //go:nosplit 182 func getRandomData(r []byte) { 183 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 184 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 185 closefd(fd) 186 extendRandom(r, int(n)) 187 } 188 189 func goenvs() { 190 goenvs_unix() 191 } 192 193 // Called to initialize a new m (including the bootstrap m). 194 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 195 func mpreinit(mp *m) { 196 mp.gsignal = malg(32 * 1024) 197 mp.gsignal.m = mp 198 } 199 200 // Called to initialize a new m (including the bootstrap m). 201 // Called on the new thread, cannot allocate memory. 202 func minit() { 203 getg().m.procid = uint64(lwp_gettid()) 204 minitSignals() 205 } 206 207 // Called from dropm to undo the effect of an minit. 208 // 209 //go:nosplit 210 func unminit() { 211 unminitSignals() 212 } 213 214 // Called from exitm, but not from drop, to undo the effect of thread-owned 215 // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. 216 func mdestroy(mp *m) { 217 } 218 219 func sigtramp() 220 221 type sigactiont struct { 222 sa_sigaction uintptr 223 sa_flags int32 224 sa_mask sigset 225 } 226 227 //go:nosplit 228 //go:nowritebarrierrec 229 func setsig(i uint32, fn uintptr) { 230 var sa sigactiont 231 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART 232 sa.sa_mask = sigset_all 233 if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go 234 fn = abi.FuncPCABI0(sigtramp) 235 } 236 sa.sa_sigaction = fn 237 sigaction(i, &sa, nil) 238 } 239 240 //go:nosplit 241 //go:nowritebarrierrec 242 func setsigstack(i uint32) { 243 throw("setsigstack") 244 } 245 246 //go:nosplit 247 //go:nowritebarrierrec 248 func getsig(i uint32) uintptr { 249 var sa sigactiont 250 sigaction(i, nil, &sa) 251 return sa.sa_sigaction 252 } 253 254 // setSignalstackSP sets the ss_sp field of a stackt. 255 // 256 //go:nosplit 257 func setSignalstackSP(s *stackt, sp uintptr) { 258 s.ss_sp = sp 259 } 260 261 //go:nosplit 262 //go:nowritebarrierrec 263 func sigaddset(mask *sigset, i int) { 264 mask.__bits[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31) 265 } 266 267 func sigdelset(mask *sigset, i int) { 268 mask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31) 269 } 270 271 //go:nosplit 272 func (c *sigctxt) fixsigcode(sig uint32) { 273 } 274 275 func setProcessCPUProfiler(hz int32) { 276 setProcessCPUProfilerTimer(hz) 277 } 278 279 func setThreadCPUProfiler(hz int32) { 280 setThreadCPUProfilerHz(hz) 281 } 282 283 //go:nosplit 284 func validSIGPROF(mp *m, c *sigctxt) bool { 285 return true 286 } 287 288 func sysargs(argc int32, argv **byte) { 289 n := argc + 1 290 291 // skip over argv, envp to get to auxv 292 for argv_index(argv, n) != nil { 293 n++ 294 } 295 296 // skip NULL separator 297 n++ 298 299 auxvp := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize)) 300 pairs := sysauxv(auxvp[:]) 301 auxv = auxvp[: pairs*2 : pairs*2] 302 } 303 304 const ( 305 _AT_NULL = 0 306 _AT_PAGESZ = 6 307 ) 308 309 func sysauxv(auxv []uintptr) (pairs int) { 310 var i int 311 for i = 0; auxv[i] != _AT_NULL; i += 2 { 312 tag, val := auxv[i], auxv[i+1] 313 switch tag { 314 case _AT_PAGESZ: 315 physPageSize = val 316 } 317 } 318 return i / 2 319 } 320 321 // raise sends a signal to the calling thread. 322 // 323 // It must be nosplit because it is used by the signal handler before 324 // it definitely has a Go stack. 325 // 326 //go:nosplit 327 func raise(sig uint32) { 328 lwp_kill(-1, lwp_gettid(), int(sig)) 329 } 330 331 func signalM(mp *m, sig int) { 332 lwp_kill(-1, int32(mp.procid), sig) 333 } 334 335 // sigPerThreadSyscall is only used on linux, so we assign a bogus signal 336 // number. 337 const sigPerThreadSyscall = 1 << 31 338 339 //go:nosplit 340 func runPerThreadSyscall() { 341 throw("runPerThreadSyscall only valid on linux") 342 }