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