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  }