github.com/fenixara/go@v0.0.0-20170127160404-96ea0918e670/src/runtime/os_freebsd.go (about)

     1  // Copyright 2011 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  type mOS struct{}
    13  
    14  //go:noescape
    15  func thr_new(param *thrparam, size int32)
    16  
    17  //go:noescape
    18  func sigaltstack(new, old *stackt)
    19  
    20  //go:noescape
    21  func sigaction(sig uint32, new, old *sigactiont)
    22  
    23  //go:noescape
    24  func sigprocmask(how int32, new, old *sigset)
    25  
    26  //go:noescape
    27  func setitimer(mode int32, new, old *itimerval)
    28  
    29  //go:noescape
    30  func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
    31  
    32  //go:noescape
    33  func getrlimit(kind int32, limit unsafe.Pointer) int32
    34  func raise(sig uint32)
    35  func raiseproc(sig uint32)
    36  
    37  //go:noescape
    38  func sys_umtx_op(addr *uint32, mode int32, val uint32, uaddr1 uintptr, ut *umtx_time) int32
    39  
    40  func osyield()
    41  
    42  // From FreeBSD's <sys/sysctl.h>
    43  const (
    44  	_CTL_HW      = 6
    45  	_HW_NCPU     = 3
    46  	_HW_PAGESIZE = 7
    47  )
    48  
    49  var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
    50  
    51  func getncpu() int32 {
    52  	mib := [2]uint32{_CTL_HW, _HW_NCPU}
    53  	out := uint32(0)
    54  	nout := unsafe.Sizeof(out)
    55  	ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
    56  	if ret >= 0 {
    57  		return int32(out)
    58  	}
    59  	return 1
    60  }
    61  
    62  func getPageSize() uintptr {
    63  	mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
    64  	out := uint32(0)
    65  	nout := unsafe.Sizeof(out)
    66  	ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
    67  	if ret >= 0 {
    68  		return uintptr(out)
    69  	}
    70  	return 0
    71  }
    72  
    73  // FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and
    74  // thus the code is largely similar. See Linux implementation
    75  // and lock_futex.go for comments.
    76  
    77  //go:nosplit
    78  func futexsleep(addr *uint32, val uint32, ns int64) {
    79  	systemstack(func() {
    80  		futexsleep1(addr, val, ns)
    81  	})
    82  }
    83  
    84  func futexsleep1(addr *uint32, val uint32, ns int64) {
    85  	var utp *umtx_time
    86  	if ns >= 0 {
    87  		var ut umtx_time
    88  		ut._clockid = _CLOCK_MONOTONIC
    89  		ut._timeout.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ut._timeout.tv_nsec)))))
    90  		utp = &ut
    91  	}
    92  	ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, unsafe.Sizeof(*utp), utp)
    93  	if ret >= 0 || ret == -_EINTR {
    94  		return
    95  	}
    96  	print("umtx_wait addr=", addr, " val=", val, " ret=", ret, "\n")
    97  	*(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005
    98  }
    99  
   100  //go:nosplit
   101  func futexwakeup(addr *uint32, cnt uint32) {
   102  	ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, 0, nil)
   103  	if ret >= 0 {
   104  		return
   105  	}
   106  
   107  	systemstack(func() {
   108  		print("umtx_wake_addr=", addr, " ret=", ret, "\n")
   109  	})
   110  }
   111  
   112  func thr_start()
   113  
   114  // May run with m.p==nil, so write barriers are not allowed.
   115  //go:nowritebarrier
   116  func newosproc(mp *m, stk unsafe.Pointer) {
   117  	if false {
   118  		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", funcPC(thr_start), " id=", mp.id, " ostk=", &mp, "\n")
   119  	}
   120  
   121  	// NOTE(rsc): This code is confused. stackbase is the top of the stack
   122  	// and is equal to stk. However, it's working, so I'm not changing it.
   123  	param := thrparam{
   124  		start_func: funcPC(thr_start),
   125  		arg:        unsafe.Pointer(mp),
   126  		stack_base: mp.g0.stack.hi,
   127  		stack_size: uintptr(stk) - mp.g0.stack.hi,
   128  		child_tid:  unsafe.Pointer(&mp.procid),
   129  		parent_tid: nil,
   130  		tls_base:   unsafe.Pointer(&mp.tls[0]),
   131  		tls_size:   unsafe.Sizeof(mp.tls),
   132  	}
   133  
   134  	var oset sigset
   135  	sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
   136  	// TODO: Check for error.
   137  	thr_new(&param, int32(unsafe.Sizeof(param)))
   138  	sigprocmask(_SIG_SETMASK, &oset, nil)
   139  }
   140  
   141  func osinit() {
   142  	ncpu = getncpu()
   143  	physPageSize = getPageSize()
   144  }
   145  
   146  var urandom_dev = []byte("/dev/urandom\x00")
   147  
   148  //go:nosplit
   149  func getRandomData(r []byte) {
   150  	fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
   151  	n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
   152  	closefd(fd)
   153  	extendRandom(r, int(n))
   154  }
   155  
   156  func goenvs() {
   157  	goenvs_unix()
   158  }
   159  
   160  // Called to initialize a new m (including the bootstrap m).
   161  // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
   162  func mpreinit(mp *m) {
   163  	mp.gsignal = malg(32 * 1024)
   164  	mp.gsignal.m = mp
   165  }
   166  
   167  // Called to initialize a new m (including the bootstrap m).
   168  // Called on the new thread, cannot allocate memory.
   169  func minit() {
   170  	// m.procid is a uint64, but thr_new writes a uint32 on 32-bit systems.
   171  	// Fix it up. (Only matters on big-endian, but be clean anyway.)
   172  	if sys.PtrSize == 4 {
   173  		_g_ := getg()
   174  		_g_.m.procid = uint64(*(*uint32)(unsafe.Pointer(&_g_.m.procid)))
   175  	}
   176  
   177  	minitSignals()
   178  }
   179  
   180  // Called from dropm to undo the effect of an minit.
   181  //go:nosplit
   182  func unminit() {
   183  	unminitSignals()
   184  }
   185  
   186  func memlimit() uintptr {
   187  	/*
   188  		TODO: Convert to Go when something actually uses the result.
   189  		Rlimit rl;
   190  		extern byte runtime·text[], runtime·end[];
   191  		uintptr used;
   192  
   193  		if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
   194  			return 0;
   195  		if(rl.rlim_cur >= 0x7fffffff)
   196  			return 0;
   197  
   198  		// Estimate our VM footprint excluding the heap.
   199  		// Not an exact science: use size of binary plus
   200  		// some room for thread stacks.
   201  		used = runtime·end - runtime·text + (64<<20);
   202  		if(used >= rl.rlim_cur)
   203  			return 0;
   204  
   205  		// If there's not at least 16 MB left, we're probably
   206  		// not going to be able to do much. Treat as no limit.
   207  		rl.rlim_cur -= used;
   208  		if(rl.rlim_cur < (16<<20))
   209  			return 0;
   210  
   211  		return rl.rlim_cur - used;
   212  	*/
   213  
   214  	return 0
   215  }
   216  
   217  func sigtramp()
   218  
   219  type sigactiont struct {
   220  	sa_handler uintptr
   221  	sa_flags   int32
   222  	sa_mask    sigset
   223  }
   224  
   225  //go:nosplit
   226  //go:nowritebarrierrec
   227  func setsig(i uint32, fn uintptr) {
   228  	var sa sigactiont
   229  	sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
   230  	sa.sa_mask = sigset_all
   231  	if fn == funcPC(sighandler) {
   232  		fn = funcPC(sigtramp)
   233  	}
   234  	sa.sa_handler = fn
   235  	sigaction(i, &sa, nil)
   236  }
   237  
   238  //go:nosplit
   239  //go:nowritebarrierrec
   240  func setsigstack(i uint32) {
   241  	throw("setsigstack")
   242  }
   243  
   244  //go:nosplit
   245  //go:nowritebarrierrec
   246  func getsig(i uint32) uintptr {
   247  	var sa sigactiont
   248  	sigaction(i, nil, &sa)
   249  	return sa.sa_handler
   250  }
   251  
   252  // setSignaltstackSP sets the ss_sp field of a stackt.
   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  func (c *sigctxt) fixsigcode(sig uint32) {
   269  }