github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/src/runtime/os_freebsd.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/sys" 9 "unsafe" 10 ) 11 12 type mOS struct{} 13 14 //go:noescape 15 func thr_new(param *thrparam, size int32) 16 17 //go:noescape 18 func sigaltstack(new, old *stackt) 19 20 //go:noescape 21 func sigaction(sig uint32, new, old *sigactiont) 22 23 //go:noescape 24 func sigprocmask(how int32, new, old *sigset) 25 26 //go:noescape 27 func setitimer(mode int32, new, old *itimerval) 28 29 //go:noescape 30 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 31 32 //go:noescape 33 func getrlimit(kind int32, limit unsafe.Pointer) int32 34 func raise(sig uint32) 35 func raiseproc(sig uint32) 36 37 //go:noescape 38 func sys_umtx_op(addr *uint32, mode int32, val uint32, uaddr1 uintptr, ut *umtx_time) int32 39 40 func osyield() 41 42 // From FreeBSD's <sys/sysctl.h> 43 const ( 44 _CTL_HW = 6 45 _HW_NCPU = 3 46 _HW_PAGESIZE = 7 47 ) 48 49 var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}} 50 51 func getncpu() int32 { 52 mib := [2]uint32{_CTL_HW, _HW_NCPU} 53 out := uint32(0) 54 nout := unsafe.Sizeof(out) 55 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) 56 if ret >= 0 { 57 return int32(out) 58 } 59 return 1 60 } 61 62 func getPageSize() uintptr { 63 mib := [2]uint32{_CTL_HW, _HW_PAGESIZE} 64 out := uint32(0) 65 nout := unsafe.Sizeof(out) 66 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) 67 if ret >= 0 { 68 return uintptr(out) 69 } 70 return 0 71 } 72 73 // FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and 74 // thus the code is largely similar. See Linux implementation 75 // and lock_futex.go for comments. 76 77 //go:nosplit 78 func futexsleep(addr *uint32, val uint32, ns int64) { 79 systemstack(func() { 80 futexsleep1(addr, val, ns) 81 }) 82 } 83 84 func futexsleep1(addr *uint32, val uint32, ns int64) { 85 var utp *umtx_time 86 if ns >= 0 { 87 var ut umtx_time 88 ut._clockid = _CLOCK_MONOTONIC 89 ut._timeout.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ut._timeout.tv_nsec))))) 90 utp = &ut 91 } 92 ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, unsafe.Sizeof(*utp), utp) 93 if ret >= 0 || ret == -_EINTR { 94 return 95 } 96 print("umtx_wait addr=", addr, " val=", val, " ret=", ret, "\n") 97 *(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005 98 } 99 100 //go:nosplit 101 func futexwakeup(addr *uint32, cnt uint32) { 102 ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, 0, nil) 103 if ret >= 0 { 104 return 105 } 106 107 systemstack(func() { 108 print("umtx_wake_addr=", addr, " ret=", ret, "\n") 109 }) 110 } 111 112 func thr_start() 113 114 // May run with m.p==nil, so write barriers are not allowed. 115 //go:nowritebarrier 116 func newosproc(mp *m, stk unsafe.Pointer) { 117 if false { 118 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", funcPC(thr_start), " id=", mp.id, " ostk=", &mp, "\n") 119 } 120 121 // NOTE(rsc): This code is confused. stackbase is the top of the stack 122 // and is equal to stk. However, it's working, so I'm not changing it. 123 param := thrparam{ 124 start_func: funcPC(thr_start), 125 arg: unsafe.Pointer(mp), 126 stack_base: mp.g0.stack.hi, 127 stack_size: uintptr(stk) - mp.g0.stack.hi, 128 child_tid: unsafe.Pointer(&mp.procid), 129 parent_tid: nil, 130 tls_base: unsafe.Pointer(&mp.tls[0]), 131 tls_size: unsafe.Sizeof(mp.tls), 132 } 133 134 var oset sigset 135 sigprocmask(_SIG_SETMASK, &sigset_all, &oset) 136 // TODO: Check for error. 137 thr_new(¶m, int32(unsafe.Sizeof(param))) 138 sigprocmask(_SIG_SETMASK, &oset, nil) 139 } 140 141 func osinit() { 142 ncpu = getncpu() 143 physPageSize = getPageSize() 144 } 145 146 var urandom_dev = []byte("/dev/urandom\x00") 147 148 //go:nosplit 149 func getRandomData(r []byte) { 150 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 151 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 152 closefd(fd) 153 extendRandom(r, int(n)) 154 } 155 156 func goenvs() { 157 goenvs_unix() 158 } 159 160 // Called to initialize a new m (including the bootstrap m). 161 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 162 func mpreinit(mp *m) { 163 mp.gsignal = malg(32 * 1024) 164 mp.gsignal.m = mp 165 } 166 167 // Called to initialize a new m (including the bootstrap m). 168 // Called on the new thread, cannot allocate memory. 169 func minit() { 170 // m.procid is a uint64, but thr_new writes a uint32 on 32-bit systems. 171 // Fix it up. (Only matters on big-endian, but be clean anyway.) 172 if sys.PtrSize == 4 { 173 _g_ := getg() 174 _g_.m.procid = uint64(*(*uint32)(unsafe.Pointer(&_g_.m.procid))) 175 } 176 177 minitSignals() 178 } 179 180 // Called from dropm to undo the effect of an minit. 181 //go:nosplit 182 func unminit() { 183 unminitSignals() 184 } 185 186 func memlimit() uintptr { 187 /* 188 TODO: Convert to Go when something actually uses the result. 189 Rlimit rl; 190 extern byte runtime·text[], runtime·end[]; 191 uintptr used; 192 193 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0) 194 return 0; 195 if(rl.rlim_cur >= 0x7fffffff) 196 return 0; 197 198 // Estimate our VM footprint excluding the heap. 199 // Not an exact science: use size of binary plus 200 // some room for thread stacks. 201 used = runtime·end - runtime·text + (64<<20); 202 if(used >= rl.rlim_cur) 203 return 0; 204 205 // If there's not at least 16 MB left, we're probably 206 // not going to be able to do much. Treat as no limit. 207 rl.rlim_cur -= used; 208 if(rl.rlim_cur < (16<<20)) 209 return 0; 210 211 return rl.rlim_cur - used; 212 */ 213 214 return 0 215 } 216 217 func sigtramp() 218 219 type sigactiont struct { 220 sa_handler uintptr 221 sa_flags int32 222 sa_mask sigset 223 } 224 225 //go:nosplit 226 //go:nowritebarrierrec 227 func setsig(i uint32, fn uintptr) { 228 var sa sigactiont 229 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART 230 sa.sa_mask = sigset_all 231 if fn == funcPC(sighandler) { 232 fn = funcPC(sigtramp) 233 } 234 sa.sa_handler = fn 235 sigaction(i, &sa, nil) 236 } 237 238 //go:nosplit 239 //go:nowritebarrierrec 240 func setsigstack(i uint32) { 241 throw("setsigstack") 242 } 243 244 //go:nosplit 245 //go:nowritebarrierrec 246 func getsig(i uint32) uintptr { 247 var sa sigactiont 248 sigaction(i, nil, &sa) 249 return sa.sa_handler 250 } 251 252 // setSignaltstackSP sets the ss_sp field of a stackt. 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 func (c *sigctxt) fixsigcode(sig uint32) { 269 }