github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/runtime/os_linux.go (about) 1 // Copyright 2009 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 futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32 16 17 // Linux futex. 18 // 19 // futexsleep(uint32 *addr, uint32 val) 20 // futexwakeup(uint32 *addr) 21 // 22 // Futexsleep atomically checks if *addr == val and if so, sleeps on addr. 23 // Futexwakeup wakes up threads sleeping on addr. 24 // Futexsleep is allowed to wake up spuriously. 25 26 const ( 27 _FUTEX_WAIT = 0 28 _FUTEX_WAKE = 1 29 ) 30 31 // Atomically, 32 // if(*addr == val) sleep 33 // Might be woken up spuriously; that's allowed. 34 // Don't sleep longer than ns; ns < 0 means forever. 35 //go:nosplit 36 func futexsleep(addr *uint32, val uint32, ns int64) { 37 var ts timespec 38 39 // Some Linux kernels have a bug where futex of 40 // FUTEX_WAIT returns an internal error code 41 // as an errno. Libpthread ignores the return value 42 // here, and so can we: as it says a few lines up, 43 // spurious wakeups are allowed. 44 if ns < 0 { 45 futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, nil, nil, 0) 46 return 47 } 48 49 // It's difficult to live within the no-split stack limits here. 50 // On ARM and 386, a 64-bit divide invokes a general software routine 51 // that needs more stack than we can afford. So we use timediv instead. 52 // But on real 64-bit systems, where words are larger but the stack limit 53 // is not, even timediv is too heavy, and we really need to use just an 54 // ordinary machine instruction. 55 if sys.PtrSize == 8 { 56 ts.set_sec(ns / 1000000000) 57 ts.set_nsec(int32(ns % 1000000000)) 58 } else { 59 ts.tv_nsec = 0 60 ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec))))) 61 } 62 futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, unsafe.Pointer(&ts), nil, 0) 63 } 64 65 // If any procs are sleeping on addr, wake up at most cnt. 66 //go:nosplit 67 func futexwakeup(addr *uint32, cnt uint32) { 68 ret := futex(unsafe.Pointer(addr), _FUTEX_WAKE, cnt, nil, nil, 0) 69 if ret >= 0 { 70 return 71 } 72 73 // I don't know that futex wakeup can return 74 // EAGAIN or EINTR, but if it does, it would be 75 // safe to loop and call futex again. 76 systemstack(func() { 77 print("futexwakeup addr=", addr, " returned ", ret, "\n") 78 }) 79 80 *(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006 81 } 82 83 func getproccount() int32 { 84 // This buffer is huge (8 kB) but we are on the system stack 85 // and there should be plenty of space (64 kB). 86 // Also this is a leaf, so we're not holding up the memory for long. 87 // See golang.org/issue/11823. 88 // The suggested behavior here is to keep trying with ever-larger 89 // buffers, but we don't have a dynamic memory allocator at the 90 // moment, so that's a bit tricky and seems like overkill. 91 const maxCPUs = 64 * 1024 92 var buf [maxCPUs / (sys.PtrSize * 8)]uintptr 93 r := sched_getaffinity(0, unsafe.Sizeof(buf), &buf[0]) 94 if r < 0 { 95 return 1 96 } 97 n := int32(0) 98 for _, v := range buf[:r/sys.PtrSize] { 99 for v != 0 { 100 n += int32(v & 1) 101 v >>= 1 102 } 103 } 104 if n == 0 { 105 n = 1 106 } 107 return n 108 } 109 110 // Clone, the Linux rfork. 111 const ( 112 _CLONE_VM = 0x100 113 _CLONE_FS = 0x200 114 _CLONE_FILES = 0x400 115 _CLONE_SIGHAND = 0x800 116 _CLONE_PTRACE = 0x2000 117 _CLONE_VFORK = 0x4000 118 _CLONE_PARENT = 0x8000 119 _CLONE_THREAD = 0x10000 120 _CLONE_NEWNS = 0x20000 121 _CLONE_SYSVSEM = 0x40000 122 _CLONE_SETTLS = 0x80000 123 _CLONE_PARENT_SETTID = 0x100000 124 _CLONE_CHILD_CLEARTID = 0x200000 125 _CLONE_UNTRACED = 0x800000 126 _CLONE_CHILD_SETTID = 0x1000000 127 _CLONE_STOPPED = 0x2000000 128 _CLONE_NEWUTS = 0x4000000 129 _CLONE_NEWIPC = 0x8000000 130 131 // As of QEMU 2.8.0 (5ea2fc84d), user emulation requires all six of these 132 // flags to be set when creating a thread; attempts to share the other 133 // five but leave SYSVSEM unshared will fail with -EINVAL. 134 // 135 // In non-QEMU environments CLONE_SYSVSEM is inconsequential as we do not 136 // use System V semaphores. 137 138 cloneFlags = _CLONE_VM | /* share memory */ 139 _CLONE_FS | /* share cwd, etc */ 140 _CLONE_FILES | /* share fd table */ 141 _CLONE_SIGHAND | /* share sig handler table */ 142 _CLONE_SYSVSEM | /* share semaphore adjustments */ 143 _CLONE_THREAD /* revisit - okay for now */ 144 ) 145 146 //go:noescape 147 func clone(flags int32, stk, mp, gp, fn unsafe.Pointer) int32 148 149 // May run with m.p==nil, so write barriers are not allowed. 150 //go:nowritebarrier 151 func newosproc(mp *m, stk unsafe.Pointer) { 152 /* 153 * note: strace gets confused if we use CLONE_PTRACE here. 154 */ 155 if false { 156 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", funcPC(clone), " id=", mp.id, " ostk=", &mp, "\n") 157 } 158 159 // Disable signals during clone, so that the new thread starts 160 // with signals disabled. It will enable them in minit. 161 var oset sigset 162 sigprocmask(_SIG_SETMASK, &sigset_all, &oset) 163 ret := clone(cloneFlags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart))) 164 sigprocmask(_SIG_SETMASK, &oset, nil) 165 166 if ret < 0 { 167 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", -ret, ")\n") 168 if ret == -_EAGAIN { 169 println("runtime: may need to increase max user processes (ulimit -u)") 170 } 171 throw("newosproc") 172 } 173 } 174 175 // Version of newosproc that doesn't require a valid G. 176 //go:nosplit 177 func newosproc0(stacksize uintptr, fn unsafe.Pointer) { 178 stack := sysAlloc(stacksize, &memstats.stacks_sys) 179 if stack == nil { 180 write(2, unsafe.Pointer(&failallocatestack[0]), int32(len(failallocatestack))) 181 exit(1) 182 } 183 ret := clone(cloneFlags, unsafe.Pointer(uintptr(stack)+stacksize), nil, nil, fn) 184 if ret < 0 { 185 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate))) 186 exit(1) 187 } 188 } 189 190 var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n") 191 var failthreadcreate = []byte("runtime: failed to create new OS thread\n") 192 193 const ( 194 _AT_NULL = 0 // End of vector 195 _AT_PAGESZ = 6 // System physical page size 196 _AT_HWCAP = 16 // hardware capability bit vector 197 _AT_RANDOM = 25 // introduced in 2.6.29 198 _AT_HWCAP2 = 26 // hardware capability bit vector 2 199 ) 200 201 var procAuxv = []byte("/proc/self/auxv\x00") 202 203 func sysargs(argc int32, argv **byte) { 204 n := argc + 1 205 206 // skip over argv, envp to get to auxv 207 for argv_index(argv, n) != nil { 208 n++ 209 } 210 211 // skip NULL separator 212 n++ 213 214 // now argv+n is auxv 215 auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize)) 216 if sysauxv(auxv[:]) == 0 { 217 // In some situations we don't get a loader-provided 218 // auxv, such as when loaded as a library on Android. 219 // Fall back to /proc/self/auxv. 220 fd := open(&procAuxv[0], 0 /* O_RDONLY */, 0) 221 if fd < 0 { 222 // On Android, /proc/self/auxv might be unreadable (issue 9229), so we fallback to 223 // try using mincore to detect the physical page size. 224 // mincore should return EINVAL when address is not a multiple of system page size. 225 const size = 256 << 10 // size of memory region to allocate 226 p := mmap(nil, size, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0) 227 if uintptr(p) < 4096 { 228 return 229 } 230 var n uintptr 231 for n = 4 << 10; n < size; n <<= 1 { 232 err := mincore(unsafe.Pointer(uintptr(p)+n), 1, &addrspace_vec[0]) 233 if err == 0 { 234 physPageSize = n 235 break 236 } 237 } 238 if physPageSize == 0 { 239 physPageSize = size 240 } 241 munmap(p, size) 242 return 243 } 244 var buf [128]uintptr 245 n := read(fd, noescape(unsafe.Pointer(&buf[0])), int32(unsafe.Sizeof(buf))) 246 closefd(fd) 247 if n < 0 { 248 return 249 } 250 // Make sure buf is terminated, even if we didn't read 251 // the whole file. 252 buf[len(buf)-2] = _AT_NULL 253 sysauxv(buf[:]) 254 } 255 } 256 257 func sysauxv(auxv []uintptr) int { 258 var i int 259 for ; auxv[i] != _AT_NULL; i += 2 { 260 tag, val := auxv[i], auxv[i+1] 261 switch tag { 262 case _AT_RANDOM: 263 // The kernel provides a pointer to 16-bytes 264 // worth of random data. 265 startupRandomData = (*[16]byte)(unsafe.Pointer(val))[:] 266 267 case _AT_PAGESZ: 268 physPageSize = val 269 } 270 271 archauxv(tag, val) 272 } 273 return i / 2 274 } 275 276 func osinit() { 277 ncpu = getproccount() 278 } 279 280 var urandom_dev = []byte("/dev/urandom\x00") 281 282 func getRandomData(r []byte) { 283 if startupRandomData != nil { 284 n := copy(r, startupRandomData) 285 extendRandom(r, n) 286 return 287 } 288 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 289 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 290 closefd(fd) 291 extendRandom(r, int(n)) 292 } 293 294 func goenvs() { 295 goenvs_unix() 296 } 297 298 // Called to do synchronous initialization of Go code built with 299 // -buildmode=c-archive or -buildmode=c-shared. 300 // None of the Go runtime is initialized. 301 //go:nosplit 302 //go:nowritebarrierrec 303 func libpreinit() { 304 initsig(true) 305 } 306 307 // Called to initialize a new m (including the bootstrap m). 308 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 309 func mpreinit(mp *m) { 310 mp.gsignal = malg(32 * 1024) // Linux wants >= 2K 311 mp.gsignal.m = mp 312 } 313 314 func gettid() uint32 315 316 // Called to initialize a new m (including the bootstrap m). 317 // Called on the new thread, cannot allocate memory. 318 func minit() { 319 minitSignals() 320 321 // for debuggers, in case cgo created the thread 322 getg().m.procid = uint64(gettid()) 323 } 324 325 // Called from dropm to undo the effect of an minit. 326 //go:nosplit 327 func unminit() { 328 unminitSignals() 329 } 330 331 func memlimit() uintptr { 332 /* 333 TODO: Convert to Go when something actually uses the result. 334 335 Rlimit rl; 336 extern byte runtime·text[], runtime·end[]; 337 uintptr used; 338 339 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0) 340 return 0; 341 if(rl.rlim_cur >= 0x7fffffff) 342 return 0; 343 344 // Estimate our VM footprint excluding the heap. 345 // Not an exact science: use size of binary plus 346 // some room for thread stacks. 347 used = runtime·end - runtime·text + (64<<20); 348 if(used >= rl.rlim_cur) 349 return 0; 350 351 // If there's not at least 16 MB left, we're probably 352 // not going to be able to do much. Treat as no limit. 353 rl.rlim_cur -= used; 354 if(rl.rlim_cur < (16<<20)) 355 return 0; 356 357 return rl.rlim_cur - used; 358 */ 359 360 return 0 361 } 362 363 //#ifdef GOARCH_386 364 //#define sa_handler k_sa_handler 365 //#endif 366 367 func sigreturn() 368 func sigtramp(sig uint32, info *siginfo, ctx unsafe.Pointer) 369 func cgoSigtramp() 370 371 //go:noescape 372 func sigaltstack(new, old *stackt) 373 374 //go:noescape 375 func setitimer(mode int32, new, old *itimerval) 376 377 //go:noescape 378 func rtsigprocmask(how int32, new, old *sigset, size int32) 379 380 //go:nosplit 381 //go:nowritebarrierrec 382 func sigprocmask(how int32, new, old *sigset) { 383 rtsigprocmask(how, new, old, int32(unsafe.Sizeof(*new))) 384 } 385 386 //go:noescape 387 func getrlimit(kind int32, limit unsafe.Pointer) int32 388 func raise(sig uint32) 389 func raiseproc(sig uint32) 390 391 //go:noescape 392 func sched_getaffinity(pid, len uintptr, buf *uintptr) int32 393 func osyield() 394 395 //go:nosplit 396 //go:nowritebarrierrec 397 func setsig(i uint32, fn uintptr) { 398 var sa sigactiont 399 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTORER | _SA_RESTART 400 sigfillset(&sa.sa_mask) 401 // Although Linux manpage says "sa_restorer element is obsolete and 402 // should not be used". x86_64 kernel requires it. Only use it on 403 // x86. 404 if GOARCH == "386" || GOARCH == "amd64" { 405 sa.sa_restorer = funcPC(sigreturn) 406 } 407 if fn == funcPC(sighandler) { 408 if iscgo { 409 fn = funcPC(cgoSigtramp) 410 } else { 411 fn = funcPC(sigtramp) 412 } 413 } 414 sa.sa_handler = fn 415 rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) 416 } 417 418 //go:nosplit 419 //go:nowritebarrierrec 420 func setsigstack(i uint32) { 421 var sa sigactiont 422 rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) 423 if sa.sa_flags&_SA_ONSTACK != 0 { 424 return 425 } 426 sa.sa_flags |= _SA_ONSTACK 427 rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) 428 } 429 430 //go:nosplit 431 //go:nowritebarrierrec 432 func getsig(i uint32) uintptr { 433 var sa sigactiont 434 if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 { 435 throw("rt_sigaction read failure") 436 } 437 return sa.sa_handler 438 } 439 440 // setSignaltstackSP sets the ss_sp field of a stackt. 441 //go:nosplit 442 func setSignalstackSP(s *stackt, sp uintptr) { 443 *(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp 444 } 445 446 func (c *sigctxt) fixsigcode(sig uint32) { 447 }