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

View as plain text