summaryrefslogtreecommitdiffstats
path: root/src/runtime/vdso_freebsd.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/vdso_freebsd.go')
-rw-r--r--src/runtime/vdso_freebsd.go114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/runtime/vdso_freebsd.go b/src/runtime/vdso_freebsd.go
new file mode 100644
index 0000000..0fe21cf
--- /dev/null
+++ b/src/runtime/vdso_freebsd.go
@@ -0,0 +1,114 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build freebsd
+
+package runtime
+
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
+
+const _VDSO_TH_NUM = 4 // defined in <sys/vdso.h> #ifdef _KERNEL
+
+var timekeepSharedPage *vdsoTimekeep
+
+//go:nosplit
+func (bt *bintime) Add(bt2 *bintime) {
+ u := bt.frac
+ bt.frac += bt2.frac
+ if u > bt.frac {
+ bt.sec++
+ }
+ bt.sec += bt2.sec
+}
+
+//go:nosplit
+func (bt *bintime) AddX(x uint64) {
+ u := bt.frac
+ bt.frac += x
+ if u > bt.frac {
+ bt.sec++
+ }
+}
+
+var (
+ // binuptimeDummy is used in binuptime as the address of an atomic.Load, to simulate
+ // an atomic_thread_fence_acq() call which behaves as an instruction reordering and
+ // memory barrier.
+ binuptimeDummy uint32
+
+ zeroBintime bintime
+)
+
+// based on /usr/src/lib/libc/sys/__vdso_gettimeofday.c
+//
+//go:nosplit
+func binuptime(abs bool) (bt bintime) {
+ timehands := (*[_VDSO_TH_NUM]vdsoTimehands)(add(unsafe.Pointer(timekeepSharedPage), vdsoTimekeepSize))
+ for {
+ if timekeepSharedPage.enabled == 0 {
+ return zeroBintime
+ }
+
+ curr := atomic.Load(&timekeepSharedPage.current) // atomic_load_acq_32
+ th := &timehands[curr]
+ gen := atomic.Load(&th.gen) // atomic_load_acq_32
+ bt = th.offset
+
+ if tc, ok := th.getTimecounter(); !ok {
+ return zeroBintime
+ } else {
+ delta := (tc - th.offset_count) & th.counter_mask
+ bt.AddX(th.scale * uint64(delta))
+ }
+ if abs {
+ bt.Add(&th.boottime)
+ }
+
+ atomic.Load(&binuptimeDummy) // atomic_thread_fence_acq()
+ if curr == timekeepSharedPage.current && gen != 0 && gen == th.gen {
+ break
+ }
+ }
+ return bt
+}
+
+//go:nosplit
+func vdsoClockGettime(clockID int32) bintime {
+ if timekeepSharedPage == nil || timekeepSharedPage.ver != _VDSO_TK_VER_CURR {
+ return zeroBintime
+ }
+ abs := false
+ switch clockID {
+ case _CLOCK_MONOTONIC:
+ /* ok */
+ case _CLOCK_REALTIME:
+ abs = true
+ default:
+ return zeroBintime
+ }
+ return binuptime(abs)
+}
+
+func fallback_nanotime() int64
+func fallback_walltime() (sec int64, nsec int32)
+
+//go:nosplit
+func nanotime1() int64 {
+ bt := vdsoClockGettime(_CLOCK_MONOTONIC)
+ if bt == zeroBintime {
+ return fallback_nanotime()
+ }
+ return int64((1e9 * uint64(bt.sec)) + ((1e9 * uint64(bt.frac>>32)) >> 32))
+}
+
+func walltime() (sec int64, nsec int32) {
+ bt := vdsoClockGettime(_CLOCK_REALTIME)
+ if bt == zeroBintime {
+ return fallback_walltime()
+ }
+ return int64(bt.sec), int32((1e9 * uint64(bt.frac>>32)) >> 32)
+}