github.com/euank/go@v0.0.0-20160829210321-495514729181/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 n := int32(0) 95 for _, v := range buf[:r/sys.PtrSize] { 96 for v != 0 { 97 n += int32(v & 1) 98 v >>= 1 99 } 100 } 101 if n == 0 { 102 n = 1 103 } 104 return n 105 } 106 107 // Clone, the Linux rfork. 108 const ( 109 _CLONE_VM = 0x100 110 _CLONE_FS = 0x200 111 _CLONE_FILES = 0x400 112 _CLONE_SIGHAND = 0x800 113 _CLONE_PTRACE = 0x2000 114 _CLONE_VFORK = 0x4000 115 _CLONE_PARENT = 0x8000 116 _CLONE_THREAD = 0x10000 117 _CLONE_NEWNS = 0x20000 118 _CLONE_SYSVSEM = 0x40000 119 _CLONE_SETTLS = 0x80000 120 _CLONE_PARENT_SETTID = 0x100000 121 _CLONE_CHILD_CLEARTID = 0x200000 122 _CLONE_UNTRACED = 0x800000 123 _CLONE_CHILD_SETTID = 0x1000000 124 _CLONE_STOPPED = 0x2000000 125 _CLONE_NEWUTS = 0x4000000 126 _CLONE_NEWIPC = 0x8000000 127 128 cloneFlags = _CLONE_VM | /* share memory */ 129 _CLONE_FS | /* share cwd, etc */ 130 _CLONE_FILES | /* share fd table */ 131 _CLONE_SIGHAND | /* share sig handler table */ 132 _CLONE_THREAD /* revisit - okay for now */ 133 ) 134 135 //go:noescape 136 func clone(flags int32, stk, mp, gp, fn unsafe.Pointer) int32 137 138 // May run with m.p==nil, so write barriers are not allowed. 139 //go:nowritebarrier 140 func newosproc(mp *m, stk unsafe.Pointer) { 141 /* 142 * note: strace gets confused if we use CLONE_PTRACE here. 143 */ 144 if false { 145 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", funcPC(clone), " id=", mp.id, " ostk=", &mp, "\n") 146 } 147 148 // Disable signals during clone, so that the new thread starts 149 // with signals disabled. It will enable them in minit. 150 var oset sigset 151 rtsigprocmask(_SIG_SETMASK, &sigset_all, &oset, int32(unsafe.Sizeof(oset))) 152 ret := clone(cloneFlags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart))) 153 rtsigprocmask(_SIG_SETMASK, &oset, nil, int32(unsafe.Sizeof(oset))) 154 155 if ret < 0 { 156 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", -ret, ")\n") 157 if ret == -_EAGAIN { 158 println("runtime: may need to increase max user processes (ulimit -u)") 159 } 160 throw("newosproc") 161 } 162 } 163 164 // Version of newosproc that doesn't require a valid G. 165 //go:nosplit 166 func newosproc0(stacksize uintptr, fn unsafe.Pointer) { 167 stack := sysAlloc(stacksize, &memstats.stacks_sys) 168 if stack == nil { 169 write(2, unsafe.Pointer(&failallocatestack[0]), int32(len(failallocatestack))) 170 exit(1) 171 } 172 ret := clone(cloneFlags, unsafe.Pointer(uintptr(stack)+stacksize), nil, nil, fn) 173 if ret < 0 { 174 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate))) 175 exit(1) 176 } 177 } 178 179 var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n") 180 var failthreadcreate = []byte("runtime: failed to create new OS thread\n") 181 182 const ( 183 _AT_NULL = 0 // End of vector 184 _AT_PAGESZ = 6 // System physical page size 185 _AT_RANDOM = 25 // introduced in 2.6.29 186 ) 187 188 func sysargs(argc int32, argv **byte) { 189 n := argc + 1 190 191 // skip over argv, envp to get to auxv 192 for argv_index(argv, n) != nil { 193 n++ 194 } 195 196 // skip NULL separator 197 n++ 198 199 // now argv+n is auxv 200 auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize)) 201 for i := 0; auxv[i] != _AT_NULL; i += 2 { 202 tag, val := auxv[i], auxv[i+1] 203 switch tag { 204 case _AT_RANDOM: 205 // The kernel provides a pointer to 16-bytes 206 // worth of random data. 207 startupRandomData = (*[16]byte)(unsafe.Pointer(val))[:] 208 209 case _AT_PAGESZ: 210 // Check that the true physical page size is 211 // compatible with the runtime's assumed 212 // physical page size. 213 if sys.PhysPageSize < val { 214 print("runtime: kernel page size (", val, ") is larger than runtime page size (", sys.PhysPageSize, ")\n") 215 exit(1) 216 } 217 if sys.PhysPageSize%val != 0 { 218 print("runtime: runtime page size (", sys.PhysPageSize, ") is not a multiple of kernel page size (", val, ")\n") 219 exit(1) 220 } 221 } 222 223 archauxv(tag, val) 224 } 225 } 226 227 func osinit() { 228 ncpu = getproccount() 229 } 230 231 var urandom_dev = []byte("/dev/urandom\x00") 232 233 func getRandomData(r []byte) { 234 if startupRandomData != nil { 235 n := copy(r, startupRandomData) 236 extendRandom(r, n) 237 return 238 } 239 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 240 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 241 closefd(fd) 242 extendRandom(r, int(n)) 243 } 244 245 func goenvs() { 246 goenvs_unix() 247 } 248 249 // Called to do synchronous initialization of Go code built with 250 // -buildmode=c-archive or -buildmode=c-shared. 251 // None of the Go runtime is initialized. 252 //go:nosplit 253 //go:nowritebarrierrec 254 func libpreinit() { 255 initsig(true) 256 } 257 258 // Called to initialize a new m (including the bootstrap m). 259 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 260 func mpreinit(mp *m) { 261 mp.gsignal = malg(32 * 1024) // Linux wants >= 2K 262 mp.gsignal.m = mp 263 } 264 265 //go:nosplit 266 func msigsave(mp *m) { 267 smask := &mp.sigmask 268 rtsigprocmask(_SIG_SETMASK, nil, smask, int32(unsafe.Sizeof(*smask))) 269 } 270 271 //go:nosplit 272 func msigrestore(sigmask sigset) { 273 rtsigprocmask(_SIG_SETMASK, &sigmask, nil, int32(unsafe.Sizeof(sigmask))) 274 } 275 276 //go:nosplit 277 func sigblock() { 278 rtsigprocmask(_SIG_SETMASK, &sigset_all, nil, int32(unsafe.Sizeof(sigset_all))) 279 } 280 281 func gettid() uint32 282 283 // Called to initialize a new m (including the bootstrap m). 284 // Called on the new thread, cannot allocate memory. 285 func minit() { 286 // Initialize signal handling. 287 _g_ := getg() 288 289 var st sigaltstackt 290 sigaltstack(nil, &st) 291 if st.ss_flags&_SS_DISABLE != 0 { 292 signalstack(&_g_.m.gsignal.stack) 293 _g_.m.newSigstack = true 294 } else { 295 // Use existing signal stack. 296 stsp := uintptr(unsafe.Pointer(st.ss_sp)) 297 _g_.m.gsignal.stack.lo = stsp 298 _g_.m.gsignal.stack.hi = stsp + st.ss_size 299 _g_.m.gsignal.stackguard0 = stsp + _StackGuard 300 _g_.m.gsignal.stackguard1 = stsp + _StackGuard 301 _g_.m.gsignal.stackAlloc = st.ss_size 302 _g_.m.newSigstack = false 303 } 304 305 // for debuggers, in case cgo created the thread 306 _g_.m.procid = uint64(gettid()) 307 308 // restore signal mask from m.sigmask and unblock essential signals 309 nmask := _g_.m.sigmask 310 for i := range sigtable { 311 if sigtable[i].flags&_SigUnblock != 0 { 312 sigdelset(&nmask, i) 313 } 314 } 315 rtsigprocmask(_SIG_SETMASK, &nmask, nil, int32(unsafe.Sizeof(nmask))) 316 } 317 318 // Called from dropm to undo the effect of an minit. 319 //go:nosplit 320 func unminit() { 321 if getg().m.newSigstack { 322 signalstack(nil) 323 } 324 } 325 326 func memlimit() uintptr { 327 /* 328 TODO: Convert to Go when something actually uses the result. 329 330 Rlimit rl; 331 extern byte runtime·text[], runtime·end[]; 332 uintptr used; 333 334 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0) 335 return 0; 336 if(rl.rlim_cur >= 0x7fffffff) 337 return 0; 338 339 // Estimate our VM footprint excluding the heap. 340 // Not an exact science: use size of binary plus 341 // some room for thread stacks. 342 used = runtime·end - runtime·text + (64<<20); 343 if(used >= rl.rlim_cur) 344 return 0; 345 346 // If there's not at least 16 MB left, we're probably 347 // not going to be able to do much. Treat as no limit. 348 rl.rlim_cur -= used; 349 if(rl.rlim_cur < (16<<20)) 350 return 0; 351 352 return rl.rlim_cur - used; 353 */ 354 355 return 0 356 } 357 358 //#ifdef GOARCH_386 359 //#define sa_handler k_sa_handler 360 //#endif 361 362 func sigreturn() 363 func sigtramp(sig uint32, info *siginfo, ctx unsafe.Pointer) 364 func cgoSigtramp() 365 366 //go:noescape 367 func rt_sigaction(sig uintptr, new, old *sigactiont, size uintptr) int32 368 369 //go:noescape 370 func sigaltstack(new, old *sigaltstackt) 371 372 //go:noescape 373 func setitimer(mode int32, new, old *itimerval) 374 375 //go:noescape 376 func rtsigprocmask(sig uint32, new, old *sigset, size int32) 377 378 //go:noescape 379 func getrlimit(kind int32, limit unsafe.Pointer) int32 380 func raise(sig int32) 381 func raiseproc(sig int32) 382 383 //go:noescape 384 func sched_getaffinity(pid, len uintptr, buf *uintptr) int32 385 func osyield() 386 387 //go:nosplit 388 //go:nowritebarrierrec 389 func setsig(i int32, fn uintptr, restart bool) { 390 var sa sigactiont 391 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTORER 392 if restart { 393 sa.sa_flags |= _SA_RESTART 394 } 395 sigfillset(&sa.sa_mask) 396 // Although Linux manpage says "sa_restorer element is obsolete and 397 // should not be used". x86_64 kernel requires it. Only use it on 398 // x86. 399 if GOARCH == "386" || GOARCH == "amd64" { 400 sa.sa_restorer = funcPC(sigreturn) 401 } 402 if fn == funcPC(sighandler) { 403 if iscgo { 404 fn = funcPC(cgoSigtramp) 405 } else { 406 fn = funcPC(sigtramp) 407 } 408 } 409 sa.sa_handler = fn 410 rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) 411 } 412 413 //go:nosplit 414 //go:nowritebarrierrec 415 func setsigstack(i int32) { 416 var sa sigactiont 417 if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 { 418 throw("rt_sigaction failure") 419 } 420 if sa.sa_handler == 0 || sa.sa_handler == _SIG_DFL || sa.sa_handler == _SIG_IGN || sa.sa_flags&_SA_ONSTACK != 0 { 421 return 422 } 423 sa.sa_flags |= _SA_ONSTACK 424 if rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) != 0 { 425 throw("rt_sigaction failure") 426 } 427 } 428 429 //go:nosplit 430 //go:nowritebarrierrec 431 func getsig(i int32) uintptr { 432 var sa sigactiont 433 if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 { 434 throw("rt_sigaction read failure") 435 } 436 if sa.sa_handler == funcPC(sigtramp) || sa.sa_handler == funcPC(cgoSigtramp) { 437 return funcPC(sighandler) 438 } 439 return sa.sa_handler 440 } 441 442 //go:nosplit 443 func signalstack(s *stack) { 444 var st sigaltstackt 445 if s == nil { 446 st.ss_flags = _SS_DISABLE 447 } else { 448 st.ss_sp = (*byte)(unsafe.Pointer(s.lo)) 449 st.ss_size = s.hi - s.lo 450 st.ss_flags = 0 451 } 452 sigaltstack(&st, nil) 453 } 454 455 //go:nosplit 456 //go:nowritebarrierrec 457 func updatesigmask(m sigmask) { 458 var mask sigset 459 sigcopyset(&mask, m) 460 rtsigprocmask(_SIG_SETMASK, &mask, nil, int32(unsafe.Sizeof(mask))) 461 } 462 463 func unblocksig(sig int32) { 464 var mask sigset 465 sigaddset(&mask, int(sig)) 466 rtsigprocmask(_SIG_UNBLOCK, &mask, nil, int32(unsafe.Sizeof(mask))) 467 }