Source file
src/runtime/vdso_freebsd_x86.go
1
2
3
4
5
6
7 package runtime
8
9 import (
10 "internal/runtime/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
22
23 hpetDevPath = "/dev/hpetX\x00"
24 )
25
26 var hpetDevMap [_HPET_DEV_MAP_MAX]uintptr
27
28
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
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
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_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
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 }
91
View as plain text