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