github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/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 func newosproc(mp *m, _ unsafe.Pointer) { 135 var ( 136 attr pthreadattr 137 oset sigset 138 tid pthread 139 ret int32 140 size uint64 141 ) 142 143 if pthread_attr_init(&attr) != 0 { 144 throw("pthread_attr_init") 145 } 146 if pthread_attr_setstack(&attr, 0, 0x200000) != 0 { 147 throw("pthread_attr_setstack") 148 } 149 if pthread_attr_getstack(&attr, unsafe.Pointer(&mp.g0.stack.hi), &size) != 0 { 150 throw("pthread_attr_getstack") 151 } 152 mp.g0.stack.lo = mp.g0.stack.hi - uintptr(size) 153 if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 { 154 throw("pthread_attr_setdetachstate") 155 } 156 157 // Disable signals during create, so that the new thread starts 158 // with signals disabled. It will enable them in minit. 159 sigprocmask(_SIG_SETMASK, &sigset_all, &oset) 160 ret = pthread_create(&tid, &attr, funcPC(tstart_sysvicall), unsafe.Pointer(mp)) 161 sigprocmask(_SIG_SETMASK, &oset, nil) 162 if ret != 0 { 163 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", ret, ")\n") 164 throw("newosproc") 165 } 166 } 167 168 var urandom_dev = []byte("/dev/urandom\x00") 169 170 //go:nosplit 171 func getRandomData(r []byte) { 172 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) 173 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 174 close(fd) 175 extendRandom(r, int(n)) 176 } 177 178 func goenvs() { 179 goenvs_unix() 180 } 181 182 // Called to initialize a new m (including the bootstrap m). 183 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 184 func mpreinit(mp *m) { 185 mp.gsignal = malg(32 * 1024) 186 mp.gsignal.m = mp 187 } 188 189 func miniterrno() 190 191 // Called to initialize a new m (including the bootstrap m). 192 // Called on the new thread, can not allocate memory. 193 func minit() { 194 _g_ := getg() 195 asmcgocall(unsafe.Pointer(funcPC(miniterrno)), unsafe.Pointer(libc____errno)) 196 // Initialize signal handling 197 signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024) 198 sigprocmask(_SIG_SETMASK, &sigset_none, nil) 199 } 200 201 // Called from dropm to undo the effect of an minit. 202 func unminit() { 203 signalstack(nil, 0) 204 } 205 206 func memlimit() uintptr { 207 /* 208 TODO: Convert to Go when something actually uses the result. 209 Rlimit rl; 210 extern byte runtime·text[], runtime·end[]; 211 uintptr used; 212 213 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0) 214 return 0; 215 if(rl.rlim_cur >= 0x7fffffff) 216 return 0; 217 218 // Estimate our VM footprint excluding the heap. 219 // Not an exact science: use size of binary plus 220 // some room for thread stacks. 221 used = runtime·end - runtime·text + (64<<20); 222 if(used >= rl.rlim_cur) 223 return 0; 224 225 // If there's not at least 16 MB left, we're probably 226 // not going to be able to do much. Treat as no limit. 227 rl.rlim_cur -= used; 228 if(rl.rlim_cur < (16<<20)) 229 return 0; 230 231 return rl.rlim_cur - used; 232 */ 233 234 return 0 235 } 236 237 func sigtramp() 238 239 func setsig(i int32, fn uintptr, restart bool) { 240 var sa sigactiont 241 242 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK 243 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK 244 if restart { 245 sa.sa_flags |= _SA_RESTART 246 } 247 sa.sa_mask = sigset_all 248 if fn == funcPC(sighandler) { 249 fn = funcPC(sigtramp) 250 } 251 *((*uintptr)(unsafe.Pointer(&sa._funcptr))) = fn 252 sigaction(i, &sa, nil) 253 } 254 255 func setsigstack(i int32) { 256 throw("setsigstack") 257 } 258 259 func getsig(i int32) uintptr { 260 var sa sigactiont 261 sigaction(i, nil, &sa) 262 if *((*uintptr)(unsafe.Pointer(&sa._funcptr))) == funcPC(sigtramp) { 263 return funcPC(sighandler) 264 } 265 return *((*uintptr)(unsafe.Pointer(&sa._funcptr))) 266 } 267 268 func signalstack(p *byte, n int32) { 269 var st sigaltstackt 270 st.ss_sp = (*byte)(unsafe.Pointer(p)) 271 st.ss_size = uint64(n) 272 st.ss_flags = 0 273 if p == nil { 274 st.ss_flags = _SS_DISABLE 275 } 276 sigaltstack(&st, nil) 277 } 278 279 func unblocksignals() { 280 sigprocmask(_SIG_SETMASK, &sigset_none, nil) 281 } 282 283 //go:nosplit 284 func semacreate() uintptr { 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(libc_malloc) 292 _g_.m.libcall.n = 1 293 memclr(unsafe.Pointer(&_g_.m.scratch), uintptr(len(_g_.m.scratch.v))) 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 return 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 memclr(unsafe.Pointer(&_m_.scratch), uintptr(len(_m_.scratch.v))) 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 memclr(unsafe.Pointer(&_m_.scratch), uintptr(len(_m_.scratch.v))) 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 close(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 { 373 return unsafe.Pointer(sysvicall6(libc_mmap, uintptr(addr), uintptr(n), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off))) 374 } 375 376 //go:nosplit 377 func munmap(addr unsafe.Pointer, n uintptr) { 378 sysvicall2(libc_munmap, uintptr(addr), uintptr(n)) 379 } 380 381 func nanotime1() 382 383 //go:nosplit 384 func nanotime() int64 { 385 return int64(sysvicall0(libcFunc(funcPC(nanotime1)))) 386 } 387 388 //go:nosplit 389 func open(path *byte, mode, perm int32) int32 { 390 return int32(sysvicall3(libc_open, uintptr(unsafe.Pointer(path)), uintptr(mode), uintptr(perm))) 391 } 392 393 func pthread_attr_destroy(attr *pthreadattr) int32 { 394 return int32(sysvicall1(libc_pthread_attr_destroy, uintptr(unsafe.Pointer(attr)))) 395 } 396 397 func pthread_attr_getstack(attr *pthreadattr, addr unsafe.Pointer, size *uint64) int32 { 398 return int32(sysvicall3(libc_pthread_attr_getstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(unsafe.Pointer(size)))) 399 } 400 401 func pthread_attr_init(attr *pthreadattr) int32 { 402 return int32(sysvicall1(libc_pthread_attr_init, uintptr(unsafe.Pointer(attr)))) 403 } 404 405 func pthread_attr_setdetachstate(attr *pthreadattr, state int32) int32 { 406 return int32(sysvicall2(libc_pthread_attr_setdetachstate, uintptr(unsafe.Pointer(attr)), uintptr(state))) 407 } 408 409 func pthread_attr_setstack(attr *pthreadattr, addr uintptr, size uint64) int32 { 410 return int32(sysvicall3(libc_pthread_attr_setstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(size))) 411 } 412 413 func pthread_create(thread *pthread, attr *pthreadattr, fn uintptr, arg unsafe.Pointer) int32 { 414 return int32(sysvicall4(libc_pthread_create, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(fn), uintptr(arg))) 415 } 416 417 func raise(sig int32) /* int32 */ { 418 sysvicall1(libc_raise, uintptr(sig)) 419 } 420 421 func raiseproc(sig int32) /* int32 */ { 422 sysvicall1(libc_raise, uintptr(sig)) 423 } 424 425 //go:nosplit 426 func read(fd int32, buf unsafe.Pointer, nbyte int32) int32 { 427 return int32(sysvicall3(libc_read, uintptr(fd), uintptr(buf), uintptr(nbyte))) 428 } 429 430 //go:nosplit 431 func sem_init(sem *semt, pshared int32, value uint32) int32 { 432 return int32(sysvicall3(libc_sem_init, uintptr(unsafe.Pointer(sem)), uintptr(pshared), uintptr(value))) 433 } 434 435 //go:nosplit 436 func sem_post(sem *semt) int32 { 437 return int32(sysvicall1(libc_sem_post, uintptr(unsafe.Pointer(sem)))) 438 } 439 440 //go:nosplit 441 func sem_reltimedwait_np(sem *semt, timeout *timespec) int32 { 442 return int32(sysvicall2(libc_sem_reltimedwait_np, uintptr(unsafe.Pointer(sem)), uintptr(unsafe.Pointer(timeout)))) 443 } 444 445 //go:nosplit 446 func sem_wait(sem *semt) int32 { 447 return int32(sysvicall1(libc_sem_wait, uintptr(unsafe.Pointer(sem)))) 448 } 449 450 func setitimer(which int32, value *itimerval, ovalue *itimerval) /* int32 */ { 451 sysvicall3(libc_setitimer, uintptr(which), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(ovalue))) 452 } 453 454 func sigaction(sig int32, act *sigactiont, oact *sigactiont) /* int32 */ { 455 sysvicall3(libc_sigaction, uintptr(sig), uintptr(unsafe.Pointer(act)), uintptr(unsafe.Pointer(oact))) 456 } 457 458 func sigaltstack(ss *sigaltstackt, oss *sigaltstackt) /* int32 */ { 459 sysvicall2(libc_sigaltstack, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(oss))) 460 } 461 462 func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ { 463 sysvicall3(libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset))) 464 } 465 466 func sysconf(name int32) int64 { 467 return int64(sysvicall1(libc_sysconf, uintptr(name))) 468 } 469 470 func usleep1(uint32) 471 472 //go:nosplit 473 func usleep(µs uint32) { 474 usleep1(µs) 475 } 476 477 //go:nosplit 478 func write(fd uintptr, buf unsafe.Pointer, nbyte int32) int32 { 479 return int32(sysvicall3(libc_write, uintptr(fd), uintptr(buf), uintptr(nbyte))) 480 } 481 482 func osyield1() 483 484 //go:nosplit 485 func osyield() { 486 _g_ := getg() 487 488 // Check the validity of m because we might be called in cgo callback 489 // path early enough where there isn't a m available yet. 490 if _g_ != nil && _g_.m != nil { 491 sysvicall0(libc_sched_yield) 492 return 493 } 494 osyield1() 495 }