golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/src/runtime/os_netbsd.go (about)

     1  // Copyright 2014 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/atomic"
     9  	"unsafe"
    10  )
    11  
    12  const (
    13  	_SS_DISABLE  = 4
    14  	_SIG_BLOCK   = 1
    15  	_SIG_UNBLOCK = 2
    16  	_SIG_SETMASK = 3
    17  	_NSIG        = 33
    18  	_SI_USER     = 0
    19  
    20  	// From NetBSD's <sys/ucontext.h>
    21  	_UC_SIGMASK = 0x01
    22  	_UC_CPU     = 0x04
    23  
    24  	_EAGAIN = 35
    25  )
    26  
    27  type mOS struct {
    28  	waitsemacount uint32
    29  }
    30  
    31  //go:noescape
    32  func setitimer(mode int32, new, old *itimerval)
    33  
    34  //go:noescape
    35  func sigaction(sig uint32, new, old *sigactiont)
    36  
    37  //go:noescape
    38  func sigaltstack(new, old *stackt)
    39  
    40  //go:noescape
    41  func sigprocmask(how int32, new, old *sigset)
    42  
    43  //go:noescape
    44  func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
    45  
    46  func lwp_tramp()
    47  
    48  func raise(sig uint32)
    49  func raiseproc(sig uint32)
    50  
    51  //go:noescape
    52  func getcontext(ctxt unsafe.Pointer)
    53  
    54  //go:noescape
    55  func lwp_create(ctxt unsafe.Pointer, flags uintptr, lwpid unsafe.Pointer) int32
    56  
    57  //go:noescape
    58  func lwp_park(abstime *timespec, unpark int32, hint, unparkhint unsafe.Pointer) int32
    59  
    60  //go:noescape
    61  func lwp_unpark(lwp int32, hint unsafe.Pointer) int32
    62  
    63  func lwp_self() int32
    64  
    65  func osyield()
    66  
    67  const (
    68  	_ESRCH     = 3
    69  	_ETIMEDOUT = 60
    70  
    71  	// From NetBSD's <sys/time.h>
    72  	_CLOCK_REALTIME  = 0
    73  	_CLOCK_VIRTUAL   = 1
    74  	_CLOCK_PROF      = 2
    75  	_CLOCK_MONOTONIC = 3
    76  )
    77  
    78  var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
    79  
    80  // From NetBSD's <sys/sysctl.h>
    81  const (
    82  	_CTL_HW      = 6
    83  	_HW_NCPU     = 3
    84  	_HW_PAGESIZE = 7
    85  )
    86  
    87  func getncpu() int32 {
    88  	mib := [2]uint32{_CTL_HW, _HW_NCPU}
    89  	out := uint32(0)
    90  	nout := unsafe.Sizeof(out)
    91  	ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
    92  	if ret >= 0 {
    93  		return int32(out)
    94  	}
    95  	return 1
    96  }
    97  
    98  func getPageSize() uintptr {
    99  	mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
   100  	out := uint32(0)
   101  	nout := unsafe.Sizeof(out)
   102  	ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
   103  	if ret >= 0 {
   104  		return uintptr(out)
   105  	}
   106  	return 0
   107  }
   108  
   109  //go:nosplit
   110  func semacreate(mp *m) {
   111  }
   112  
   113  //go:nosplit
   114  func semasleep(ns int64) int32 {
   115  	_g_ := getg()
   116  
   117  	// Compute sleep deadline.
   118  	var tsp *timespec
   119  	if ns >= 0 {
   120  		var ts timespec
   121  		var nsec int32
   122  		ns += nanotime()
   123  		ts.set_sec(timediv(ns, 1000000000, &nsec))
   124  		ts.set_nsec(nsec)
   125  		tsp = &ts
   126  	}
   127  
   128  	for {
   129  		v := atomic.Load(&_g_.m.waitsemacount)
   130  		if v > 0 {
   131  			if atomic.Cas(&_g_.m.waitsemacount, v, v-1) {
   132  				return 0 // semaphore acquired
   133  			}
   134  			continue
   135  		}
   136  
   137  		// Sleep until unparked by semawakeup or timeout.
   138  		ret := lwp_park(tsp, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil)
   139  		if ret == _ETIMEDOUT {
   140  			return -1
   141  		}
   142  	}
   143  }
   144  
   145  //go:nosplit
   146  func semawakeup(mp *m) {
   147  	atomic.Xadd(&mp.waitsemacount, 1)
   148  	// From NetBSD's _lwp_unpark(2) manual:
   149  	// "If the target LWP is not currently waiting, it will return
   150  	// immediately upon the next call to _lwp_park()."
   151  	ret := lwp_unpark(int32(mp.procid), unsafe.Pointer(&mp.waitsemacount))
   152  	if ret != 0 && ret != _ESRCH {
   153  		// semawakeup can be called on signal stack.
   154  		systemstack(func() {
   155  			print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
   156  		})
   157  	}
   158  }
   159  
   160  // May run with m.p==nil, so write barriers are not allowed.
   161  //go:nowritebarrier
   162  func newosproc(mp *m, stk unsafe.Pointer) {
   163  	if false {
   164  		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
   165  	}
   166  
   167  	var uc ucontextt
   168  	getcontext(unsafe.Pointer(&uc))
   169  
   170  	// _UC_SIGMASK does not seem to work here.
   171  	// It would be nice if _UC_SIGMASK and _UC_STACK
   172  	// worked so that we could do all the work setting
   173  	// the sigmask and the stack here, instead of setting
   174  	// the mask here and the stack in netbsdMstart.
   175  	// For now do the blocking manually.
   176  	uc.uc_flags = _UC_SIGMASK | _UC_CPU
   177  	uc.uc_link = nil
   178  	uc.uc_sigmask = sigset_all
   179  
   180  	var oset sigset
   181  	sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
   182  
   183  	lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp.g0, funcPC(netbsdMstart))
   184  
   185  	ret := lwp_create(unsafe.Pointer(&uc), 0, unsafe.Pointer(&mp.procid))
   186  	sigprocmask(_SIG_SETMASK, &oset, nil)
   187  	if ret < 0 {
   188  		print("runtime: failed to create new OS thread (have ", mcount()-1, " already; errno=", -ret, ")\n")
   189  		if ret == -_EAGAIN {
   190  			println("runtime: may need to increase max user processes (ulimit -p)")
   191  		}
   192  		throw("runtime.newosproc")
   193  	}
   194  }
   195  
   196  // netbsdMStart is the function call that starts executing a newly
   197  // created thread. On NetBSD, a new thread inherits the signal stack
   198  // of the creating thread. That confuses minit, so we remove that
   199  // signal stack here before calling the regular mstart. It's a bit
   200  // baroque to remove a signal stack here only to add one in minit, but
   201  // it's a simple change that keeps NetBSD working like other OS's.
   202  // At this point all signals are blocked, so there is no race.
   203  //go:nosplit
   204  func netbsdMstart() {
   205  	st := stackt{ss_flags: _SS_DISABLE}
   206  	sigaltstack(&st, nil)
   207  	mstart()
   208  }
   209  
   210  func osinit() {
   211  	ncpu = getncpu()
   212  	physPageSize = getPageSize()
   213  }
   214  
   215  var urandom_dev = []byte("/dev/urandom\x00")
   216  
   217  //go:nosplit
   218  func getRandomData(r []byte) {
   219  	fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
   220  	n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
   221  	closefd(fd)
   222  	extendRandom(r, int(n))
   223  }
   224  
   225  func goenvs() {
   226  	goenvs_unix()
   227  }
   228  
   229  // Called to initialize a new m (including the bootstrap m).
   230  // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
   231  func mpreinit(mp *m) {
   232  	mp.gsignal = malg(32 * 1024)
   233  	mp.gsignal.m = mp
   234  }
   235  
   236  // Called to initialize a new m (including the bootstrap m).
   237  // Called on the new thread, cannot allocate memory.
   238  func minit() {
   239  	_g_ := getg()
   240  	_g_.m.procid = uint64(lwp_self())
   241  
   242  	// On NetBSD a thread created by pthread_create inherits the
   243  	// signal stack of the creating thread. We always create a
   244  	// new signal stack here, to avoid having two Go threads using
   245  	// the same signal stack. This breaks the case of a thread
   246  	// created in C that calls sigaltstack and then calls a Go
   247  	// function, because we will lose track of the C code's
   248  	// sigaltstack, but it's the best we can do.
   249  	signalstack(&_g_.m.gsignal.stack)
   250  	_g_.m.newSigstack = true
   251  
   252  	minitSignalMask()
   253  }
   254  
   255  // Called from dropm to undo the effect of an minit.
   256  //go:nosplit
   257  func unminit() {
   258  	unminitSignals()
   259  }
   260  
   261  func memlimit() uintptr {
   262  	return 0
   263  }
   264  
   265  func sigtramp()
   266  
   267  type sigactiont struct {
   268  	sa_sigaction uintptr
   269  	sa_mask      sigset
   270  	sa_flags     int32
   271  }
   272  
   273  //go:nosplit
   274  //go:nowritebarrierrec
   275  func setsig(i uint32, fn uintptr) {
   276  	var sa sigactiont
   277  	sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
   278  	sa.sa_mask = sigset_all
   279  	if fn == funcPC(sighandler) {
   280  		fn = funcPC(sigtramp)
   281  	}
   282  	sa.sa_sigaction = fn
   283  	sigaction(i, &sa, nil)
   284  }
   285  
   286  //go:nosplit
   287  //go:nowritebarrierrec
   288  func setsigstack(i uint32) {
   289  	throw("setsigstack")
   290  }
   291  
   292  //go:nosplit
   293  //go:nowritebarrierrec
   294  func getsig(i uint32) uintptr {
   295  	var sa sigactiont
   296  	sigaction(i, nil, &sa)
   297  	return sa.sa_sigaction
   298  }
   299  
   300  // setSignaltstackSP sets the ss_sp field of a stackt.
   301  //go:nosplit
   302  func setSignalstackSP(s *stackt, sp uintptr) {
   303  	s.ss_sp = sp
   304  }
   305  
   306  //go:nosplit
   307  //go:nowritebarrierrec
   308  func sigaddset(mask *sigset, i int) {
   309  	mask.__bits[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31)
   310  }
   311  
   312  func sigdelset(mask *sigset, i int) {
   313  	mask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
   314  }
   315  
   316  func (c *sigctxt) fixsigcode(sig uint32) {
   317  }