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