@@ -1027,9 +1027,76 @@ _PyTime_TimeWithInfo(PyTime_t *t, _Py_clock_info_t *info)
10271027}
10281028
10291029
1030+ #ifdef MS_WINDOWS
1031+ static int
1032+ py_win_perf_counter_frequency (_PyTimeFraction * base , int raise_exc )
1033+ {
1034+ LARGE_INTEGER freq ;
1035+ // Since Windows XP, the function cannot fail.
1036+ (void )QueryPerformanceFrequency (& freq );
1037+ LONGLONG frequency = freq .QuadPart ;
1038+
1039+ // Since Windows XP, frequency cannot be zero.
1040+ assert (frequency >= 1 );
1041+
1042+ Py_BUILD_ASSERT (sizeof (PyTime_t ) == sizeof (frequency ));
1043+ PyTime_t denom = (PyTime_t )frequency ;
1044+
1045+ // Known QueryPerformanceFrequency() values:
1046+ //
1047+ // * 10,000,000 (10 MHz): 100 ns resolution
1048+ // * 3,579,545 Hz (3.6 MHz): 279 ns resolution
1049+ if (_PyTimeFraction_Set (base , SEC_TO_NS , denom ) < 0 ) {
1050+ if (raise_exc ) {
1051+ PyErr_SetString (PyExc_RuntimeError ,
1052+ "invalid QueryPerformanceFrequency" );
1053+ }
1054+ return -1 ;
1055+ }
1056+ return 0 ;
1057+ }
1058+
1059+
1060+ // N.B. If raise_exc=0, this may be called without the GIL.
1061+ static int
1062+ py_get_win_perf_counter (PyTime_t * tp , _Py_clock_info_t * info , int raise_exc )
1063+ {
1064+ assert (info == NULL || raise_exc );
1065+
1066+ static _PyTimeFraction base = {0 , 0 };
1067+ if (base .denom == 0 ) {
1068+ if (py_win_perf_counter_frequency (& base , raise_exc ) < 0 ) {
1069+ return -1 ;
1070+ }
1071+ }
1072+
1073+ if (info ) {
1074+ info -> implementation = "QueryPerformanceCounter()" ;
1075+ info -> resolution = _PyTimeFraction_Resolution (& base );
1076+ info -> monotonic = 1 ;
1077+ info -> adjustable = 0 ;
1078+ }
1079+
1080+ LARGE_INTEGER now ;
1081+ QueryPerformanceCounter (& now );
1082+ LONGLONG ticksll = now .QuadPart ;
1083+
1084+ /* Make sure that casting LONGLONG to PyTime_t cannot overflow,
1085+ both types are signed */
1086+ PyTime_t ticks ;
1087+ static_assert (sizeof (ticksll ) <= sizeof (ticks ),
1088+ "LONGLONG is larger than PyTime_t" );
1089+ ticks = (PyTime_t )ticksll ;
1090+
1091+ * tp = _PyTimeFraction_Mul (ticks , & base );
1092+ return 0 ;
1093+ }
1094+ #endif // MS_WINDOWS
1095+
1096+
10301097#ifdef __APPLE__
10311098static int
1032- py_mach_timebase_info (_PyTimeFraction * base , int raise )
1099+ py_mach_timebase_info (_PyTimeFraction * base , int raise_exc )
10331100{
10341101 mach_timebase_info_data_t timebase ;
10351102 // According to the Technical Q&A QA1398, mach_timebase_info() cannot
@@ -1051,7 +1118,7 @@ py_mach_timebase_info(_PyTimeFraction *base, int raise)
10511118 // * (1000000000, 33333335) on PowerPC: ~30 ns
10521119 // * (1000000000, 25000000) on PowerPC: 40 ns
10531120 if (_PyTimeFraction_Set (base , numer , denom ) < 0 ) {
1054- if (raise ) {
1121+ if (raise_exc ) {
10551122 PyErr_SetString (PyExc_RuntimeError ,
10561123 "invalid mach_timebase_info" );
10571124 }
@@ -1069,42 +1136,9 @@ py_get_monotonic_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
10691136 assert (info == NULL || raise_exc );
10701137
10711138#if defined(MS_WINDOWS )
1072- ULONGLONG ticks = GetTickCount64 ();
1073- static_assert (sizeof (ticks ) <= sizeof (PyTime_t ),
1074- "ULONGLONG is larger than PyTime_t" );
1075- PyTime_t t ;
1076- if (ticks <= (ULONGLONG )PyTime_MAX ) {
1077- t = (PyTime_t )ticks ;
1078- }
1079- else {
1080- // GetTickCount64() maximum is larger than PyTime_t maximum:
1081- // ULONGLONG is unsigned, whereas PyTime_t is signed.
1082- t = PyTime_MAX ;
1083- }
1084-
1085- int res = pytime_mul (& t , MS_TO_NS );
1086- * tp = t ;
1087-
1088- if (raise_exc && res < 0 ) {
1089- pytime_overflow ();
1139+ if (py_get_win_perf_counter (tp , info , raise_exc ) < 0 ) {
10901140 return -1 ;
10911141 }
1092-
1093- if (info ) {
1094- DWORD timeAdjustment , timeIncrement ;
1095- BOOL isTimeAdjustmentDisabled , ok ;
1096- info -> implementation = "GetTickCount64()" ;
1097- info -> monotonic = 1 ;
1098- ok = GetSystemTimeAdjustment (& timeAdjustment , & timeIncrement ,
1099- & isTimeAdjustmentDisabled );
1100- if (!ok ) {
1101- PyErr_SetFromWindowsErr (0 );
1102- return -1 ;
1103- }
1104- info -> resolution = timeIncrement * 1e-7 ;
1105- info -> adjustable = 0 ;
1106- }
1107-
11081142#elif defined(__APPLE__ )
11091143 static _PyTimeFraction base = {0 , 0 };
11101144 if (base .denom == 0 ) {
@@ -1190,8 +1224,7 @@ _PyTime_MonotonicUnchecked(void)
11901224{
11911225 PyTime_t t ;
11921226 if (py_get_monotonic_clock (& t , NULL , 0 ) < 0 ) {
1193- // If mach_timebase_info(), clock_gettime() or gethrtime() fails:
1194- // silently ignore the failure and return 0.
1227+ // Ignore silently the error and return 0.
11951228 t = 0 ;
11961229 }
11971230 return t ;
@@ -1216,122 +1249,24 @@ _PyTime_MonotonicWithInfo(PyTime_t *tp, _Py_clock_info_t *info)
12161249}
12171250
12181251
1219- #ifdef MS_WINDOWS
1220- static int
1221- py_win_perf_counter_frequency (_PyTimeFraction * base , int raise )
1222- {
1223- LONGLONG frequency ;
1224-
1225- LARGE_INTEGER freq ;
1226- // Since Windows XP, the function cannot fail.
1227- (void )QueryPerformanceFrequency (& freq );
1228- frequency = freq .QuadPart ;
1229-
1230- // Since Windows XP, frequency cannot be zero.
1231- assert (frequency >= 1 );
1232-
1233- Py_BUILD_ASSERT (sizeof (PyTime_t ) == sizeof (frequency ));
1234- PyTime_t denom = (PyTime_t )frequency ;
1235-
1236- // Known QueryPerformanceFrequency() values:
1237- //
1238- // * 10,000,000 (10 MHz): 100 ns resolution
1239- // * 3,579,545 Hz (3.6 MHz): 279 ns resolution
1240- if (_PyTimeFraction_Set (base , SEC_TO_NS , denom ) < 0 ) {
1241- if (raise ) {
1242- PyErr_SetString (PyExc_RuntimeError ,
1243- "invalid QueryPerformanceFrequency" );
1244- }
1245- return -1 ;
1246- }
1247- return 0 ;
1248- }
1249-
1250-
1251- // N.B. If raise_exc=0, this may be called without the GIL.
1252- static int
1253- py_get_win_perf_counter (PyTime_t * tp , _Py_clock_info_t * info , int raise_exc )
1254- {
1255- assert (info == NULL || raise_exc );
1256-
1257- static _PyTimeFraction base = {0 , 0 };
1258- if (base .denom == 0 ) {
1259- if (py_win_perf_counter_frequency (& base , raise_exc ) < 0 ) {
1260- return -1 ;
1261- }
1262- }
1263-
1264- if (info ) {
1265- info -> implementation = "QueryPerformanceCounter()" ;
1266- info -> resolution = _PyTimeFraction_Resolution (& base );
1267- info -> monotonic = 1 ;
1268- info -> adjustable = 0 ;
1269- }
1270-
1271- LARGE_INTEGER now ;
1272- QueryPerformanceCounter (& now );
1273- LONGLONG ticksll = now .QuadPart ;
1274-
1275- /* Make sure that casting LONGLONG to PyTime_t cannot overflow,
1276- both types are signed */
1277- PyTime_t ticks ;
1278- static_assert (sizeof (ticksll ) <= sizeof (ticks ),
1279- "LONGLONG is larger than PyTime_t" );
1280- ticks = (PyTime_t )ticksll ;
1281-
1282- PyTime_t ns = _PyTimeFraction_Mul (ticks , & base );
1283- * tp = ns ;
1284- return 0 ;
1285- }
1286- #endif // MS_WINDOWS
1287-
1288-
12891252int
12901253_PyTime_PerfCounterWithInfo (PyTime_t * t , _Py_clock_info_t * info )
12911254{
1292- #ifdef MS_WINDOWS
1293- return py_get_win_perf_counter (t , info , 1 );
1294- #else
12951255 return _PyTime_MonotonicWithInfo (t , info );
1296- #endif
12971256}
12981257
12991258
13001259PyTime_t
13011260_PyTime_PerfCounterUnchecked (void )
13021261{
1303- PyTime_t t ;
1304- int res ;
1305- #ifdef MS_WINDOWS
1306- res = py_get_win_perf_counter (& t , NULL , 0 );
1307- #else
1308- res = py_get_monotonic_clock (& t , NULL , 0 );
1309- #endif
1310- if (res < 0 ) {
1311- // If py_win_perf_counter_frequency() or py_get_monotonic_clock()
1312- // fails: silently ignore the failure and return 0.
1313- t = 0 ;
1314- }
1315- return t ;
1262+ return _PyTime_MonotonicUnchecked ();
13161263}
13171264
13181265
13191266int
13201267PyTime_PerfCounter (PyTime_t * result )
13211268{
1322- int res ;
1323- #ifdef MS_WINDOWS
1324- res = py_get_win_perf_counter (result , NULL , 1 );
1325- #else
1326- res = py_get_monotonic_clock (result , NULL , 1 );
1327- #endif
1328- if (res < 0 ) {
1329- // If py_win_perf_counter_frequency() or py_get_monotonic_clock()
1330- // fails: silently ignore the failure and return 0.
1331- * result = 0 ;
1332- return -1 ;
1333- }
1334- return 0 ;
1269+ return PyTime_Monotonic (result );
13351270}
13361271
13371272
0 commit comments