...

Source file src/runtime/vdso_freebsd_x86.go

     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	}
    94	

View as plain text