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