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