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 pipe2(flags int32) (r, w int32, errno int32)
    66  func closeonexec(fd int32)
    67  
    68  // From DragonFly's <sys/sysctl.h>
    69  const (
    70  	_CTL_HW      = 6
    71  	_HW_NCPU     = 3
    72  	_HW_PAGESIZE = 7
    73  )
    74  
    75  var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
    76  
    77  func getncpu() int32 {
    78  	mib := [2]uint32{_CTL_HW, _HW_NCPU}
    79  	out := uint32(0)
    80  	nout := unsafe.Sizeof(out)
    81  	ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
    82  	if ret >= 0 {
    83  		return int32(out)
    84  	}
    85  	return 1
    86  }
    87  
    88  func getPageSize() uintptr {
    89  	mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
    90  	out := uint32(0)
    91  	nout := unsafe.Sizeof(out)
    92  	ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
    93  	if ret >= 0 {
    94  		return uintptr(out)
    95  	}
    96  	return 0
    97  }
    98  
    99  //go:nosplit
   100  func futexsleep(addr *uint32, val uint32, ns int64) {
   101  	systemstack(func() {
   102  		futexsleep1(addr, val, ns)
   103  	})
   104  }
   105  
   106  func futexsleep1(addr *uint32, val uint32, ns int64) {
   107  	var timeout int32
   108  	if ns >= 0 {
   109  		// The timeout is specified in microseconds - ensure that we
   110  		// do not end up dividing to zero, which would put us to sleep
   111  		// indefinitely...
   112  		timeout = timediv(ns, 1000, nil)
   113  		if timeout == 0 {
   114  			timeout = 1
   115  		}
   116  	}
   117  
   118  	// sys_umtx_sleep will return EWOULDBLOCK (EAGAIN) when the timeout
   119  	// expires or EBUSY if the mutex value does not match.
   120  	ret := sys_umtx_sleep(addr, int32(val), timeout)
   121  	if ret >= 0 || ret == -_EINTR || ret == -_EAGAIN || ret == -_EBUSY {
   122  		return
   123  	}
   124  
   125  	print("umtx_sleep addr=", addr, " val=", val, " ret=", ret, "\n")
   126  	*(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005
   127  }
   128  
   129  //go:nosplit
   130  func futexwakeup(addr *uint32, cnt uint32) {
   131  	ret := sys_umtx_wakeup(addr, int32(cnt))
   132  	if ret >= 0 {
   133  		return
   134  	}
   135  
   136  	systemstack(func() {
   137  		print("umtx_wake_addr=", addr, " ret=", ret, "\n")
   138  		*(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
   139  	})
   140  }
   141  
   142  func lwp_start(uintptr)
   143  
   144  // May run with m.p==nil, so write barriers are not allowed.
   145  //
   146  //go:nowritebarrier
   147  func newosproc(mp *m) {
   148  	stk := unsafe.Pointer(mp.g0.stack.hi)
   149  	if false {
   150  		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " lwp_start=", abi.FuncPCABI0(lwp_start), " id=", mp.id, " ostk=", &mp, "\n")
   151  	}
   152  
   153  	var oset sigset
   154  	sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
   155  
   156  	params := lwpparams{
   157  		start_func: abi.FuncPCABI0(lwp_start),
   158  		arg:        unsafe.Pointer(mp),
   159  		stack:      uintptr(stk),
   160  		tid1:       nil, // minit will record tid
   161  		tid2:       nil,
   162  	}
   163  
   164  	// TODO: Check for error.
   165  	lwp_create(&params)
   166  	sigprocmask(_SIG_SETMASK, &oset, nil)
   167  }
   168  
   169  func osinit() {
   170  	ncpu = getncpu()
   171  	if physPageSize == 0 {
   172  		physPageSize = getPageSize()
   173  	}
   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  // Called to initialize a new m (including the bootstrap m).
   191  // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
   192  func mpreinit(mp *m) {
   193  	mp.gsignal = malg(32 * 1024)
   194  	mp.gsignal.m = mp
   195  }
   196  
   197  // Called to initialize a new m (including the bootstrap m).
   198  // Called on the new thread, cannot allocate memory.
   199  func minit() {
   200  	getg().m.procid = uint64(lwp_gettid())
   201  	minitSignals()
   202  }
   203  
   204  // Called from dropm to undo the effect of an minit.
   205  //
   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  //
   253  //go:nosplit
   254  func setSignalstackSP(s *stackt, sp uintptr) {
   255  	s.ss_sp = sp
   256  }
   257  
   258  //go:nosplit
   259  //go:nowritebarrierrec
   260  func sigaddset(mask *sigset, i int) {
   261  	mask.__bits[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31)
   262  }
   263  
   264  func sigdelset(mask *sigset, i int) {
   265  	mask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
   266  }
   267  
   268  //go:nosplit
   269  func (c *sigctxt) fixsigcode(sig uint32) {
   270  }
   271  
   272  func setProcessCPUProfiler(hz int32) {
   273  	setProcessCPUProfilerTimer(hz)
   274  }
   275  
   276  func setThreadCPUProfiler(hz int32) {
   277  	setThreadCPUProfilerHz(hz)
   278  }
   279  
   280  //go:nosplit
   281  func validSIGPROF(mp *m, c *sigctxt) bool {
   282  	return true
   283  }
   284  
   285  func sysargs(argc int32, argv **byte) {
   286  	n := argc + 1
   287  
   288  	// skip over argv, envp to get to auxv
   289  	for argv_index(argv, n) != nil {
   290  		n++
   291  	}
   292  
   293  	// skip NULL separator
   294  	n++
   295  
   296  	auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize))
   297  	sysauxv(auxv[:])
   298  }
   299  
   300  const (
   301  	_AT_NULL   = 0
   302  	_AT_PAGESZ = 6
   303  )
   304  
   305  func sysauxv(auxv []uintptr) {
   306  	for i := 0; auxv[i] != _AT_NULL; i += 2 {
   307  		tag, val := auxv[i], auxv[i+1]
   308  		switch tag {
   309  		case _AT_PAGESZ:
   310  			physPageSize = val
   311  		}
   312  	}
   313  }
   314  
   315  // raise sends a signal to the calling thread.
   316  //
   317  // It must be nosplit because it is used by the signal handler before
   318  // it definitely has a Go stack.
   319  //
   320  //go:nosplit
   321  func raise(sig uint32) {
   322  	lwp_kill(-1, lwp_gettid(), int(sig))
   323  }
   324  
   325  func signalM(mp *m, sig int) {
   326  	lwp_kill(-1, int32(mp.procid), sig)
   327  }
   328  
   329  // sigPerThreadSyscall is only used on linux, so we assign a bogus signal
   330  // number.
   331  const sigPerThreadSyscall = 1 << 31
   332  
   333  //go:nosplit
   334  func runPerThreadSyscall() {
   335  	throw("runPerThreadSyscall only valid on linux")
   336  }
   337  

View as plain text