...

Source file src/runtime/os3_solaris.go

     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	//go:nosplit
   277	func (c *sigctxt) fixsigcode(sig uint32) {
   278	}
   279	
   280	//go:nosplit
   281	func semacreate(mp *m) {
   282		if mp.waitsema != 0 {
   283			return
   284		}
   285	
   286		var sem *semt
   287		_g_ := getg()
   288	
   289		// Call libc's malloc rather than malloc. This will
   290		// allocate space on the C heap. We can't call malloc
   291		// here because it could cause a deadlock.
   292		_g_.m.libcall.fn = uintptr(unsafe.Pointer(&libc_malloc))
   293		_g_.m.libcall.n = 1
   294		_g_.m.scratch = mscratch{}
   295		_g_.m.scratch.v[0] = unsafe.Sizeof(*sem)
   296		_g_.m.libcall.args = uintptr(unsafe.Pointer(&_g_.m.scratch))
   297		asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&_g_.m.libcall))
   298		sem = (*semt)(unsafe.Pointer(_g_.m.libcall.r1))
   299		if sem_init(sem, 0, 0) != 0 {
   300			throw("sem_init")
   301		}
   302		mp.waitsema = uintptr(unsafe.Pointer(sem))
   303	}
   304	
   305	//go:nosplit
   306	func semasleep(ns int64) int32 {
   307		_m_ := getg().m
   308		if ns >= 0 {
   309			_m_.ts.tv_sec = ns / 1000000000
   310			_m_.ts.tv_nsec = ns % 1000000000
   311	
   312			_m_.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_reltimedwait_np))
   313			_m_.libcall.n = 2
   314			_m_.scratch = mscratch{}
   315			_m_.scratch.v[0] = _m_.waitsema
   316			_m_.scratch.v[1] = uintptr(unsafe.Pointer(&_m_.ts))
   317			_m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch))
   318			asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&_m_.libcall))
   319			if *_m_.perrno != 0 {
   320				if *_m_.perrno == _ETIMEDOUT || *_m_.perrno == _EAGAIN || *_m_.perrno == _EINTR {
   321					return -1
   322				}
   323				throw("sem_reltimedwait_np")
   324			}
   325			return 0
   326		}
   327		for {
   328			_m_.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_wait))
   329			_m_.libcall.n = 1
   330			_m_.scratch = mscratch{}
   331			_m_.scratch.v[0] = _m_.waitsema
   332			_m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch))
   333			asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&_m_.libcall))
   334			if _m_.libcall.r1 == 0 {
   335				break
   336			}
   337			if *_m_.perrno == _EINTR {
   338				continue
   339			}
   340			throw("sem_wait")
   341		}
   342		return 0
   343	}
   344	
   345	//go:nosplit
   346	func semawakeup(mp *m) {
   347		if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 {
   348			throw("sem_post")
   349		}
   350	}
   351	
   352	//go:nosplit
   353	func closefd(fd int32) int32 {
   354		return int32(sysvicall1(&libc_close, uintptr(fd)))
   355	}
   356	
   357	//go:nosplit
   358	func exit(r int32) {
   359		sysvicall1(&libc_exit, uintptr(r))
   360	}
   361	
   362	//go:nosplit
   363	func getcontext(context *ucontext) /* int32 */ {
   364		sysvicall1(&libc_getcontext, uintptr(unsafe.Pointer(context)))
   365	}
   366	
   367	//go:nosplit
   368	func madvise(addr unsafe.Pointer, n uintptr, flags int32) {
   369		sysvicall3(&libc_madvise, uintptr(addr), uintptr(n), uintptr(flags))
   370	}
   371	
   372	//go:nosplit
   373	func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (unsafe.Pointer, int) {
   374		p, err := doMmap(uintptr(addr), n, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off))
   375		if p == ^uintptr(0) {
   376			return nil, int(err)
   377		}
   378		return unsafe.Pointer(p), 0
   379	}
   380	
   381	//go:nosplit
   382	func doMmap(addr, n, prot, flags, fd, off uintptr) (uintptr, uintptr) {
   383		var libcall libcall
   384		libcall.fn = uintptr(unsafe.Pointer(&libc_mmap))
   385		libcall.n = 6
   386		libcall.args = uintptr(noescape(unsafe.Pointer(&addr)))
   387		asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall))
   388		return libcall.r1, libcall.err
   389	}
   390	
   391	//go:nosplit
   392	func munmap(addr unsafe.Pointer, n uintptr) {
   393		sysvicall2(&libc_munmap, uintptr(addr), uintptr(n))
   394	}
   395	
   396	func nanotime1()
   397	
   398	//go:nosplit
   399	func nanotime() int64 {
   400		return int64(sysvicall0((*libcFunc)(unsafe.Pointer(funcPC(nanotime1)))))
   401	}
   402	
   403	//go:nosplit
   404	func open(path *byte, mode, perm int32) int32 {
   405		return int32(sysvicall3(&libc_open, uintptr(unsafe.Pointer(path)), uintptr(mode), uintptr(perm)))
   406	}
   407	
   408	func pthread_attr_destroy(attr *pthreadattr) int32 {
   409		return int32(sysvicall1(&libc_pthread_attr_destroy, uintptr(unsafe.Pointer(attr))))
   410	}
   411	
   412	func pthread_attr_getstack(attr *pthreadattr, addr unsafe.Pointer, size *uint64) int32 {
   413		return int32(sysvicall3(&libc_pthread_attr_getstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(unsafe.Pointer(size))))
   414	}
   415	
   416	func pthread_attr_init(attr *pthreadattr) int32 {
   417		return int32(sysvicall1(&libc_pthread_attr_init, uintptr(unsafe.Pointer(attr))))
   418	}
   419	
   420	func pthread_attr_setdetachstate(attr *pthreadattr, state int32) int32 {
   421		return int32(sysvicall2(&libc_pthread_attr_setdetachstate, uintptr(unsafe.Pointer(attr)), uintptr(state)))
   422	}
   423	
   424	func pthread_attr_setstack(attr *pthreadattr, addr uintptr, size uint64) int32 {
   425		return int32(sysvicall3(&libc_pthread_attr_setstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(size)))
   426	}
   427	
   428	func pthread_create(thread *pthread, attr *pthreadattr, fn uintptr, arg unsafe.Pointer) int32 {
   429		return int32(sysvicall4(&libc_pthread_create, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(fn), uintptr(arg)))
   430	}
   431	
   432	//go:nosplit
   433	//go:nowritebarrierrec
   434	func raise(sig uint32) /* int32 */ {
   435		sysvicall1(&libc_raise, uintptr(sig))
   436	}
   437	
   438	func raiseproc(sig uint32) /* int32 */ {
   439		pid := sysvicall0(&libc_getpid)
   440		sysvicall2(&libc_kill, pid, uintptr(sig))
   441	}
   442	
   443	//go:nosplit
   444	func read(fd int32, buf unsafe.Pointer, nbyte int32) int32 {
   445		return int32(sysvicall3(&libc_read, uintptr(fd), uintptr(buf), uintptr(nbyte)))
   446	}
   447	
   448	//go:nosplit
   449	func sem_init(sem *semt, pshared int32, value uint32) int32 {
   450		return int32(sysvicall3(&libc_sem_init, uintptr(unsafe.Pointer(sem)), uintptr(pshared), uintptr(value)))
   451	}
   452	
   453	//go:nosplit
   454	func sem_post(sem *semt) int32 {
   455		return int32(sysvicall1(&libc_sem_post, uintptr(unsafe.Pointer(sem))))
   456	}
   457	
   458	//go:nosplit
   459	func sem_reltimedwait_np(sem *semt, timeout *timespec) int32 {
   460		return int32(sysvicall2(&libc_sem_reltimedwait_np, uintptr(unsafe.Pointer(sem)), uintptr(unsafe.Pointer(timeout))))
   461	}
   462	
   463	//go:nosplit
   464	func sem_wait(sem *semt) int32 {
   465		return int32(sysvicall1(&libc_sem_wait, uintptr(unsafe.Pointer(sem))))
   466	}
   467	
   468	func setitimer(which int32, value *itimerval, ovalue *itimerval) /* int32 */ {
   469		sysvicall3(&libc_setitimer, uintptr(which), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(ovalue)))
   470	}
   471	
   472	//go:nosplit
   473	//go:nowritebarrierrec
   474	func sigaction(sig uint32, act *sigactiont, oact *sigactiont) /* int32 */ {
   475		sysvicall3(&libc_sigaction, uintptr(sig), uintptr(unsafe.Pointer(act)), uintptr(unsafe.Pointer(oact)))
   476	}
   477	
   478	//go:nosplit
   479	//go:nowritebarrierrec
   480	func sigaltstack(ss *stackt, oss *stackt) /* int32 */ {
   481		sysvicall2(&libc_sigaltstack, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(oss)))
   482	}
   483	
   484	//go:nosplit
   485	//go:nowritebarrierrec
   486	func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ {
   487		sysvicall3(&libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset)))
   488	}
   489	
   490	func sysconf(name int32) int64 {
   491		return int64(sysvicall1(&libc_sysconf, uintptr(name)))
   492	}
   493	
   494	func usleep1(usec uint32)
   495	
   496	//go:nosplit
   497	func usleep(µs uint32) {
   498		usleep1(µs)
   499	}
   500	
   501	//go:nosplit
   502	func write(fd uintptr, buf unsafe.Pointer, nbyte int32) int32 {
   503		return int32(sysvicall3(&libc_write, uintptr(fd), uintptr(buf), uintptr(nbyte)))
   504	}
   505	
   506	func osyield1()
   507	
   508	//go:nosplit
   509	func osyield() {
   510		_g_ := getg()
   511	
   512		// Check the validity of m because we might be called in cgo callback
   513		// path early enough where there isn't a m available yet.
   514		if _g_ != nil && _g_.m != nil {
   515			sysvicall0(&libc_sched_yield)
   516			return
   517		}
   518		osyield1()
   519	}
   520	
   521	//go:linkname executablePath os.executablePath
   522	var executablePath string
   523	
   524	func sysargs(argc int32, argv **byte) {
   525		n := argc + 1
   526	
   527		// skip over argv, envp to get to auxv
   528		for argv_index(argv, n) != nil {
   529			n++
   530		}
   531	
   532		// skip NULL separator
   533		n++
   534	
   535		// now argv+n is auxv
   536		auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
   537		sysauxv(auxv[:])
   538	}
   539	
   540	const (
   541		_AT_NULL         = 0    // Terminates the vector
   542		_AT_PAGESZ       = 6    // Page size in bytes
   543		_AT_SUN_EXECNAME = 2014 // exec() path name
   544	)
   545	
   546	func sysauxv(auxv []uintptr) {
   547		for i := 0; auxv[i] != _AT_NULL; i += 2 {
   548			tag, val := auxv[i], auxv[i+1]
   549			switch tag {
   550			case _AT_PAGESZ:
   551				physPageSize = val
   552			case _AT_SUN_EXECNAME:
   553				executablePath = gostringnocopy((*byte)(unsafe.Pointer(val)))
   554			}
   555		}
   556	}
   557	

View as plain text