github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/runtime/vdso_freebsd_x86.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 // +build freebsd 6 // +build 386 amd64 7 8 package runtime 9 10 import ( 11 "runtime/internal/atomic" 12 "unsafe" 13 ) 14 15 const ( 16 _VDSO_TH_ALGO_X86_TSC = 1 17 _VDSO_TH_ALGO_X86_HPET = 2 18 ) 19 20 const ( 21 _HPET_DEV_MAP_MAX = 10 22 _HPET_MAIN_COUNTER = 0xf0 /* Main counter register */ 23 24 hpetDevPath = "/dev/hpetX\x00" 25 ) 26 27 var hpetDevMap [_HPET_DEV_MAP_MAX]uintptr 28 29 //go:nosplit 30 func (th *vdsoTimehands) getTSCTimecounter() uint32 { 31 tsc := cputicks() 32 if th.x86_shift > 0 { 33 tsc >>= th.x86_shift 34 } 35 return uint32(tsc) 36 } 37 38 //go:systemstack 39 func (th *vdsoTimehands) getHPETTimecounter() (uint32, bool) { 40 const digits = "0123456789" 41 42 idx := int(th.x86_hpet_idx) 43 if idx >= len(hpetDevMap) { 44 return 0, false 45 } 46 47 p := atomic.Loaduintptr(&hpetDevMap[idx]) 48 if p == 0 { 49 var devPath [len(hpetDevPath)]byte 50 copy(devPath[:], hpetDevPath) 51 devPath[9] = digits[idx] 52 53 fd := open(&devPath[0], 0 /* O_RDONLY */, 0) 54 if fd < 0 { 55 atomic.Casuintptr(&hpetDevMap[idx], 0, ^uintptr(0)) 56 return 0, false 57 } 58 59 addr, mmapErr := mmap(nil, physPageSize, _PROT_READ, _MAP_SHARED, fd, 0) 60 closefd(fd) 61 newP := uintptr(addr) 62 if mmapErr != 0 { 63 newP = ^uintptr(0) 64 } 65 if !atomic.Casuintptr(&hpetDevMap[idx], 0, newP) && mmapErr == 0 { 66 munmap(addr, physPageSize) 67 } 68 p = atomic.Loaduintptr(&hpetDevMap[idx]) 69 } 70 if p == ^uintptr(0) { 71 return 0, false 72 } 73 return *(*uint32)(unsafe.Pointer(p + _HPET_MAIN_COUNTER)), true 74 } 75 76 //go:nosplit 77 func (th *vdsoTimehands) getTimecounter() (uint32, bool) { 78 switch th.algo { 79 case _VDSO_TH_ALGO_X86_TSC: 80 return th.getTSCTimecounter(), true 81 case _VDSO_TH_ALGO_X86_HPET: 82 var ( 83 tc uint32 84 ok bool 85 ) 86 systemstack(func() { 87 tc, ok = th.getHPETTimecounter() 88 }) 89 return tc, ok 90 default: 91 return 0, false 92 } 93 }