...
Run Format

Source file src/runtime/os_dragonfly.go

Documentation: runtime

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

View as plain text