From a9fc37525891e47b4277cde040a06db585e1780d Mon Sep 17 00:00:00 2001 From: Yuval Pavel Zholkover Date: Fri, 4 May 2018 15:01:44 +0300 Subject: [PATCH] runtime: fast clock_gettime on FreeBSD, always call getHPETTimecounter on systemstack CL 108095 goes to some length inorder to keep the stack usage of getHPETTimecounter code paths bellow a limit being checked by the linker analysis. That limit is spurious, when running on the system or signal stack. In a similar scenario, cgocallback_gofunc performs an indirect call through AX to hide the call from the linker analysis. Here instead, mark getHPETTimecounter //go:systemstack and call it appropriately. Change-Id: I80bec5e4974eee3c564d94f6e1142f322df88b2f Reviewed-on: https://go-review.googlesource.com/111495 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/runtime/vdso_freebsd_x86.go | 37 +++++++++++++++++---------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/runtime/vdso_freebsd_x86.go b/src/runtime/vdso_freebsd_x86.go index 1b1be5f9256..1fa5d80dcc0 100644 --- a/src/runtime/vdso_freebsd_x86.go +++ b/src/runtime/vdso_freebsd_x86.go @@ -20,23 +20,11 @@ const ( const ( _HPET_DEV_MAP_MAX = 10 _HPET_MAIN_COUNTER = 0xf0 /* Main counter register */ + + hpetDevPath = "/dev/hpetX\x00" ) -var ( - hpetDevMap [_HPET_DEV_MAP_MAX]uintptr - hpetDevPath = [_HPET_DEV_MAP_MAX][11]byte{ - {'/', 'd', 'e', 'v', '/', 'h', 'p', 'e', 't', '0', 0}, - {'/', 'd', 'e', 'v', '/', 'h', 'p', 'e', 't', '1', 0}, - {'/', 'd', 'e', 'v', '/', 'h', 'p', 'e', 't', '2', 0}, - {'/', 'd', 'e', 'v', '/', 'h', 'p', 'e', 't', '3', 0}, - {'/', 'd', 'e', 'v', '/', 'h', 'p', 'e', 't', '4', 0}, - {'/', 'd', 'e', 'v', '/', 'h', 'p', 'e', 't', '5', 0}, - {'/', 'd', 'e', 'v', '/', 'h', 'p', 'e', 't', '6', 0}, - {'/', 'd', 'e', 'v', '/', 'h', 'p', 'e', 't', '7', 0}, - {'/', 'd', 'e', 'v', '/', 'h', 'p', 'e', 't', '8', 0}, - {'/', 'd', 'e', 'v', '/', 'h', 'p', 'e', 't', '9', 0}, - } -) +var hpetDevMap [_HPET_DEV_MAP_MAX]uintptr //go:nosplit func (th *vdsoTimehands) getTSCTimecounter() uint32 { @@ -47,8 +35,10 @@ func (th *vdsoTimehands) getTSCTimecounter() uint32 { return uint32(tsc) } -//go:nosplit +//go:systemstack func (th *vdsoTimehands) getHPETTimecounter() (uint32, bool) { + const digits = "0123456789" + idx := int(th.x86_hpet_idx) if idx >= len(hpetDevMap) { return 0, false @@ -56,7 +46,11 @@ func (th *vdsoTimehands) getHPETTimecounter() (uint32, bool) { p := atomic.Loaduintptr(&hpetDevMap[idx]) if p == 0 { - fd := open(&hpetDevPath[idx][0], 0 /* O_RDONLY */, 0) + var devPath [len(hpetDevPath)]byte + copy(devPath[:], hpetDevPath) + devPath[9] = digits[idx] + + fd := open(&devPath[0], 0 /* O_RDONLY */, 0) if fd < 0 { atomic.Casuintptr(&hpetDevMap[idx], 0, ^uintptr(0)) return 0, false @@ -85,7 +79,14 @@ func (th *vdsoTimehands) getTimecounter() (uint32, bool) { case _VDSO_TH_ALGO_X86_TSC: return th.getTSCTimecounter(), true case _VDSO_TH_ALGO_X86_HPET: - return th.getHPETTimecounter() + var ( + tc uint32 + ok bool + ) + systemstack(func() { + tc, ok = th.getHPETTimecounter() + }) + return tc, ok default: return 0, false }