github.com/comwrg/go/src@v0.0.0-20220319063731-c238d0440370/runtime/vdso_freebsd.go (about) 1 // Copyright 2018 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 //go:build freebsd 6 // +build freebsd 7 8 package runtime 9 10 import ( 11 "runtime/internal/atomic" 12 "unsafe" 13 ) 14 15 const _VDSO_TH_NUM = 4 // defined in <sys/vdso.h> #ifdef _KERNEL 16 17 var timekeepSharedPage *vdsoTimekeep 18 19 //go:nosplit 20 func (bt *bintime) Add(bt2 *bintime) { 21 u := bt.frac 22 bt.frac += bt2.frac 23 if u > bt.frac { 24 bt.sec++ 25 } 26 bt.sec += bt2.sec 27 } 28 29 //go:nosplit 30 func (bt *bintime) AddX(x uint64) { 31 u := bt.frac 32 bt.frac += x 33 if u > bt.frac { 34 bt.sec++ 35 } 36 } 37 38 var ( 39 // binuptimeDummy is used in binuptime as the address of an atomic.Load, to simulate 40 // an atomic_thread_fence_acq() call which behaves as an instruction reordering and 41 // memory barrier. 42 binuptimeDummy uint32 43 44 zeroBintime bintime 45 ) 46 47 // based on /usr/src/lib/libc/sys/__vdso_gettimeofday.c 48 // 49 //go:nosplit 50 func binuptime(abs bool) (bt bintime) { 51 timehands := (*[_VDSO_TH_NUM]vdsoTimehands)(add(unsafe.Pointer(timekeepSharedPage), vdsoTimekeepSize)) 52 for { 53 if timekeepSharedPage.enabled == 0 { 54 return zeroBintime 55 } 56 57 curr := atomic.Load(&timekeepSharedPage.current) // atomic_load_acq_32 58 th := &timehands[curr] 59 gen := atomic.Load(&th.gen) // atomic_load_acq_32 60 bt = th.offset 61 62 if tc, ok := th.getTimecounter(); !ok { 63 return zeroBintime 64 } else { 65 delta := (tc - th.offset_count) & th.counter_mask 66 bt.AddX(th.scale * uint64(delta)) 67 } 68 if abs { 69 bt.Add(&th.boottime) 70 } 71 72 atomic.Load(&binuptimeDummy) // atomic_thread_fence_acq() 73 if curr == timekeepSharedPage.current && gen != 0 && gen == th.gen { 74 break 75 } 76 } 77 return bt 78 } 79 80 //go:nosplit 81 func vdsoClockGettime(clockID int32) bintime { 82 if timekeepSharedPage == nil || timekeepSharedPage.ver != _VDSO_TK_VER_CURR { 83 return zeroBintime 84 } 85 abs := false 86 switch clockID { 87 case _CLOCK_MONOTONIC: 88 /* ok */ 89 case _CLOCK_REALTIME: 90 abs = true 91 default: 92 return zeroBintime 93 } 94 return binuptime(abs) 95 } 96 97 func fallback_nanotime() int64 98 func fallback_walltime() (sec int64, nsec int32) 99 100 //go:nosplit 101 func nanotime1() int64 { 102 bt := vdsoClockGettime(_CLOCK_MONOTONIC) 103 if bt == zeroBintime { 104 return fallback_nanotime() 105 } 106 return int64((1e9 * uint64(bt.sec)) + ((1e9 * uint64(bt.frac>>32)) >> 32)) 107 } 108 109 func walltime() (sec int64, nsec int32) { 110 bt := vdsoClockGettime(_CLOCK_REALTIME) 111 if bt == zeroBintime { 112 return fallback_walltime() 113 } 114 return int64(bt.sec), int32((1e9 * uint64(bt.frac>>32)) >> 32) 115 }