github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/runtime/os_aix.go (about)

     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  // Ms related functions
   101  func mpreinit(mp *m) {
   102  	mp.gsignal = malg(32 * 1024) // AIX wants >= 8K
   103  	mp.gsignal.m = mp
   104  }
   105  
   106  // errno address must be retrieved by calling _Errno libc function.
   107  // This will return a pointer to errno
   108  func miniterrno() {
   109  	mp := getg().m
   110  	r, _ := syscall0(&libc__Errno)
   111  	mp.perrno = r
   112  
   113  }
   114  
   115  func minit() {
   116  	miniterrno()
   117  	minitSignals()
   118  }
   119  
   120  func unminit() {
   121  	unminitSignals()
   122  }
   123  
   124  // tstart is a function descriptor to _tstart defined in assembly.
   125  var tstart funcDescriptor
   126  
   127  func newosproc(mp *m) {
   128  	var (
   129  		attr pthread_attr
   130  		oset sigset
   131  		tid  pthread
   132  	)
   133  
   134  	if pthread_attr_init(&attr) != 0 {
   135  		throw("pthread_attr_init")
   136  	}
   137  
   138  	if pthread_attr_setstacksize(&attr, threadStackSize) != 0 {
   139  		throw("pthread_attr_getstacksize")
   140  	}
   141  
   142  	if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
   143  		throw("pthread_attr_setdetachstate")
   144  	}
   145  
   146  	// Disable signals during create, so that the new thread starts
   147  	// with signals disabled. It will enable them in minit.
   148  	sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
   149  	var ret int32
   150  	for tries := 0; tries < 20; tries++ {
   151  		// pthread_create can fail with EAGAIN for no reasons
   152  		// but it will be ok if it retries.
   153  		ret = pthread_create(&tid, &attr, &tstart, unsafe.Pointer(mp))
   154  		if ret != _EAGAIN {
   155  			break
   156  		}
   157  		usleep(uint32(tries+1) * 1000) // Milliseconds.
   158  	}
   159  	sigprocmask(_SIG_SETMASK, &oset, nil)
   160  	if ret != 0 {
   161  		print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", ret, ")\n")
   162  		if ret == _EAGAIN {
   163  			println("runtime: may need to increase max user processes (ulimit -u)")
   164  		}
   165  		throw("newosproc")
   166  	}
   167  
   168  }
   169  
   170  func exitThread(wait *uint32) {
   171  	// We should never reach exitThread on AIX because we let
   172  	// libc clean up threads.
   173  	throw("exitThread")
   174  }
   175  
   176  var urandom_dev = []byte("/dev/urandom\x00")
   177  
   178  //go:nosplit
   179  func getRandomData(r []byte) {
   180  	fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
   181  	n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
   182  	closefd(fd)
   183  	extendRandom(r, int(n))
   184  }
   185  
   186  func goenvs() {
   187  	goenvs_unix()
   188  }
   189  
   190  /* SIGNAL */
   191  
   192  const (
   193  	_NSIG = 256
   194  )
   195  
   196  // sigtramp is a function descriptor to _sigtramp defined in assembly
   197  var sigtramp funcDescriptor
   198  
   199  //go:nosplit
   200  //go:nowritebarrierrec
   201  func setsig(i uint32, fn uintptr) {
   202  	var sa sigactiont
   203  	sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
   204  	sa.sa_mask = sigset_all
   205  	if fn == funcPC(sighandler) {
   206  		fn = uintptr(unsafe.Pointer(&sigtramp))
   207  	}
   208  	sa.sa_handler = fn
   209  	sigaction(uintptr(i), &sa, nil)
   210  
   211  }
   212  
   213  //go:nosplit
   214  //go:nowritebarrierrec
   215  func setsigstack(i uint32) {
   216  	throw("Not yet implemented\n")
   217  }
   218  
   219  //go:nosplit
   220  //go:nowritebarrierrec
   221  func getsig(i uint32) uintptr {
   222  	var sa sigactiont
   223  	sigaction(uintptr(i), nil, &sa)
   224  	return sa.sa_handler
   225  }
   226  
   227  // setSignaltstackSP sets the ss_sp field of a stackt.
   228  //go:nosplit
   229  func setSignalstackSP(s *stackt, sp uintptr) {
   230  	*(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp
   231  }
   232  
   233  func (c *sigctxt) fixsigcode(sig uint32) {
   234  }
   235  
   236  func sigaddset(mask *sigset, i int) {
   237  	(*mask)[(i-1)/64] |= 1 << ((uint32(i) - 1) & 63)
   238  }
   239  
   240  func sigdelset(mask *sigset, i int) {
   241  	(*mask)[(i-1)/64] &^= 1 << ((uint32(i) - 1) & 63)
   242  }
   243  
   244  const (
   245  	_CLOCK_REALTIME  = 9
   246  	_CLOCK_MONOTONIC = 10
   247  )
   248  
   249  //go:nosplit
   250  func nanotime() int64 {
   251  	tp := &timespec{}
   252  	if clock_gettime(_CLOCK_REALTIME, tp) != 0 {
   253  		throw("syscall clock_gettime failed")
   254  	}
   255  	return tp.tv_sec*1000000000 + tp.tv_nsec
   256  }
   257  
   258  func walltime() (sec int64, nsec int32) {
   259  	ts := &timespec{}
   260  	if clock_gettime(_CLOCK_REALTIME, ts) != 0 {
   261  		throw("syscall clock_gettime failed")
   262  	}
   263  	return ts.tv_sec, int32(ts.tv_nsec)
   264  }
   265  
   266  const (
   267  	// getsystemcfg constants
   268  	_SC_IMPL     = 2
   269  	_IMPL_POWER8 = 0x10000
   270  	_IMPL_POWER9 = 0x20000
   271  )
   272  
   273  // setupSystemConf retrieves information about the CPU and updates
   274  // cpu.HWCap variables.
   275  func setupSystemConf() {
   276  	impl := getsystemcfg(_SC_IMPL)
   277  	if impl&_IMPL_POWER8 != 0 {
   278  		cpu.HWCap2 |= cpu.PPC_FEATURE2_ARCH_2_07
   279  	}
   280  	if impl&_IMPL_POWER9 != 0 {
   281  		cpu.HWCap2 |= cpu.PPC_FEATURE2_ARCH_3_00
   282  	}
   283  }