rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/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 "unsafe" 8 9 //go:cgo_export_dynamic runtime.end _end 10 //go:cgo_export_dynamic runtime.etext _etext 11 //go:cgo_export_dynamic runtime.edata _edata 12 13 //go:cgo_import_dynamic libc____errno ___errno "libc.so" 14 //go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so" 15 //go:cgo_import_dynamic libc_close close "libc.so" 16 //go:cgo_import_dynamic libc_exit exit "libc.so" 17 //go:cgo_import_dynamic libc_fstat fstat "libc.so" 18 //go:cgo_import_dynamic libc_getcontext getcontext "libc.so" 19 //go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so" 20 //go:cgo_import_dynamic libc_madvise madvise "libc.so" 21 //go:cgo_import_dynamic libc_malloc malloc "libc.so" 22 //go:cgo_import_dynamic libc_mmap mmap "libc.so" 23 //go:cgo_import_dynamic libc_munmap munmap "libc.so" 24 //go:cgo_import_dynamic libc_open open "libc.so" 25 //go:cgo_import_dynamic libc_pthread_attr_destroy pthread_attr_destroy "libc.so" 26 //go:cgo_import_dynamic libc_pthread_attr_getstack pthread_attr_getstack "libc.so" 27 //go:cgo_import_dynamic libc_pthread_attr_init pthread_attr_init "libc.so" 28 //go:cgo_import_dynamic libc_pthread_attr_setdetachstate pthread_attr_setdetachstate "libc.so" 29 //go:cgo_import_dynamic libc_pthread_attr_setstack pthread_attr_setstack "libc.so" 30 //go:cgo_import_dynamic libc_pthread_create pthread_create "libc.so" 31 //go:cgo_import_dynamic libc_raise raise "libc.so" 32 //go:cgo_import_dynamic libc_read read "libc.so" 33 //go:cgo_import_dynamic libc_select select "libc.so" 34 //go:cgo_import_dynamic libc_sched_yield sched_yield "libc.so" 35 //go:cgo_import_dynamic libc_sem_init sem_init "libc.so" 36 //go:cgo_import_dynamic libc_sem_post sem_post "libc.so" 37 //go:cgo_import_dynamic libc_sem_reltimedwait_np sem_reltimedwait_np "libc.so" 38 //go:cgo_import_dynamic libc_sem_wait sem_wait "libc.so" 39 //go:cgo_import_dynamic libc_setitimer setitimer "libc.so" 40 //go:cgo_import_dynamic libc_sigaction sigaction "libc.so" 41 //go:cgo_import_dynamic libc_sigaltstack sigaltstack "libc.so" 42 //go:cgo_import_dynamic libc_sigprocmask sigprocmask "libc.so" 43 //go:cgo_import_dynamic libc_sysconf sysconf "libc.so" 44 //go:cgo_import_dynamic libc_usleep usleep "libc.so" 45 //go:cgo_import_dynamic libc_write write "libc.so" 46 47 //go:linkname libc____errno libc____errno 48 //go:linkname libc_clock_gettime libc_clock_gettime 49 //go:linkname libc_close libc_close 50 //go:linkname libc_exit libc_exit 51 //go:linkname libc_fstat libc_fstat 52 //go:linkname libc_getcontext libc_getcontext 53 //go:linkname libc_getrlimit libc_getrlimit 54 //go:linkname libc_madvise libc_madvise 55 //go:linkname libc_malloc libc_malloc 56 //go:linkname libc_mmap libc_mmap 57 //go:linkname libc_munmap libc_munmap 58 //go:linkname libc_open libc_open 59 //go:linkname libc_pthread_attr_destroy libc_pthread_attr_destroy 60 //go:linkname libc_pthread_attr_getstack libc_pthread_attr_getstack 61 //go:linkname libc_pthread_attr_init libc_pthread_attr_init 62 //go:linkname libc_pthread_attr_setdetachstate libc_pthread_attr_setdetachstate 63 //go:linkname libc_pthread_attr_setstack libc_pthread_attr_setstack 64 //go:linkname libc_pthread_create libc_pthread_create 65 //go:linkname libc_raise libc_raise 66 //go:linkname libc_read libc_read 67 //go:linkname libc_select libc_select 68 //go:linkname libc_sched_yield libc_sched_yield 69 //go:linkname libc_sem_init libc_sem_init 70 //go:linkname libc_sem_post libc_sem_post 71 //go:linkname libc_sem_reltimedwait_np libc_sem_reltimedwait_np 72 //go:linkname libc_sem_wait libc_sem_wait 73 //go:linkname libc_setitimer libc_setitimer 74 //go:linkname libc_sigaction libc_sigaction 75 //go:linkname libc_sigaltstack libc_sigaltstack 76 //go:linkname libc_sigprocmask libc_sigprocmask 77 //go:linkname libc_sysconf libc_sysconf 78 //go:linkname libc_usleep libc_usleep 79 //go:linkname libc_write libc_write 80 81 var ( 82 libc____errno, 83 libc_clock_gettime, 84 libc_close, 85 libc_exit, 86 libc_fstat, 87 libc_getcontext, 88 libc_getrlimit, 89 libc_madvise, 90 libc_malloc, 91 libc_mmap, 92 libc_munmap, 93 libc_open, 94 libc_pthread_attr_destroy, 95 libc_pthread_attr_getstack, 96 libc_pthread_attr_init, 97 libc_pthread_attr_setdetachstate, 98 libc_pthread_attr_setstack, 99 libc_pthread_create, 100 libc_raise, 101 libc_read, 102 libc_sched_yield, 103 libc_select, 104 libc_sem_init, 105 libc_sem_post, 106 libc_sem_reltimedwait_np, 107 libc_sem_wait, 108 libc_setitimer, 109 libc_sigaction, 110 libc_sigaltstack, 111 libc_sigprocmask, 112 libc_sysconf, 113 libc_usleep, 114 libc_write libcFunc 115 ) 116 117 var sigset_none = sigset{} 118 var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}} 119 120 func getncpu() int32 { 121 n := int32(sysconf(__SC_NPROCESSORS_ONLN)) 122 if n < 1 { 123 return 1 124 } 125 return n 126 } 127 128 func osinit() { 129 ncpu = getncpu() 130 } 131 132 func tstart_sysvicall() 133 134 // May run with m.p==nil, so write barriers are not allowed. 135 //go:nowritebarrier 136 func newosproc(mp *m, _ unsafe.Pointer) { 137 var ( 138 attr pthreadattr 139 oset sigset 140 tid pthread 141 ret int32 142 size uint64 143 ) 144 145 if pthread_attr_init(&attr) != 0 { 146 throw("pthread_attr_init") 147 } 148 if pthread_attr_setstack(&attr, 0, 0x200000) != 0 { 149 throw("pthread_attr_setstack") 150 } 151 if pthread_attr_getstack(&attr, unsafe.Pointer(&mp.g0.stack.hi), &size) != 0 { 152 throw("pthread_attr_getstack") 153 } 154 mp.g0.stack.lo = mp.g0.stack.hi - uintptr(size) 155 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 { 156 throw("pthread_attr_setdetachstate") 157 } 158 159 // Disable signals during create, so that the new thread starts 160 // with signals disabled. It will enable them in minit. 161 sigprocmask(_SIG_SETMASK, &sigset_all, &oset) 162 ret = pthread_create(&tid, &attr, funcPC(tstart_sysvicall), unsafe.Pointer(mp)) 163 sigprocmask(_SIG_SETMASK, &oset, nil) 164 if ret != 0 { 165 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", ret, ")\n") 166 throw("newosproc") 167 } 168 } 169 170 var urandom_dev = []byte("/dev/urandom\x00") 171 172 //go:nosplit 173 func getRandomData(r []byte) { 174 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 175 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 176 closefd(fd) 177 extendRandom(r, int(n)) 178 } 179 180 func goenvs() { 181 goenvs_unix() 182 } 183 184 // Called to initialize a new m (including the bootstrap m). 185 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 186 func mpreinit(mp *m) { 187 mp.gsignal = malg(32 * 1024) 188 mp.gsignal.m = mp 189 } 190 191 func miniterrno() 192 193 // Called to initialize a new m (including the bootstrap m). 194 // Called on the new thread, can not allocate memory. 195 func minit() { 196 _g_ := getg() 197 asmcgocall(unsafe.Pointer(funcPC(miniterrno)), unsafe.Pointer(libc____errno)) 198 // Initialize signal handling 199 signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024) 200 sigprocmask(_SIG_SETMASK, &sigset_none, nil) 201 } 202 203 // Called from dropm to undo the effect of an minit. 204 func unminit() { 205 signalstack(nil, 0) 206 } 207 208 func memlimit() uintptr { 209 /* 210 TODO: Convert to Go when something actually uses the result. 211 Rlimit rl; 212 extern byte runtime·text[], runtime·end[]; 213 uintptr used; 214 215 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0) 216 return 0; 217 if(rl.rlim_cur >= 0x7fffffff) 218 return 0; 219 220 // Estimate our VM footprint excluding the heap. 221 // Not an exact science: use size of binary plus 222 // some room for thread stacks. 223 used = runtime·end - runtime·text + (64<<20); 224 if(used >= rl.rlim_cur) 225 return 0; 226 227 // If there's not at least 16 MB left, we're probably 228 // not going to be able to do much. Treat as no limit. 229 rl.rlim_cur -= used; 230 if(rl.rlim_cur < (16<<20)) 231 return 0; 232 233 return rl.rlim_cur - used; 234 */ 235 236 return 0 237 } 238 239 func sigtramp() 240 241 func setsig(i int32, fn uintptr, restart bool) { 242 var sa sigactiont 243 244 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK 245 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK 246 if restart { 247 sa.sa_flags |= _SA_RESTART 248 } 249 sa.sa_mask = sigset_all 250 if fn == funcPC(sighandler) { 251 fn = funcPC(sigtramp) 252 } 253 *((*uintptr)(unsafe.Pointer(&sa._funcptr))) = fn 254 sigaction(i, &sa, nil) 255 } 256 257 func setsigstack(i int32) { 258 throw("setsigstack") 259 } 260 261 func getsig(i int32) uintptr { 262 var sa sigactiont 263 sigaction(i, nil, &sa) 264 if *((*uintptr)(unsafe.Pointer(&sa._funcptr))) == funcPC(sigtramp) { 265 return funcPC(sighandler) 266 } 267 return *((*uintptr)(unsafe.Pointer(&sa._funcptr))) 268 } 269 270 func signalstack(p *byte, n int32) { 271 var st sigaltstackt 272 st.ss_sp = (*byte)(unsafe.Pointer(p)) 273 st.ss_size = uint64(n) 274 st.ss_flags = 0 275 if p == nil { 276 st.ss_flags = _SS_DISABLE 277 } 278 sigaltstack(&st, nil) 279 } 280 281 func unblocksignals() { 282 sigprocmask(_SIG_SETMASK, &sigset_none, nil) 283 } 284 285 //go:nosplit 286 func semacreate() uintptr { 287 var sem *semt 288 _g_ := getg() 289 290 // Call libc's malloc rather than malloc. This will 291 // allocate space on the C heap. We can't call malloc 292 // here because it could cause a deadlock. 293 _g_.m.libcall.fn = uintptr(libc_malloc) 294 _g_.m.libcall.n = 1 295 memclr(unsafe.Pointer(&_g_.m.scratch), uintptr(len(_g_.m.scratch.v))) 296 _g_.m.scratch.v[0] = unsafe.Sizeof(*sem) 297 _g_.m.libcall.args = uintptr(unsafe.Pointer(&_g_.m.scratch)) 298 asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_g_.m.libcall)) 299 sem = (*semt)(unsafe.Pointer(_g_.m.libcall.r1)) 300 if sem_init(sem, 0, 0) != 0 { 301 throw("sem_init") 302 } 303 return uintptr(unsafe.Pointer(sem)) 304 } 305 306 //go:nosplit 307 func semasleep(ns int64) int32 { 308 _m_ := getg().m 309 if ns >= 0 { 310 _m_.ts.tv_sec = ns / 1000000000 311 _m_.ts.tv_nsec = ns % 1000000000 312 313 _m_.libcall.fn = uintptr(unsafe.Pointer(libc_sem_reltimedwait_np)) 314 _m_.libcall.n = 2 315 memclr(unsafe.Pointer(&_m_.scratch), uintptr(len(_m_.scratch.v))) 316 _m_.scratch.v[0] = _m_.waitsema 317 _m_.scratch.v[1] = uintptr(unsafe.Pointer(&_m_.ts)) 318 _m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch)) 319 asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_m_.libcall)) 320 if *_m_.perrno != 0 { 321 if *_m_.perrno == _ETIMEDOUT || *_m_.perrno == _EAGAIN || *_m_.perrno == _EINTR { 322 return -1 323 } 324 throw("sem_reltimedwait_np") 325 } 326 return 0 327 } 328 for { 329 _m_.libcall.fn = uintptr(unsafe.Pointer(libc_sem_wait)) 330 _m_.libcall.n = 1 331 memclr(unsafe.Pointer(&_m_.scratch), uintptr(len(_m_.scratch.v))) 332 _m_.scratch.v[0] = _m_.waitsema 333 _m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch)) 334 asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_m_.libcall)) 335 if _m_.libcall.r1 == 0 { 336 break 337 } 338 if *_m_.perrno == _EINTR { 339 continue 340 } 341 throw("sem_wait") 342 } 343 return 0 344 } 345 346 //go:nosplit 347 func semawakeup(mp *m) { 348 if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 { 349 throw("sem_post") 350 } 351 } 352 353 //go:nosplit 354 func closefd(fd int32) int32 { 355 return int32(sysvicall1(libc_close, uintptr(fd))) 356 } 357 358 //go:nosplit 359 func exit(r int32) { 360 sysvicall1(libc_exit, uintptr(r)) 361 } 362 363 //go:nosplit 364 func getcontext(context *ucontext) /* int32 */ { 365 sysvicall1(libc_getcontext, uintptr(unsafe.Pointer(context))) 366 } 367 368 //go:nosplit 369 func madvise(addr unsafe.Pointer, n uintptr, flags int32) { 370 sysvicall3(libc_madvise, uintptr(addr), uintptr(n), uintptr(flags)) 371 } 372 373 //go:nosplit 374 func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer { 375 return unsafe.Pointer(sysvicall6(libc_mmap, uintptr(addr), uintptr(n), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off))) 376 } 377 378 //go:nosplit 379 func munmap(addr unsafe.Pointer, n uintptr) { 380 sysvicall2(libc_munmap, uintptr(addr), uintptr(n)) 381 } 382 383 func nanotime1() 384 385 //go:nosplit 386 func nanotime() int64 { 387 return int64(sysvicall0(libcFunc(funcPC(nanotime1)))) 388 } 389 390 //go:nosplit 391 func open(path *byte, mode, perm int32) int32 { 392 return int32(sysvicall3(libc_open, uintptr(unsafe.Pointer(path)), uintptr(mode), uintptr(perm))) 393 } 394 395 func pthread_attr_destroy(attr *pthreadattr) int32 { 396 return int32(sysvicall1(libc_pthread_attr_destroy, uintptr(unsafe.Pointer(attr)))) 397 } 398 399 func pthread_attr_getstack(attr *pthreadattr, addr unsafe.Pointer, size *uint64) int32 { 400 return int32(sysvicall3(libc_pthread_attr_getstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(unsafe.Pointer(size)))) 401 } 402 403 func pthread_attr_init(attr *pthreadattr) int32 { 404 return int32(sysvicall1(libc_pthread_attr_init, uintptr(unsafe.Pointer(attr)))) 405 } 406 407 func pthread_attr_setdetachstate(attr *pthreadattr, state int32) int32 { 408 return int32(sysvicall2(libc_pthread_attr_setdetachstate, uintptr(unsafe.Pointer(attr)), uintptr(state))) 409 } 410 411 func pthread_attr_setstack(attr *pthreadattr, addr uintptr, size uint64) int32 { 412 return int32(sysvicall3(libc_pthread_attr_setstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(size))) 413 } 414 415 func pthread_create(thread *pthread, attr *pthreadattr, fn uintptr, arg unsafe.Pointer) int32 { 416 return int32(sysvicall4(libc_pthread_create, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(fn), uintptr(arg))) 417 } 418 419 func raise(sig int32) /* int32 */ { 420 sysvicall1(libc_raise, uintptr(sig)) 421 } 422 423 func raiseproc(sig int32) /* int32 */ { 424 sysvicall1(libc_raise, uintptr(sig)) 425 } 426 427 //go:nosplit 428 func read(fd int32, buf unsafe.Pointer, nbyte int32) int32 { 429 return int32(sysvicall3(libc_read, uintptr(fd), uintptr(buf), uintptr(nbyte))) 430 } 431 432 //go:nosplit 433 func sem_init(sem *semt, pshared int32, value uint32) int32 { 434 return int32(sysvicall3(libc_sem_init, uintptr(unsafe.Pointer(sem)), uintptr(pshared), uintptr(value))) 435 } 436 437 //go:nosplit 438 func sem_post(sem *semt) int32 { 439 return int32(sysvicall1(libc_sem_post, uintptr(unsafe.Pointer(sem)))) 440 } 441 442 //go:nosplit 443 func sem_reltimedwait_np(sem *semt, timeout *timespec) int32 { 444 return int32(sysvicall2(libc_sem_reltimedwait_np, uintptr(unsafe.Pointer(sem)), uintptr(unsafe.Pointer(timeout)))) 445 } 446 447 //go:nosplit 448 func sem_wait(sem *semt) int32 { 449 return int32(sysvicall1(libc_sem_wait, uintptr(unsafe.Pointer(sem)))) 450 } 451 452 func setitimer(which int32, value *itimerval, ovalue *itimerval) /* int32 */ { 453 sysvicall3(libc_setitimer, uintptr(which), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(ovalue))) 454 } 455 456 func sigaction(sig int32, act *sigactiont, oact *sigactiont) /* int32 */ { 457 sysvicall3(libc_sigaction, uintptr(sig), uintptr(unsafe.Pointer(act)), uintptr(unsafe.Pointer(oact))) 458 } 459 460 func sigaltstack(ss *sigaltstackt, oss *sigaltstackt) /* int32 */ { 461 sysvicall2(libc_sigaltstack, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(oss))) 462 } 463 464 func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ { 465 sysvicall3(libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset))) 466 } 467 468 func sysconf(name int32) int64 { 469 return int64(sysvicall1(libc_sysconf, uintptr(name))) 470 } 471 472 func usleep1(uint32) 473 474 //go:nosplit 475 func usleep(µs uint32) { 476 usleep1(µs) 477 } 478 479 //go:nosplit 480 func write(fd uintptr, buf unsafe.Pointer, nbyte int32) int32 { 481 return int32(sysvicall3(libc_write, uintptr(fd), uintptr(buf), uintptr(nbyte))) 482 } 483 484 func osyield1() 485 486 //go:nosplit 487 func osyield() { 488 _g_ := getg() 489 490 // Check the validity of m because we might be called in cgo callback 491 // path early enough where there isn't a m available yet. 492 if _g_ != nil && _g_.m != nil { 493 sysvicall0(libc_sched_yield) 494 return 495 } 496 osyield1() 497 }