1// Copyright 2021 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 windows 6 7package testing 8 9import ( 10 "errors" 11 "internal/syscall/windows" 12 "math/bits" 13 "syscall" 14 "time" 15) 16 17// isWindowsRetryable reports whether err is a Windows error code 18// that may be fixed by retrying a failed filesystem operation. 19func isWindowsRetryable(err error) bool { 20 for { 21 unwrapped := errors.Unwrap(err) 22 if unwrapped == nil { 23 break 24 } 25 err = unwrapped 26 } 27 if err == syscall.ERROR_ACCESS_DENIED { 28 return true // Observed in https://go.dev/issue/50051. 29 } 30 if err == windows.ERROR_SHARING_VIOLATION { 31 return true // Observed in https://go.dev/issue/51442. 32 } 33 return false 34} 35 36// highPrecisionTime represents a single point in time with query performance counter. 37// time.Time on Windows has low system granularity, which is not suitable for 38// measuring short time intervals. 39// 40// TODO: If Windows runtime implements high resolution timing then highPrecisionTime 41// can be removed. 42type highPrecisionTime struct { 43 now int64 44} 45 46// highPrecisionTimeNow returns high precision time for benchmarking. 47func highPrecisionTimeNow() highPrecisionTime { 48 var t highPrecisionTime 49 // This should always succeed for Windows XP and above. 50 t.now = windows.QueryPerformanceCounter() 51 return t 52} 53 54func (a highPrecisionTime) sub(b highPrecisionTime) time.Duration { 55 delta := a.now - b.now 56 57 if queryPerformanceFrequency == 0 { 58 queryPerformanceFrequency = windows.QueryPerformanceFrequency() 59 } 60 hi, lo := bits.Mul64(uint64(delta), uint64(time.Second)/uint64(time.Nanosecond)) 61 quo, _ := bits.Div64(hi, lo, uint64(queryPerformanceFrequency)) 62 return time.Duration(quo) 63} 64 65var queryPerformanceFrequency int64 66 67// highPrecisionTimeSince returns duration since a. 68func highPrecisionTimeSince(a highPrecisionTime) time.Duration { 69 return highPrecisionTimeNow().sub(a) 70} 71