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