github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/src/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 "unsafe"
     8  
     9  const (
    10  	_NSIG        = 33
    11  	_SI_USER     = 0
    12  	_SS_DISABLE  = 4
    13  	_RLIMIT_AS   = 10
    14  	_SIG_BLOCK   = 1
    15  	_SIG_UNBLOCK = 2
    16  	_SIG_SETMASK = 3
    17  )
    18  
    19  type mOS struct{}
    20  
    21  //go:noescape
    22  func lwp_create(param *lwpparams) int32
    23  
    24  //go:noescape
    25  func sigaltstack(new, old *stackt)
    26  
    27  //go:noescape
    28  func sigaction(sig uint32, new, old *sigactiont)
    29  
    30  //go:noescape
    31  func sigprocmask(how int32, new, old *sigset)
    32  
    33  //go:noescape
    34  func setitimer(mode int32, new, old *itimerval)
    35  
    36  //go:noescape
    37  func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
    38  
    39  //go:noescape
    40  func getrlimit(kind int32, limit unsafe.Pointer) int32
    41  
    42  func raise(sig uint32)
    43  func raiseproc(sig uint32)
    44  
    45  //go:noescape
    46  func sys_umtx_sleep(addr *uint32, val, timeout int32) int32
    47  
    48  //go:noescape
    49  func sys_umtx_wakeup(addr *uint32, val int32) int32
    50  
    51  func osyield()
    52  
    53  const stackSystem = 0
    54  
    55  // From DragonFly's <sys/sysctl.h>
    56  const (
    57  	_CTL_HW      = 6
    58  	_HW_NCPU     = 3
    59  	_HW_PAGESIZE = 7
    60  )
    61  
    62  var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
    63  
    64  func getncpu() int32 {
    65  	mib := [2]uint32{_CTL_HW, _HW_NCPU}
    66  	out := uint32(0)
    67  	nout := unsafe.Sizeof(out)
    68  	ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
    69  	if ret >= 0 {
    70  		return int32(out)
    71  	}
    72  	return 1
    73  }
    74  
    75  func getPageSize() uintptr {
    76  	mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
    77  	out := uint32(0)
    78  	nout := unsafe.Sizeof(out)
    79  	ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
    80  	if ret >= 0 {
    81  		return uintptr(out)
    82  	}
    83  	return 0
    84  }
    85  
    86  //go:nosplit
    87  func futexsleep(addr *uint32, val uint32, ns int64) {
    88  	systemstack(func() {
    89  		futexsleep1(addr, val, ns)
    90  	})
    91  }
    92  
    93  func futexsleep1(addr *uint32, val uint32, ns int64) {
    94  	var timeout int32
    95  	if ns >= 0 {
    96  		// The timeout is specified in microseconds - ensure that we
    97  		// do not end up dividing to zero, which would put us to sleep
    98  		// indefinitely...
    99  		timeout = timediv(ns, 1000, nil)
   100  		if timeout == 0 {
   101  			timeout = 1
   102  		}
   103  	}
   104  
   105  	// sys_umtx_sleep will return EWOULDBLOCK (EAGAIN) when the timeout
   106  	// expires or EBUSY if the mutex value does not match.
   107  	ret := sys_umtx_sleep(addr, int32(val), timeout)
   108  	if ret >= 0 || ret == -_EINTR || ret == -_EAGAIN || ret == -_EBUSY {
   109  		return
   110  	}
   111  
   112  	print("umtx_sleep addr=", addr, " val=", val, " ret=", ret, "\n")
   113  	*(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005
   114  }
   115  
   116  //go:nosplit
   117  func futexwakeup(addr *uint32, cnt uint32) {
   118  	ret := sys_umtx_wakeup(addr, int32(cnt))
   119  	if ret >= 0 {
   120  		return
   121  	}
   122  
   123  	systemstack(func() {
   124  		print("umtx_wake_addr=", addr, " ret=", ret, "\n")
   125  		*(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
   126  	})
   127  }
   128  
   129  func lwp_start(uintptr)
   130  
   131  // May run with m.p==nil, so write barriers are not allowed.
   132  //go:nowritebarrier
   133  func newosproc(mp *m, stk unsafe.Pointer) {
   134  	if false {
   135  		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " lwp_start=", funcPC(lwp_start), " id=", mp.id, " ostk=", &mp, "\n")
   136  	}
   137  
   138  	var oset sigset
   139  	sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
   140  
   141  	params := lwpparams{
   142  		start_func: funcPC(lwp_start),
   143  		arg:        unsafe.Pointer(mp),
   144  		stack:      uintptr(stk),
   145  		tid1:       unsafe.Pointer(&mp.procid),
   146  		tid2:       nil,
   147  	}
   148  
   149  	// TODO: Check for error.
   150  	lwp_create(&params)
   151  	sigprocmask(_SIG_SETMASK, &oset, nil)
   152  }
   153  
   154  func osinit() {
   155  	ncpu = getncpu()
   156  	physPageSize = getPageSize()
   157  }
   158  
   159  var urandom_dev = []byte("/dev/urandom\x00")
   160  
   161  //go:nosplit
   162  func getRandomData(r []byte) {
   163  	fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
   164  	n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
   165  	closefd(fd)
   166  	extendRandom(r, int(n))
   167  }
   168  
   169  func goenvs() {
   170  	goenvs_unix()
   171  }
   172  
   173  // Called to initialize a new m (including the bootstrap m).
   174  // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
   175  func mpreinit(mp *m) {
   176  	mp.gsignal = malg(32 * 1024)
   177  	mp.gsignal.m = mp
   178  }
   179  
   180  // Called to initialize a new m (including the bootstrap m).
   181  // Called on the new thread, cannot allocate memory.
   182  func minit() {
   183  	// m.procid is a uint64, but lwp_start writes an int32. Fix it up.
   184  	_g_ := getg()
   185  	_g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid)))
   186  
   187  	minitSignals()
   188  }
   189  
   190  // Called from dropm to undo the effect of an minit.
   191  //go:nosplit
   192  func unminit() {
   193  	unminitSignals()
   194  }
   195  
   196  func memlimit() uintptr {
   197  	/*
   198  		                TODO: Convert to Go when something actually uses the result.
   199  
   200  				Rlimit rl;
   201  				extern byte runtime·text[], runtime·end[];
   202  				uintptr used;
   203  
   204  				if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
   205  					return 0;
   206  				if(rl.rlim_cur >= 0x7fffffff)
   207  					return 0;
   208  
   209  				// Estimate our VM footprint excluding the heap.
   210  				// Not an exact science: use size of binary plus
   211  				// some room for thread stacks.
   212  				used = runtime·end - runtime·text + (64<<20);
   213  				if(used >= rl.rlim_cur)
   214  					return 0;
   215  
   216  				// If there's not at least 16 MB left, we're probably
   217  				// not going to be able to do much. Treat as no limit.
   218  				rl.rlim_cur -= used;
   219  				if(rl.rlim_cur < (16<<20))
   220  					return 0;
   221  
   222  				return rl.rlim_cur - used;
   223  	*/
   224  	return 0
   225  }
   226  
   227  func sigtramp()
   228  
   229  type sigactiont struct {
   230  	sa_sigaction uintptr
   231  	sa_flags     int32
   232  	sa_mask      sigset
   233  }
   234  
   235  //go:nosplit
   236  //go:nowritebarrierrec
   237  func setsig(i uint32, fn uintptr) {
   238  	var sa sigactiont
   239  	sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
   240  	sa.sa_mask = sigset_all
   241  	if fn == funcPC(sighandler) {
   242  		fn = funcPC(sigtramp)
   243  	}
   244  	sa.sa_sigaction = fn
   245  	sigaction(i, &sa, nil)
   246  }
   247  
   248  //go:nosplit
   249  //go:nowritebarrierrec
   250  func setsigstack(i uint32) {
   251  	throw("setsigstack")
   252  }
   253  
   254  //go:nosplit
   255  //go:nowritebarrierrec
   256  func getsig(i uint32) uintptr {
   257  	var sa sigactiont
   258  	sigaction(i, nil, &sa)
   259  	return sa.sa_sigaction
   260  }
   261  
   262  // setSignaltstackSP sets the ss_sp field of a stackt.
   263  //go:nosplit
   264  func setSignalstackSP(s *stackt, sp uintptr) {
   265  	s.ss_sp = sp
   266  }
   267  
   268  //go:nosplit
   269  //go:nowritebarrierrec
   270  func sigaddset(mask *sigset, i int) {
   271  	mask.__bits[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31)
   272  }
   273  
   274  func sigdelset(mask *sigset, i int) {
   275  	mask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
   276  }
   277  
   278  func (c *sigctxt) fixsigcode(sig uint32) {
   279  }