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 5package runtime 6 7import ( 8 "internal/abi" 9 "internal/goarch" 10 "internal/runtime/atomic" 11 "unsafe" 12) 13 14//go:cgo_export_dynamic runtime.end _end 15//go:cgo_export_dynamic runtime.etext _etext 16//go:cgo_export_dynamic runtime.edata _edata 17 18//go:cgo_import_dynamic libc____errno ___errno "libc.so" 19//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so" 20//go:cgo_import_dynamic libc_exit _exit "libc.so" 21//go:cgo_import_dynamic libc_getcontext getcontext "libc.so" 22//go:cgo_import_dynamic libc_kill kill "libc.so" 23//go:cgo_import_dynamic libc_madvise madvise "libc.so" 24//go:cgo_import_dynamic libc_malloc malloc "libc.so" 25//go:cgo_import_dynamic libc_mmap mmap "libc.so" 26//go:cgo_import_dynamic libc_munmap munmap "libc.so" 27//go:cgo_import_dynamic libc_open open "libc.so" 28//go:cgo_import_dynamic libc_pthread_attr_destroy pthread_attr_destroy "libc.so" 29//go:cgo_import_dynamic libc_pthread_attr_getstack pthread_attr_getstack "libc.so" 30//go:cgo_import_dynamic libc_pthread_attr_init pthread_attr_init "libc.so" 31//go:cgo_import_dynamic libc_pthread_attr_setdetachstate pthread_attr_setdetachstate "libc.so" 32//go:cgo_import_dynamic libc_pthread_attr_setstack pthread_attr_setstack "libc.so" 33//go:cgo_import_dynamic libc_pthread_create pthread_create "libc.so" 34//go:cgo_import_dynamic libc_pthread_self pthread_self "libc.so" 35//go:cgo_import_dynamic libc_pthread_kill pthread_kill "libc.so" 36//go:cgo_import_dynamic libc_raise raise "libc.so" 37//go:cgo_import_dynamic libc_read read "libc.so" 38//go:cgo_import_dynamic libc_select select "libc.so" 39//go:cgo_import_dynamic libc_sched_yield sched_yield "libc.so" 40//go:cgo_import_dynamic libc_sem_init sem_init "libc.so" 41//go:cgo_import_dynamic libc_sem_post sem_post "libc.so" 42//go:cgo_import_dynamic libc_sem_reltimedwait_np sem_reltimedwait_np "libc.so" 43//go:cgo_import_dynamic libc_sem_wait sem_wait "libc.so" 44//go:cgo_import_dynamic libc_setitimer setitimer "libc.so" 45//go:cgo_import_dynamic libc_sigaction sigaction "libc.so" 46//go:cgo_import_dynamic libc_sigaltstack sigaltstack "libc.so" 47//go:cgo_import_dynamic libc_sigprocmask sigprocmask "libc.so" 48//go:cgo_import_dynamic libc_sysconf sysconf "libc.so" 49//go:cgo_import_dynamic libc_usleep usleep "libc.so" 50//go:cgo_import_dynamic libc_write write "libc.so" 51//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so" 52 53//go:linkname libc____errno libc____errno 54//go:linkname libc_clock_gettime libc_clock_gettime 55//go:linkname libc_exit libc_exit 56//go:linkname libc_getcontext libc_getcontext 57//go:linkname libc_kill libc_kill 58//go:linkname libc_madvise libc_madvise 59//go:linkname libc_malloc libc_malloc 60//go:linkname libc_mmap libc_mmap 61//go:linkname libc_munmap libc_munmap 62//go:linkname libc_open libc_open 63//go:linkname libc_pthread_attr_destroy libc_pthread_attr_destroy 64//go:linkname libc_pthread_attr_getstack libc_pthread_attr_getstack 65//go:linkname libc_pthread_attr_init libc_pthread_attr_init 66//go:linkname libc_pthread_attr_setdetachstate libc_pthread_attr_setdetachstate 67//go:linkname libc_pthread_attr_setstack libc_pthread_attr_setstack 68//go:linkname libc_pthread_create libc_pthread_create 69//go:linkname libc_pthread_self libc_pthread_self 70//go:linkname libc_pthread_kill libc_pthread_kill 71//go:linkname libc_raise libc_raise 72//go:linkname libc_read libc_read 73//go:linkname libc_select libc_select 74//go:linkname libc_sched_yield libc_sched_yield 75//go:linkname libc_sem_init libc_sem_init 76//go:linkname libc_sem_post libc_sem_post 77//go:linkname libc_sem_reltimedwait_np libc_sem_reltimedwait_np 78//go:linkname libc_sem_wait libc_sem_wait 79//go:linkname libc_setitimer libc_setitimer 80//go:linkname libc_sigaction libc_sigaction 81//go:linkname libc_sigaltstack libc_sigaltstack 82//go:linkname libc_sigprocmask libc_sigprocmask 83//go:linkname libc_sysconf libc_sysconf 84//go:linkname libc_usleep libc_usleep 85//go:linkname libc_write libc_write 86//go:linkname libc_pipe2 libc_pipe2 87 88var ( 89 libc____errno, 90 libc_clock_gettime, 91 libc_exit, 92 libc_getcontext, 93 libc_kill, 94 libc_madvise, 95 libc_malloc, 96 libc_mmap, 97 libc_munmap, 98 libc_open, 99 libc_pthread_attr_destroy, 100 libc_pthread_attr_getstack, 101 libc_pthread_attr_init, 102 libc_pthread_attr_setdetachstate, 103 libc_pthread_attr_setstack, 104 libc_pthread_create, 105 libc_pthread_self, 106 libc_pthread_kill, 107 libc_raise, 108 libc_read, 109 libc_sched_yield, 110 libc_select, 111 libc_sem_init, 112 libc_sem_post, 113 libc_sem_reltimedwait_np, 114 libc_sem_wait, 115 libc_setitimer, 116 libc_sigaction, 117 libc_sigaltstack, 118 libc_sigprocmask, 119 libc_sysconf, 120 libc_usleep, 121 libc_write, 122 libc_pipe2 libcFunc 123) 124 125var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}} 126 127func getPageSize() uintptr { 128 n := int32(sysconf(__SC_PAGESIZE)) 129 if n <= 0 { 130 return 0 131 } 132 return uintptr(n) 133} 134 135func osinit() { 136 // Call miniterrno so that we can safely make system calls 137 // before calling minit on m0. 138 asmcgocall(unsafe.Pointer(abi.FuncPCABI0(miniterrno)), unsafe.Pointer(&libc____errno)) 139 140 ncpu = getncpu() 141 if physPageSize == 0 { 142 physPageSize = getPageSize() 143 } 144} 145 146func tstart_sysvicall(newm *m) uint32 147 148// May run with m.p==nil, so write barriers are not allowed. 149// 150//go:nowritebarrier 151func newosproc(mp *m) { 152 var ( 153 attr pthreadattr 154 oset sigset 155 tid pthread 156 ret int32 157 size uint64 158 ) 159 160 if pthread_attr_init(&attr) != 0 { 161 throw("pthread_attr_init") 162 } 163 // Allocate a new 2MB stack. 164 if pthread_attr_setstack(&attr, 0, 0x200000) != 0 { 165 throw("pthread_attr_setstack") 166 } 167 // Read back the allocated stack. 168 if pthread_attr_getstack(&attr, unsafe.Pointer(&mp.g0.stack.hi), &size) != 0 { 169 throw("pthread_attr_getstack") 170 } 171 mp.g0.stack.lo = mp.g0.stack.hi - uintptr(size) 172 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 { 173 throw("pthread_attr_setdetachstate") 174 } 175 176 // Disable signals during create, so that the new thread starts 177 // with signals disabled. It will enable them in minit. 178 sigprocmask(_SIG_SETMASK, &sigset_all, &oset) 179 ret = retryOnEAGAIN(func() int32 { 180 return pthread_create(&tid, &attr, abi.FuncPCABI0(tstart_sysvicall), unsafe.Pointer(mp)) 181 }) 182 sigprocmask(_SIG_SETMASK, &oset, nil) 183 if ret != 0 { 184 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", ret, ")\n") 185 if ret == _EAGAIN { 186 println("runtime: may need to increase max user processes (ulimit -u)") 187 } 188 throw("newosproc") 189 } 190} 191 192func exitThread(wait *atomic.Uint32) { 193 // We should never reach exitThread on Solaris because we let 194 // libc clean up threads. 195 throw("exitThread") 196} 197 198var urandom_dev = []byte("/dev/urandom\x00") 199 200//go:nosplit 201func readRandom(r []byte) int { 202 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 203 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 204 closefd(fd) 205 return int(n) 206} 207 208func goenvs() { 209 goenvs_unix() 210} 211 212// Called to initialize a new m (including the bootstrap m). 213// Called on the parent thread (main thread in case of bootstrap), can allocate memory. 214func mpreinit(mp *m) { 215 mp.gsignal = malg(32 * 1024) 216 mp.gsignal.m = mp 217} 218 219func miniterrno() 220 221// Called to initialize a new m (including the bootstrap m). 222// Called on the new thread, cannot allocate memory. 223func minit() { 224 asmcgocall(unsafe.Pointer(abi.FuncPCABI0(miniterrno)), unsafe.Pointer(&libc____errno)) 225 226 minitSignals() 227 228 getg().m.procid = uint64(pthread_self()) 229} 230 231// Called from dropm to undo the effect of an minit. 232func unminit() { 233 unminitSignals() 234 getg().m.procid = 0 235} 236 237// Called from exitm, but not from drop, to undo the effect of thread-owned 238// resources in minit, semacreate, or elsewhere. Do not take locks after calling this. 239func mdestroy(mp *m) { 240} 241 242func sigtramp() 243 244//go:nosplit 245//go:nowritebarrierrec 246func setsig(i uint32, fn uintptr) { 247 var sa sigactiont 248 249 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART 250 sa.sa_mask = sigset_all 251 if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go 252 fn = abi.FuncPCABI0(sigtramp) 253 } 254 *((*uintptr)(unsafe.Pointer(&sa._funcptr))) = fn 255 sigaction(i, &sa, nil) 256} 257 258//go:nosplit 259//go:nowritebarrierrec 260func setsigstack(i uint32) { 261 var sa sigactiont 262 sigaction(i, nil, &sa) 263 if sa.sa_flags&_SA_ONSTACK != 0 { 264 return 265 } 266 sa.sa_flags |= _SA_ONSTACK 267 sigaction(i, &sa, nil) 268} 269 270//go:nosplit 271//go:nowritebarrierrec 272func getsig(i uint32) uintptr { 273 var sa sigactiont 274 sigaction(i, nil, &sa) 275 return *((*uintptr)(unsafe.Pointer(&sa._funcptr))) 276} 277 278// setSignalstackSP sets the ss_sp field of a stackt. 279// 280//go:nosplit 281func setSignalstackSP(s *stackt, sp uintptr) { 282 *(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp 283} 284 285//go:nosplit 286//go:nowritebarrierrec 287func sigaddset(mask *sigset, i int) { 288 mask.__sigbits[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31) 289} 290 291func sigdelset(mask *sigset, i int) { 292 mask.__sigbits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31) 293} 294 295//go:nosplit 296func (c *sigctxt) fixsigcode(sig uint32) { 297} 298 299func setProcessCPUProfiler(hz int32) { 300 setProcessCPUProfilerTimer(hz) 301} 302 303func setThreadCPUProfiler(hz int32) { 304 setThreadCPUProfilerHz(hz) 305} 306 307//go:nosplit 308func validSIGPROF(mp *m, c *sigctxt) bool { 309 return true 310} 311 312//go:nosplit 313func semacreate(mp *m) { 314 if mp.waitsema != 0 { 315 return 316 } 317 318 var sem *semt 319 320 // Call libc's malloc rather than malloc. This will 321 // allocate space on the C heap. We can't call malloc 322 // here because it could cause a deadlock. 323 mp.libcall.fn = uintptr(unsafe.Pointer(&libc_malloc)) 324 mp.libcall.n = 1 325 mp.scratch = mscratch{} 326 mp.scratch.v[0] = unsafe.Sizeof(*sem) 327 mp.libcall.args = uintptr(unsafe.Pointer(&mp.scratch)) 328 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&mp.libcall)) 329 sem = (*semt)(unsafe.Pointer(mp.libcall.r1)) 330 if sem_init(sem, 0, 0) != 0 { 331 throw("sem_init") 332 } 333 mp.waitsema = uintptr(unsafe.Pointer(sem)) 334} 335 336//go:nosplit 337func semasleep(ns int64) int32 { 338 mp := getg().m 339 if ns >= 0 { 340 mp.ts.tv_sec = ns / 1000000000 341 mp.ts.tv_nsec = ns % 1000000000 342 343 mp.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_reltimedwait_np)) 344 mp.libcall.n = 2 345 mp.scratch = mscratch{} 346 mp.scratch.v[0] = mp.waitsema 347 mp.scratch.v[1] = uintptr(unsafe.Pointer(&mp.ts)) 348 mp.libcall.args = uintptr(unsafe.Pointer(&mp.scratch)) 349 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&mp.libcall)) 350 if *mp.perrno != 0 { 351 if *mp.perrno == _ETIMEDOUT || *mp.perrno == _EAGAIN || *mp.perrno == _EINTR { 352 return -1 353 } 354 throw("sem_reltimedwait_np") 355 } 356 return 0 357 } 358 for { 359 mp.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_wait)) 360 mp.libcall.n = 1 361 mp.scratch = mscratch{} 362 mp.scratch.v[0] = mp.waitsema 363 mp.libcall.args = uintptr(unsafe.Pointer(&mp.scratch)) 364 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&mp.libcall)) 365 if mp.libcall.r1 == 0 { 366 break 367 } 368 if *mp.perrno == _EINTR { 369 continue 370 } 371 throw("sem_wait") 372 } 373 return 0 374} 375 376//go:nosplit 377func semawakeup(mp *m) { 378 if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 { 379 throw("sem_post") 380 } 381} 382 383//go:nosplit 384func closefd(fd int32) int32 { 385 return int32(sysvicall1(&libc_close, uintptr(fd))) 386} 387 388//go:nosplit 389func exit(r int32) { 390 sysvicall1(&libc_exit, uintptr(r)) 391} 392 393//go:nosplit 394func getcontext(context *ucontext) /* int32 */ { 395 sysvicall1(&libc_getcontext, uintptr(unsafe.Pointer(context))) 396} 397 398//go:nosplit 399func madvise(addr unsafe.Pointer, n uintptr, flags int32) { 400 sysvicall3(&libc_madvise, uintptr(addr), uintptr(n), uintptr(flags)) 401} 402 403//go:nosplit 404func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (unsafe.Pointer, int) { 405 p, err := doMmap(uintptr(addr), n, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off)) 406 if p == ^uintptr(0) { 407 return nil, int(err) 408 } 409 return unsafe.Pointer(p), 0 410} 411 412//go:nosplit 413//go:cgo_unsafe_args 414func doMmap(addr, n, prot, flags, fd, off uintptr) (uintptr, uintptr) { 415 var libcall libcall 416 libcall.fn = uintptr(unsafe.Pointer(&libc_mmap)) 417 libcall.n = 6 418 libcall.args = uintptr(noescape(unsafe.Pointer(&addr))) 419 asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall)) 420 return libcall.r1, libcall.err 421} 422 423//go:nosplit 424func munmap(addr unsafe.Pointer, n uintptr) { 425 sysvicall2(&libc_munmap, uintptr(addr), uintptr(n)) 426} 427 428const ( 429 _CLOCK_REALTIME = 3 430 _CLOCK_MONOTONIC = 4 431) 432 433//go:nosplit 434func nanotime1() int64 { 435 var ts mts 436 sysvicall2(&libc_clock_gettime, _CLOCK_MONOTONIC, uintptr(unsafe.Pointer(&ts))) 437 return ts.tv_sec*1e9 + ts.tv_nsec 438} 439 440//go:nosplit 441func open(path *byte, mode, perm int32) int32 { 442 return int32(sysvicall3(&libc_open, uintptr(unsafe.Pointer(path)), uintptr(mode), uintptr(perm))) 443} 444 445func pthread_attr_destroy(attr *pthreadattr) int32 { 446 return int32(sysvicall1(&libc_pthread_attr_destroy, uintptr(unsafe.Pointer(attr)))) 447} 448 449func pthread_attr_getstack(attr *pthreadattr, addr unsafe.Pointer, size *uint64) int32 { 450 return int32(sysvicall3(&libc_pthread_attr_getstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(unsafe.Pointer(size)))) 451} 452 453func pthread_attr_init(attr *pthreadattr) int32 { 454 return int32(sysvicall1(&libc_pthread_attr_init, uintptr(unsafe.Pointer(attr)))) 455} 456 457func pthread_attr_setdetachstate(attr *pthreadattr, state int32) int32 { 458 return int32(sysvicall2(&libc_pthread_attr_setdetachstate, uintptr(unsafe.Pointer(attr)), uintptr(state))) 459} 460 461func pthread_attr_setstack(attr *pthreadattr, addr uintptr, size uint64) int32 { 462 return int32(sysvicall3(&libc_pthread_attr_setstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(size))) 463} 464 465func pthread_create(thread *pthread, attr *pthreadattr, fn uintptr, arg unsafe.Pointer) int32 { 466 return int32(sysvicall4(&libc_pthread_create, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(fn), uintptr(arg))) 467} 468 469func pthread_self() pthread { 470 return pthread(sysvicall0(&libc_pthread_self)) 471} 472 473func signalM(mp *m, sig int) { 474 sysvicall2(&libc_pthread_kill, uintptr(pthread(mp.procid)), uintptr(sig)) 475} 476 477//go:nosplit 478//go:nowritebarrierrec 479func raise(sig uint32) /* int32 */ { 480 sysvicall1(&libc_raise, uintptr(sig)) 481} 482 483func raiseproc(sig uint32) /* int32 */ { 484 pid := sysvicall0(&libc_getpid) 485 sysvicall2(&libc_kill, pid, uintptr(sig)) 486} 487 488//go:nosplit 489func read(fd int32, buf unsafe.Pointer, nbyte int32) int32 { 490 r1, err := sysvicall3Err(&libc_read, uintptr(fd), uintptr(buf), uintptr(nbyte)) 491 if c := int32(r1); c >= 0 { 492 return c 493 } 494 return -int32(err) 495} 496 497//go:nosplit 498func sem_init(sem *semt, pshared int32, value uint32) int32 { 499 return int32(sysvicall3(&libc_sem_init, uintptr(unsafe.Pointer(sem)), uintptr(pshared), uintptr(value))) 500} 501 502//go:nosplit 503func sem_post(sem *semt) int32 { 504 return int32(sysvicall1(&libc_sem_post, uintptr(unsafe.Pointer(sem)))) 505} 506 507//go:nosplit 508func sem_reltimedwait_np(sem *semt, timeout *timespec) int32 { 509 return int32(sysvicall2(&libc_sem_reltimedwait_np, uintptr(unsafe.Pointer(sem)), uintptr(unsafe.Pointer(timeout)))) 510} 511 512//go:nosplit 513func sem_wait(sem *semt) int32 { 514 return int32(sysvicall1(&libc_sem_wait, uintptr(unsafe.Pointer(sem)))) 515} 516 517func setitimer(which int32, value *itimerval, ovalue *itimerval) /* int32 */ { 518 sysvicall3(&libc_setitimer, uintptr(which), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(ovalue))) 519} 520 521//go:nosplit 522//go:nowritebarrierrec 523func sigaction(sig uint32, act *sigactiont, oact *sigactiont) /* int32 */ { 524 sysvicall3(&libc_sigaction, uintptr(sig), uintptr(unsafe.Pointer(act)), uintptr(unsafe.Pointer(oact))) 525} 526 527//go:nosplit 528//go:nowritebarrierrec 529func sigaltstack(ss *stackt, oss *stackt) /* int32 */ { 530 sysvicall2(&libc_sigaltstack, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(oss))) 531} 532 533//go:nosplit 534//go:nowritebarrierrec 535func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ { 536 sysvicall3(&libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset))) 537} 538 539func sysconf(name int32) int64 { 540 return int64(sysvicall1(&libc_sysconf, uintptr(name))) 541} 542 543func usleep1(usec uint32) 544 545//go:nosplit 546func usleep_no_g(µs uint32) { 547 usleep1(µs) 548} 549 550//go:nosplit 551func usleep(µs uint32) { 552 usleep1(µs) 553} 554 555func walltime() (sec int64, nsec int32) { 556 var ts mts 557 sysvicall2(&libc_clock_gettime, _CLOCK_REALTIME, uintptr(unsafe.Pointer(&ts))) 558 return ts.tv_sec, int32(ts.tv_nsec) 559} 560 561//go:nosplit 562func write1(fd uintptr, buf unsafe.Pointer, nbyte int32) int32 { 563 r1, err := sysvicall3Err(&libc_write, fd, uintptr(buf), uintptr(nbyte)) 564 if c := int32(r1); c >= 0 { 565 return c 566 } 567 return -int32(err) 568} 569 570//go:nosplit 571func pipe2(flags int32) (r, w int32, errno int32) { 572 var p [2]int32 573 _, e := sysvicall2Err(&libc_pipe2, uintptr(noescape(unsafe.Pointer(&p))), uintptr(flags)) 574 return p[0], p[1], int32(e) 575} 576 577//go:nosplit 578func fcntl(fd, cmd, arg int32) (ret int32, errno int32) { 579 r1, err := sysvicall3Err(&libc_fcntl, uintptr(fd), uintptr(cmd), uintptr(arg)) 580 return int32(r1), int32(err) 581} 582 583func osyield1() 584 585//go:nosplit 586func osyield_no_g() { 587 osyield1() 588} 589 590//go:nosplit 591func osyield() { 592 sysvicall0(&libc_sched_yield) 593} 594 595//go:linkname executablePath os.executablePath 596var executablePath string 597 598func sysargs(argc int32, argv **byte) { 599 n := argc + 1 600 601 // skip over argv, envp to get to auxv 602 for argv_index(argv, n) != nil { 603 n++ 604 } 605 606 // skip NULL separator 607 n++ 608 609 // now argv+n is auxv 610 auxvp := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize)) 611 pairs := sysauxv(auxvp[:]) 612 auxv = auxvp[: pairs*2 : pairs*2] 613} 614 615const ( 616 _AT_NULL = 0 // Terminates the vector 617 _AT_PAGESZ = 6 // Page size in bytes 618 _AT_SUN_EXECNAME = 2014 // exec() path name 619) 620 621func sysauxv(auxv []uintptr) (pairs int) { 622 var i int 623 for i = 0; auxv[i] != _AT_NULL; i += 2 { 624 tag, val := auxv[i], auxv[i+1] 625 switch tag { 626 case _AT_PAGESZ: 627 physPageSize = val 628 case _AT_SUN_EXECNAME: 629 executablePath = gostringnocopy((*byte)(unsafe.Pointer(val))) 630 } 631 } 632 return i / 2 633} 634 635// sigPerThreadSyscall is only used on linux, so we assign a bogus signal 636// number. 637const sigPerThreadSyscall = 1 << 31 638 639//go:nosplit 640func runPerThreadSyscall() { 641 throw("runPerThreadSyscall only valid on linux") 642} 643