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