...

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		"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	//go:nosplit
   256	func (c *sigctxt) fixsigcode(sig uint32) {
   257	}
   258	
   259	func sysargs(argc int32, argv **byte) {
   260		n := argc + 1
   261	
   262		// skip over argv, envp to get to auxv
   263		for argv_index(argv, n) != nil {
   264			n++
   265		}
   266	
   267		// skip NULL separator
   268		n++
   269	
   270		auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
   271		sysauxv(auxv[:])
   272	}
   273	
   274	const (
   275		_AT_NULL   = 0
   276		_AT_PAGESZ = 6
   277	)
   278	
   279	func sysauxv(auxv []uintptr) {
   280		for i := 0; auxv[i] != _AT_NULL; i += 2 {
   281			tag, val := auxv[i], auxv[i+1]
   282			switch tag {
   283			case _AT_PAGESZ:
   284				physPageSize = val
   285			}
   286		}
   287	}
   288	

View as plain text