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