...

Source file src/runtime/os_aix.go

     1	// Copyright 2018 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	// +build aix
     6	
     7	package runtime
     8	
     9	import (
    10		"internal/cpu"
    11		"unsafe"
    12	)
    13	
    14	const (
    15		threadStackSize = 0x100000 // size of a thread stack allocated by OS
    16	)
    17	
    18	// funcDescriptor is a structure representing a function descriptor
    19	// A variable with this type is always created in assembler
    20	type funcDescriptor struct {
    21		fn         uintptr
    22		toc        uintptr
    23		envPointer uintptr // unused in Golang
    24	}
    25	
    26	type mOS struct {
    27		waitsema uintptr // semaphore for parking on locks
    28		perrno   uintptr // pointer to tls errno
    29	}
    30	
    31	//go:nosplit
    32	func semacreate(mp *m) {
    33		if mp.waitsema != 0 {
    34			return
    35		}
    36	
    37		var sem *semt
    38	
    39		// Call libc's malloc rather than malloc. This will
    40		// allocate space on the C heap. We can't call mallocgc
    41		// here because it could cause a deadlock.
    42		sem = (*semt)(malloc(unsafe.Sizeof(*sem)))
    43		if sem_init(sem, 0, 0) != 0 {
    44			throw("sem_init")
    45		}
    46		mp.waitsema = uintptr(unsafe.Pointer(sem))
    47	}
    48	
    49	//go:nosplit
    50	func semasleep(ns int64) int32 {
    51		_m_ := getg().m
    52		if ns >= 0 {
    53			var ts timespec
    54	
    55			if clock_gettime(_CLOCK_REALTIME, &ts) != 0 {
    56				throw("clock_gettime")
    57			}
    58			ts.tv_sec += ns / 1e9
    59			ts.tv_nsec += ns % 1e9
    60			if ts.tv_nsec >= 1e9 {
    61				ts.tv_sec++
    62				ts.tv_nsec -= 1e9
    63			}
    64	
    65			if r, err := sem_timedwait((*semt)(unsafe.Pointer(_m_.waitsema)), &ts); r != 0 {
    66				if err == _ETIMEDOUT || err == _EAGAIN || err == _EINTR {
    67					return -1
    68				}
    69				println("sem_timedwait err ", err, " ts.tv_sec ", ts.tv_sec, " ts.tv_nsec ", ts.tv_nsec, " ns ", ns, " id ", _m_.id)
    70				throw("sem_timedwait")
    71			}
    72			return 0
    73		}
    74		for {
    75			r1, err := sem_wait((*semt)(unsafe.Pointer(_m_.waitsema)))
    76			if r1 == 0 {
    77				break
    78			}
    79			if err == _EINTR {
    80				continue
    81			}
    82			throw("sem_wait")
    83		}
    84		return 0
    85	}
    86	
    87	//go:nosplit
    88	func semawakeup(mp *m) {
    89		if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 {
    90			throw("sem_post")
    91		}
    92	}
    93	
    94	func osinit() {
    95		ncpu = int32(sysconf(__SC_NPROCESSORS_ONLN))
    96		physPageSize = sysconf(__SC_PAGE_SIZE)
    97		setupSystemConf()
    98	}
    99	
   100	// newosproc0 is a version of newosproc that can be called before the runtime
   101	// is initialized.
   102	//
   103	// This function is not safe to use after initialization as it does not pass an M as fnarg.
   104	//
   105	//go:nosplit
   106	func newosproc0(stacksize uintptr, fn *funcDescriptor) {
   107		var (
   108			attr pthread_attr
   109			oset sigset
   110			tid  pthread
   111		)
   112	
   113		if pthread_attr_init(&attr) != 0 {
   114			write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
   115			exit(1)
   116		}
   117	
   118		if pthread_attr_setstacksize(&attr, threadStackSize) != 0 {
   119			write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
   120			exit(1)
   121		}
   122	
   123		if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
   124			write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
   125			exit(1)
   126		}
   127	
   128		// Disable signals during create, so that the new thread starts
   129		// with signals disabled. It will enable them in minit.
   130		sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
   131		var ret int32
   132		for tries := 0; tries < 20; tries++ {
   133			// pthread_create can fail with EAGAIN for no reasons
   134			// but it will be ok if it retries.
   135			ret = pthread_create(&tid, &attr, fn, nil)
   136			if ret != _EAGAIN {
   137				break
   138			}
   139			usleep(uint32(tries+1) * 1000) // Milliseconds.
   140		}
   141		sigprocmask(_SIG_SETMASK, &oset, nil)
   142		if ret != 0 {
   143			write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
   144			exit(1)
   145		}
   146	
   147	}
   148	
   149	var failthreadcreate = []byte("runtime: failed to create new OS thread\n")
   150	
   151	// Called to do synchronous initialization of Go code built with
   152	// -buildmode=c-archive or -buildmode=c-shared.
   153	// None of the Go runtime is initialized.
   154	//go:nosplit
   155	//go:nowritebarrierrec
   156	func libpreinit() {
   157		initsig(true)
   158	}
   159	
   160	// Ms related functions
   161	func mpreinit(mp *m) {
   162		mp.gsignal = malg(32 * 1024) // AIX wants >= 8K
   163		mp.gsignal.m = mp
   164	}
   165	
   166	// errno address must be retrieved by calling _Errno libc function.
   167	// This will return a pointer to errno
   168	func miniterrno() {
   169		mp := getg().m
   170		r, _ := syscall0(&libc__Errno)
   171		mp.perrno = r
   172	
   173	}
   174	
   175	func minit() {
   176		miniterrno()
   177		minitSignals()
   178	}
   179	
   180	func unminit() {
   181		unminitSignals()
   182	}
   183	
   184	// tstart is a function descriptor to _tstart defined in assembly.
   185	var tstart funcDescriptor
   186	
   187	func newosproc(mp *m) {
   188		var (
   189			attr pthread_attr
   190			oset sigset
   191			tid  pthread
   192		)
   193	
   194		if pthread_attr_init(&attr) != 0 {
   195			throw("pthread_attr_init")
   196		}
   197	
   198		if pthread_attr_setstacksize(&attr, threadStackSize) != 0 {
   199			throw("pthread_attr_getstacksize")
   200		}
   201	
   202		if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
   203			throw("pthread_attr_setdetachstate")
   204		}
   205	
   206		// Disable signals during create, so that the new thread starts
   207		// with signals disabled. It will enable them in minit.
   208		sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
   209		var ret int32
   210		for tries := 0; tries < 20; tries++ {
   211			// pthread_create can fail with EAGAIN for no reasons
   212			// but it will be ok if it retries.
   213			ret = pthread_create(&tid, &attr, &tstart, unsafe.Pointer(mp))
   214			if ret != _EAGAIN {
   215				break
   216			}
   217			usleep(uint32(tries+1) * 1000) // Milliseconds.
   218		}
   219		sigprocmask(_SIG_SETMASK, &oset, nil)
   220		if ret != 0 {
   221			print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", ret, ")\n")
   222			if ret == _EAGAIN {
   223				println("runtime: may need to increase max user processes (ulimit -u)")
   224			}
   225			throw("newosproc")
   226		}
   227	
   228	}
   229	
   230	func exitThread(wait *uint32) {
   231		// We should never reach exitThread on AIX because we let
   232		// libc clean up threads.
   233		throw("exitThread")
   234	}
   235	
   236	var urandom_dev = []byte("/dev/urandom\x00")
   237	
   238	//go:nosplit
   239	func getRandomData(r []byte) {
   240		fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
   241		n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
   242		closefd(fd)
   243		extendRandom(r, int(n))
   244	}
   245	
   246	func goenvs() {
   247		goenvs_unix()
   248	}
   249	
   250	/* SIGNAL */
   251	
   252	const (
   253		_NSIG = 256
   254	)
   255	
   256	// sigtramp is a function descriptor to _sigtramp defined in assembly
   257	var sigtramp funcDescriptor
   258	
   259	//go:nosplit
   260	//go:nowritebarrierrec
   261	func setsig(i uint32, fn uintptr) {
   262		var sa sigactiont
   263		sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
   264		sa.sa_mask = sigset_all
   265		if fn == funcPC(sighandler) {
   266			fn = uintptr(unsafe.Pointer(&sigtramp))
   267		}
   268		sa.sa_handler = fn
   269		sigaction(uintptr(i), &sa, nil)
   270	
   271	}
   272	
   273	//go:nosplit
   274	//go:nowritebarrierrec
   275	func setsigstack(i uint32) {
   276		var sa sigactiont
   277		sigaction(uintptr(i), nil, &sa)
   278		if sa.sa_flags&_SA_ONSTACK != 0 {
   279			return
   280		}
   281		sa.sa_flags |= _SA_ONSTACK
   282		sigaction(uintptr(i), &sa, nil)
   283	}
   284	
   285	//go:nosplit
   286	//go:nowritebarrierrec
   287	func getsig(i uint32) uintptr {
   288		var sa sigactiont
   289		sigaction(uintptr(i), nil, &sa)
   290		return sa.sa_handler
   291	}
   292	
   293	// setSignaltstackSP sets the ss_sp field of a stackt.
   294	//go:nosplit
   295	func setSignalstackSP(s *stackt, sp uintptr) {
   296		*(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp
   297	}
   298	
   299	//go:nosplit
   300	func (c *sigctxt) fixsigcode(sig uint32) {
   301		switch sig {
   302		case _SIGPIPE:
   303			// For SIGPIPE, c.sigcode() isn't set to _SI_USER as on Linux.
   304			// Therefore, raisebadsignal won't raise SIGPIPE again if
   305			// it was deliver in a non-Go thread.
   306			c.set_sigcode(_SI_USER)
   307		}
   308	}
   309	
   310	//go:nosplit
   311	//go:nowritebarrierrec
   312	func sigaddset(mask *sigset, i int) {
   313		(*mask)[(i-1)/64] |= 1 << ((uint32(i) - 1) & 63)
   314	}
   315	
   316	func sigdelset(mask *sigset, i int) {
   317		(*mask)[(i-1)/64] &^= 1 << ((uint32(i) - 1) & 63)
   318	}
   319	
   320	const (
   321		_CLOCK_REALTIME  = 9
   322		_CLOCK_MONOTONIC = 10
   323	)
   324	
   325	//go:nosplit
   326	func nanotime() int64 {
   327		tp := &timespec{}
   328		if clock_gettime(_CLOCK_REALTIME, tp) != 0 {
   329			throw("syscall clock_gettime failed")
   330		}
   331		return tp.tv_sec*1000000000 + tp.tv_nsec
   332	}
   333	
   334	func walltime() (sec int64, nsec int32) {
   335		ts := &timespec{}
   336		if clock_gettime(_CLOCK_REALTIME, ts) != 0 {
   337			throw("syscall clock_gettime failed")
   338		}
   339		return ts.tv_sec, int32(ts.tv_nsec)
   340	}
   341	
   342	const (
   343		// getsystemcfg constants
   344		_SC_IMPL     = 2
   345		_IMPL_POWER8 = 0x10000
   346		_IMPL_POWER9 = 0x20000
   347	)
   348	
   349	// setupSystemConf retrieves information about the CPU and updates
   350	// cpu.HWCap variables.
   351	func setupSystemConf() {
   352		impl := getsystemcfg(_SC_IMPL)
   353		if impl&_IMPL_POWER8 != 0 {
   354			cpu.HWCap2 |= cpu.PPC_FEATURE2_ARCH_2_07
   355		}
   356		if impl&_IMPL_POWER9 != 0 {
   357			cpu.HWCap2 |= cpu.PPC_FEATURE2_ARCH_3_00
   358		}
   359	}
   360	

View as plain text