Source file src/runtime/os_dragonfly.go

     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  	"internal/abi"
     9  	"internal/goarch"
    10  	"unsafe"
    11  )
    12  
    13  const (
    14  	_NSIG        = 33
    15  	_SI_USER     = 0
    16  	_SS_DISABLE  = 4
    17  	_SIG_BLOCK   = 1
    18  	_SIG_UNBLOCK = 2
    19  	_SIG_SETMASK = 3
    20  )
    21  
    22  type mOS struct{}
    23  
    24  //go:noescape
    25  func lwp_create(param *lwpparams) int32
    26  
    27  //go:noescape
    28  func sigaltstack(new, old *stackt)
    29  
    30  //go:noescape
    31  func sigaction(sig uint32, new, old *sigactiont)
    32  
    33  //go:noescape
    34  func sigprocmask(how int32, new, old *sigset)
    35  
    36  //go:noescape
    37  func setitimer(mode int32, new, old *itimerval)
    38  
    39  //go:noescape
    40  func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
    41  
    42  func raiseproc(sig uint32)
    43  
    44  func lwp_gettid() int32
    45  func lwp_kill(pid, tid int32, sig int)
    46  
    47  //go:noescape
    48  func sys_umtx_sleep(addr *uint32, val, timeout int32) int32
    49  
    50  //go:noescape
    51  func sys_umtx_wakeup(addr *uint32, val int32) int32
    52  
    53  func osyield()
    54  
    55  //go:nosplit
    56  func osyield_no_g() {
    57  	osyield()
    58  }
    59  
    60  func kqueue() int32
    61  
    62  //go:noescape
    63  func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
    64  
    65  func pipe() (r, w int32, errno int32)
    66  func pipe2(flags int32) (r, w int32, errno int32)
    67  func closeonexec(fd int32)
    68  func setNonblock(fd int32)
    69  
    70  // From DragonFly's <sys/sysctl.h>
    71  const (
    72  	_CTL_HW      = 6
    73  	_HW_NCPU     = 3
    74  	_HW_PAGESIZE = 7
    75  )
    76  
    77  var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
    78  
    79  func getncpu() int32 {
    80  	mib := [2]uint32{_CTL_HW, _HW_NCPU}
    81  	out := uint32(0)
    82  	nout := unsafe.Sizeof(out)
    83  	ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
    84  	if ret >= 0 {
    85  		return int32(out)
    86  	}
    87  	return 1
    88  }
    89  
    90  func getPageSize() uintptr {
    91  	mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
    92  	out := uint32(0)
    93  	nout := unsafe.Sizeof(out)
    94  	ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
    95  	if ret >= 0 {
    96  		return uintptr(out)
    97  	}
    98  	return 0
    99  }
   100  
   101  //go:nosplit
   102  func futexsleep(addr *uint32, val uint32, ns int64) {
   103  	systemstack(func() {
   104  		futexsleep1(addr, val, ns)
   105  	})
   106  }
   107  
   108  func futexsleep1(addr *uint32, val uint32, ns int64) {
   109  	var timeout int32
   110  	if ns >= 0 {
   111  		// The timeout is specified in microseconds - ensure that we
   112  		// do not end up dividing to zero, which would put us to sleep
   113  		// indefinitely...
   114  		timeout = timediv(ns, 1000, nil)
   115  		if timeout == 0 {
   116  			timeout = 1
   117  		}
   118  	}
   119  
   120  	// sys_umtx_sleep will return EWOULDBLOCK (EAGAIN) when the timeout
   121  	// expires or EBUSY if the mutex value does not match.
   122  	ret := sys_umtx_sleep(addr, int32(val), timeout)
   123  	if ret >= 0 || ret == -_EINTR || ret == -_EAGAIN || ret == -_EBUSY {
   124  		return
   125  	}
   126  
   127  	print("umtx_sleep addr=", addr, " val=", val, " ret=", ret, "\n")
   128  	*(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005
   129  }
   130  
   131  //go:nosplit
   132  func futexwakeup(addr *uint32, cnt uint32) {
   133  	ret := sys_umtx_wakeup(addr, int32(cnt))
   134  	if ret >= 0 {
   135  		return
   136  	}
   137  
   138  	systemstack(func() {
   139  		print("umtx_wake_addr=", addr, " ret=", ret, "\n")
   140  		*(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
   141  	})
   142  }
   143  
   144  func lwp_start(uintptr)
   145  
   146  // May run with m.p==nil, so write barriers are not allowed.
   147  //go:nowritebarrier
   148  func newosproc(mp *m) {
   149  	stk := unsafe.Pointer(mp.g0.stack.hi)
   150  	if false {
   151  		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " lwp_start=", abi.FuncPCABI0(lwp_start), " id=", mp.id, " ostk=", &mp, "\n")
   152  	}
   153  
   154  	var oset sigset
   155  	sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
   156  
   157  	params := lwpparams{
   158  		start_func: abi.FuncPCABI0(lwp_start),
   159  		arg:        unsafe.Pointer(mp),
   160  		stack:      uintptr(stk),
   161  		tid1:       nil, // minit will record tid
   162  		tid2:       nil,
   163  	}
   164  
   165  	// TODO: Check for error.
   166  	lwp_create(&params)
   167  	sigprocmask(_SIG_SETMASK, &oset, nil)
   168  }
   169  
   170  func osinit() {
   171  	ncpu = getncpu()
   172  	if physPageSize == 0 {
   173  		physPageSize = getPageSize()
   174  	}
   175  }
   176  
   177  var urandom_dev = []byte("/dev/urandom\x00")
   178  
   179  //go:nosplit
   180  func getRandomData(r []byte) {
   181  	fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
   182  	n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
   183  	closefd(fd)
   184  	extendRandom(r, int(n))
   185  }
   186  
   187  func goenvs() {
   188  	goenvs_unix()
   189  }
   190  
   191  // Called to initialize a new m (including the bootstrap m).
   192  // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
   193  func mpreinit(mp *m) {
   194  	mp.gsignal = malg(32 * 1024)
   195  	mp.gsignal.m = mp
   196  }
   197  
   198  // Called to initialize a new m (including the bootstrap m).
   199  // Called on the new thread, cannot allocate memory.
   200  func minit() {
   201  	getg().m.procid = uint64(lwp_gettid())
   202  	minitSignals()
   203  }
   204  
   205  // Called from dropm to undo the effect of an minit.
   206  //go:nosplit
   207  func unminit() {
   208  	unminitSignals()
   209  }
   210  
   211  // Called from exitm, but not from drop, to undo the effect of thread-owned
   212  // resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
   213  func mdestroy(mp *m) {
   214  }
   215  
   216  func sigtramp()
   217  
   218  type sigactiont struct {
   219  	sa_sigaction uintptr
   220  	sa_flags     int32
   221  	sa_mask      sigset
   222  }
   223  
   224  //go:nosplit
   225  //go:nowritebarrierrec
   226  func setsig(i uint32, fn uintptr) {
   227  	var sa sigactiont
   228  	sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
   229  	sa.sa_mask = sigset_all
   230  	if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go
   231  		fn = abi.FuncPCABI0(sigtramp)
   232  	}
   233  	sa.sa_sigaction = fn
   234  	sigaction(i, &sa, nil)
   235  }
   236  
   237  //go:nosplit
   238  //go:nowritebarrierrec
   239  func setsigstack(i uint32) {
   240  	throw("setsigstack")
   241  }
   242  
   243  //go:nosplit
   244  //go:nowritebarrierrec
   245  func getsig(i uint32) uintptr {
   246  	var sa sigactiont
   247  	sigaction(i, nil, &sa)
   248  	return sa.sa_sigaction
   249  }
   250  
   251  // setSignaltstackSP sets the ss_sp field of a stackt.
   252  //go:nosplit
   253  func setSignalstackSP(s *stackt, sp uintptr) {
   254  	s.ss_sp = sp
   255  }
   256  
   257  //go:nosplit
   258  //go:nowritebarrierrec
   259  func sigaddset(mask *sigset, i int) {
   260  	mask.__bits[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31)
   261  }
   262  
   263  func sigdelset(mask *sigset, i int) {
   264  	mask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
   265  }
   266  
   267  //go:nosplit
   268  func (c *sigctxt) fixsigcode(sig uint32) {
   269  }
   270  
   271  func setProcessCPUProfiler(hz int32) {
   272  	setProcessCPUProfilerTimer(hz)
   273  }
   274  
   275  func setThreadCPUProfiler(hz int32) {
   276  	setThreadCPUProfilerHz(hz)
   277  }
   278  
   279  //go:nosplit
   280  func validSIGPROF(mp *m, c *sigctxt) bool {
   281  	return true
   282  }
   283  
   284  func sysargs(argc int32, argv **byte) {
   285  	n := argc + 1
   286  
   287  	// skip over argv, envp to get to auxv
   288  	for argv_index(argv, n) != nil {
   289  		n++
   290  	}
   291  
   292  	// skip NULL separator
   293  	n++
   294  
   295  	auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize))
   296  	sysauxv(auxv[:])
   297  }
   298  
   299  const (
   300  	_AT_NULL   = 0
   301  	_AT_PAGESZ = 6
   302  )
   303  
   304  func sysauxv(auxv []uintptr) {
   305  	for i := 0; auxv[i] != _AT_NULL; i += 2 {
   306  		tag, val := auxv[i], auxv[i+1]
   307  		switch tag {
   308  		case _AT_PAGESZ:
   309  			physPageSize = val
   310  		}
   311  	}
   312  }
   313  
   314  // raise sends a signal to the calling thread.
   315  //
   316  // It must be nosplit because it is used by the signal handler before
   317  // it definitely has a Go stack.
   318  //
   319  //go:nosplit
   320  func raise(sig uint32) {
   321  	lwp_kill(-1, lwp_gettid(), int(sig))
   322  }
   323  
   324  func signalM(mp *m, sig int) {
   325  	lwp_kill(-1, int32(mp.procid), sig)
   326  }
   327  
   328  // sigPerThreadSyscall is only used on linux, so we assign a bogus signal
   329  // number.
   330  const sigPerThreadSyscall = 1 << 31
   331  
   332  //go:nosplit
   333  func runPerThreadSyscall() {
   334  	throw("runPerThreadSyscall only valid on linux")
   335  }
   336  

View as plain text