diff options
Diffstat (limited to 'src/runtime/vdso_freebsd.go')
-rw-r--r-- | src/runtime/vdso_freebsd.go | 114 |
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..122cc8b --- /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. + +// +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 walltime1() (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) +} |