Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb52c753

Browse files
vstinnerencukou
andauthored
gh-110850: Add PyTime_TimeRaw() function (#118394)
Add "Raw" variant of PyTime functions:* PyTime_MonotonicRaw()* PyTime_PerfCounterRaw()* PyTime_TimeRaw()Changes:* Add documentation and tests. Tests release the GIL while calling raw clock functions.* py_get_system_clock() and py_get_monotonic_clock() now check that the GIL is hold by the caller if raise_exc is non-zero.* Reimplement "Unchecked" functions with raw clock functions.Co-authored-by: Petr Viktorin <encukou@gmail.com>
1 parenta8bcf3e commitb52c753

File tree

7 files changed

+189
-35
lines changed

7 files changed

+189
-35
lines changed

‎Doc/c-api/time.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,35 @@ with the :term:`GIL` held.
7272
See:func:`time.time` for details important on this clock.
7373
7474
75+
Raw Clock Functions
76+
-------------------
77+
78+
Similar to clock functions, but don't set an exception on error and don't
79+
require the caller to hold the GIL.
80+
81+
On success, the functions return ``0``.
82+
83+
On failure, they set ``*result`` to ``0`` and return ``-1``, *without* setting
84+
an exception. To get the cause of the error, acquire the GIL and call the
85+
regular (non-``Raw``) function. Note that the regular function may succeed after
86+
the ``Raw`` one failed.
87+
88+
.. c:function:: int PyTime_MonotonicRaw(PyTime_t *result)
89+
90+
Similar to:c:func:`PyTime_Monotonic`,
91+
but don't set an exception on error and don't require holding the GIL.
92+
93+
..c:function::intPyTime_PerfCounterRaw(PyTime_t *result)
94+
95+
Similar to:c:func:`PyTime_PerfCounter`,
96+
but don't set an exception on error and don't require holding the GIL.
97+
98+
..c:function::intPyTime_TimeRaw(PyTime_t *result)
99+
100+
Similar to:c:func:`PyTime_Time`,
101+
but don't set an exception on error and don't require holding the GIL.
102+
103+
75104
Conversion functions
76105
--------------------
77106

‎Doc/whatsnew/3.13.rst

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,9 +1901,15 @@ New Features
19011901

19021902
*:c:type:`PyTime_t` type.
19031903
*:c:var:`PyTime_MIN` and:c:var:`PyTime_MAX` constants.
1904-
*:c:func:`PyTime_AsSecondsDouble`
1905-
:c:func:`PyTime_Monotonic`,:c:func:`PyTime_PerfCounter`, and
1906-
:c:func:`PyTime_Time` functions.
1904+
* Add functions:
1905+
1906+
*:c:func:`PyTime_AsSecondsDouble`.
1907+
*:c:func:`PyTime_Monotonic`.
1908+
*:c:func:`PyTime_MonotonicRaw`.
1909+
*:c:func:`PyTime_PerfCounter`.
1910+
*:c:func:`PyTime_PerfCounterRaw`.
1911+
*:c:func:`PyTime_Time`.
1912+
*:c:func:`PyTime_TimeRaw`.
19071913

19081914
(Contributed by Victor Stinner and Petr Viktorin in:gh:`110850`.)
19091915

‎Include/cpython/pytime.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ PyAPI_FUNC(int) PyTime_Monotonic(PyTime_t *result);
1616
PyAPI_FUNC(int)PyTime_PerfCounter(PyTime_t*result);
1717
PyAPI_FUNC(int)PyTime_Time(PyTime_t*result);
1818

19+
PyAPI_FUNC(int)PyTime_MonotonicRaw(PyTime_t*result);
20+
PyAPI_FUNC(int)PyTime_PerfCounterRaw(PyTime_t*result);
21+
PyAPI_FUNC(int)PyTime_TimeRaw(PyTime_t*result);
22+
1923
#ifdef__cplusplus
2024
}
2125
#endif

‎Lib/test/test_capi/test_time.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ def test_min_max(self):
1818
self.assertEqual(PyTime_MIN,-2**63)
1919
self.assertEqual(PyTime_MAX,2**63-1)
2020

21-
defcheck_clock(self,c_func,py_func):
22-
t1=c_func()
23-
t2=py_func()
24-
self.assertAlmostEqual(t1,t2,delta=CLOCK_RES)
25-
2621
deftest_assecondsdouble(self):
2722
# Test PyTime_AsSecondsDouble()
2823
defns_to_sec(ns):
@@ -58,14 +53,22 @@ def ns_to_sec(ns):
5853
self.assertEqual(_testcapi.PyTime_AsSecondsDouble(ns),
5954
ns_to_sec(ns))
6055

56+
defcheck_clock(self,c_func,py_func):
57+
t1=c_func()
58+
t2=py_func()
59+
self.assertAlmostEqual(t1,t2,delta=CLOCK_RES)
60+
6161
deftest_monotonic(self):
62-
# Test PyTime_Monotonic()
62+
# Test PyTime_Monotonic() and PyTime_MonotonicRaw()
6363
self.check_clock(_testcapi.PyTime_Monotonic,time.monotonic)
64+
self.check_clock(_testcapi.PyTime_MonotonicRaw,time.monotonic)
6465

6566
deftest_perf_counter(self):
66-
# Test PyTime_PerfCounter()
67+
# Test PyTime_PerfCounter() and PyTime_PerfCounterRaw()
6768
self.check_clock(_testcapi.PyTime_PerfCounter,time.perf_counter)
69+
self.check_clock(_testcapi.PyTime_PerfCounterRaw,time.perf_counter)
6870

6971
deftest_time(self):
70-
# TestPyTime_time()
72+
# TestPyTime_Time() and PyTime_TimeRaw()
7173
self.check_clock(_testcapi.PyTime_Time,time.time)
74+
self.check_clock(_testcapi.PyTime_TimeRaw,time.time)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Add "Raw" variant of PyTime functions
2+
3+
*:c:func:`PyTime_MonotonicRaw`
4+
*:c:func:`PyTime_PerfCounterRaw`
5+
*:c:func:`PyTime_TimeRaw`
6+
7+
Patch by Victor Stinner.

‎Modules/_testcapi/time.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,25 @@ test_pytime_monotonic(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
5151
PyTime_tt;
5252
intres=PyTime_Monotonic(&t);
5353
if (res<0) {
54+
assert(t==0);
55+
returnNULL;
56+
}
57+
assert(res==0);
58+
returnpytime_as_float(t);
59+
}
60+
61+
62+
staticPyObject*
63+
test_pytime_monotonic_raw(PyObject*Py_UNUSED(self),PyObject*Py_UNUSED(args))
64+
{
65+
PyTime_tt;
66+
intres;
67+
Py_BEGIN_ALLOW_THREADS
68+
res=PyTime_MonotonicRaw(&t);
69+
Py_END_ALLOW_THREADS
70+
if (res<0) {
71+
assert(t==0);
72+
PyErr_SetString(PyExc_RuntimeError,"PyTime_MonotonicRaw() failed");
5473
returnNULL;
5574
}
5675
assert(res==0);
@@ -64,6 +83,25 @@ test_pytime_perf_counter(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
6483
PyTime_tt;
6584
intres=PyTime_PerfCounter(&t);
6685
if (res<0) {
86+
assert(t==0);
87+
returnNULL;
88+
}
89+
assert(res==0);
90+
returnpytime_as_float(t);
91+
}
92+
93+
94+
staticPyObject*
95+
test_pytime_perf_counter_raw(PyObject*Py_UNUSED(self),PyObject*Py_UNUSED(args))
96+
{
97+
PyTime_tt;
98+
intres;
99+
Py_BEGIN_ALLOW_THREADS
100+
res=PyTime_PerfCounterRaw(&t);
101+
Py_END_ALLOW_THREADS
102+
if (res<0) {
103+
assert(t==0);
104+
PyErr_SetString(PyExc_RuntimeError,"PyTime_PerfCounterRaw() failed");
67105
returnNULL;
68106
}
69107
assert(res==0);
@@ -77,6 +115,25 @@ test_pytime_time(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
77115
PyTime_tt;
78116
intres=PyTime_Time(&t);
79117
if (res<0) {
118+
assert(t==0);
119+
returnNULL;
120+
}
121+
assert(res==0);
122+
returnpytime_as_float(t);
123+
}
124+
125+
126+
staticPyObject*
127+
test_pytime_time_raw(PyObject*Py_UNUSED(self),PyObject*Py_UNUSED(args))
128+
{
129+
PyTime_tt;
130+
intres;
131+
Py_BEGIN_ALLOW_THREADS
132+
res=PyTime_TimeRaw(&t);
133+
Py_END_ALLOW_THREADS
134+
if (res<0) {
135+
assert(t==0);
136+
PyErr_SetString(PyExc_RuntimeError,"PyTime_TimeRaw() failed");
80137
returnNULL;
81138
}
82139
assert(res==0);
@@ -87,8 +144,11 @@ test_pytime_time(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
87144
staticPyMethodDeftest_methods[]= {
88145
{"PyTime_AsSecondsDouble",test_pytime_assecondsdouble,METH_VARARGS},
89146
{"PyTime_Monotonic",test_pytime_monotonic,METH_NOARGS},
147+
{"PyTime_MonotonicRaw",test_pytime_monotonic_raw,METH_NOARGS},
90148
{"PyTime_PerfCounter",test_pytime_perf_counter,METH_NOARGS},
149+
{"PyTime_PerfCounterRaw",test_pytime_perf_counter_raw,METH_NOARGS},
91150
{"PyTime_Time",test_pytime_time,METH_NOARGS},
151+
{"PyTime_TimeRaw",test_pytime_time_raw,METH_NOARGS},
92152
{NULL},
93153
};
94154

‎Python/pytime.c

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,10 @@ static int
898898
py_get_system_clock(PyTime_t*tp,_Py_clock_info_t*info,intraise_exc)
899899
{
900900
assert(info==NULL||raise_exc);
901+
if (raise_exc) {
902+
// raise_exc requires to hold the GIL
903+
assert(PyGILState_Check());
904+
}
901905

902906
#ifdefMS_WINDOWS
903907
FILETIMEsystem_time;
@@ -1004,29 +1008,44 @@ py_get_system_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
10041008
}
10051009

10061010

1007-
PyTime_t
1008-
_PyTime_TimeUnchecked(void)
1011+
int
1012+
PyTime_Time(PyTime_t*result)
10091013
{
1010-
PyTime_tt;
1011-
if (py_get_system_clock(&t,NULL,0)<0) {
1012-
// If clock_gettime(CLOCK_REALTIME) or gettimeofday() fails:
1013-
// silently ignore the failure and return 0.
1014-
t=0;
1014+
if (py_get_system_clock(result,NULL,1)<0) {
1015+
*result=0;
1016+
return-1;
10151017
}
1016-
returnt;
1018+
return0;
10171019
}
10181020

10191021

10201022
int
1021-
PyTime_Time(PyTime_t*result)
1023+
PyTime_TimeRaw(PyTime_t*result)
10221024
{
1023-
if (py_get_system_clock(result,NULL,1)<0) {
1025+
if (py_get_system_clock(result,NULL,0)<0) {
10241026
*result=0;
10251027
return-1;
10261028
}
10271029
return0;
10281030
}
10291031

1032+
1033+
PyTime_t
1034+
_PyTime_TimeUnchecked(void)
1035+
{
1036+
PyTime_tt;
1037+
#ifdefPy_DEBUG
1038+
intresult=PyTime_TimeRaw(&t);
1039+
if (result!=0) {
1040+
Py_FatalError("unable to read the system clock");
1041+
}
1042+
#else
1043+
(void)PyTime_TimeRaw(&t);
1044+
#endif
1045+
returnt;
1046+
}
1047+
1048+
10301049
int
10311050
_PyTime_TimeWithInfo(PyTime_t*t,_Py_clock_info_t*info)
10321051
{
@@ -1140,6 +1159,10 @@ static int
11401159
py_get_monotonic_clock(PyTime_t*tp,_Py_clock_info_t*info,intraise_exc)
11411160
{
11421161
assert(info==NULL||raise_exc);
1162+
if (raise_exc) {
1163+
// raise_exc requires to hold the GIL
1164+
assert(PyGILState_Check());
1165+
}
11431166

11441167
#if defined(MS_WINDOWS)
11451168
if (py_get_win_perf_counter(tp,info,raise_exc)<0) {
@@ -1225,29 +1248,44 @@ py_get_monotonic_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
12251248
}
12261249

12271250

1228-
PyTime_t
1229-
_PyTime_MonotonicUnchecked(void)
1251+
int
1252+
PyTime_Monotonic(PyTime_t*result)
12301253
{
1231-
PyTime_tt;
1232-
if (py_get_monotonic_clock(&t,NULL,0)<0) {
1233-
// Ignore silently the error and return 0.
1234-
t=0;
1254+
if (py_get_monotonic_clock(result,NULL,1)<0) {
1255+
*result=0;
1256+
return-1;
12351257
}
1236-
returnt;
1258+
return0;
12371259
}
12381260

12391261

12401262
int
1241-
PyTime_Monotonic(PyTime_t*result)
1263+
PyTime_MonotonicRaw(PyTime_t*result)
12421264
{
1243-
if (py_get_monotonic_clock(result,NULL,1)<0) {
1265+
if (py_get_monotonic_clock(result,NULL,0)<0) {
12441266
*result=0;
12451267
return-1;
12461268
}
12471269
return0;
12481270
}
12491271

12501272

1273+
PyTime_t
1274+
_PyTime_MonotonicUnchecked(void)
1275+
{
1276+
PyTime_tt;
1277+
#ifdefPy_DEBUG
1278+
intresult=PyTime_MonotonicRaw(&t);
1279+
if (result!=0) {
1280+
Py_FatalError("unable to read the monotonic clock");
1281+
}
1282+
#else
1283+
(void)PyTime_MonotonicRaw(&t);
1284+
#endif
1285+
returnt;
1286+
}
1287+
1288+
12511289
int
12521290
_PyTime_MonotonicWithInfo(PyTime_t*tp,_Py_clock_info_t*info)
12531291
{
@@ -1262,17 +1300,24 @@ _PyTime_PerfCounterWithInfo(PyTime_t *t, _Py_clock_info_t *info)
12621300
}
12631301

12641302

1265-
PyTime_t
1266-
_PyTime_PerfCounterUnchecked(void)
1303+
int
1304+
PyTime_PerfCounter(PyTime_t*result)
12671305
{
1268-
return_PyTime_MonotonicUnchecked();
1306+
returnPyTime_Monotonic(result);
12691307
}
12701308

12711309

12721310
int
1273-
PyTime_PerfCounter(PyTime_t*result)
1311+
PyTime_PerfCounterRaw(PyTime_t*result)
12741312
{
1275-
returnPyTime_Monotonic(result);
1313+
returnPyTime_MonotonicRaw(result);
1314+
}
1315+
1316+
1317+
PyTime_t
1318+
_PyTime_PerfCounterUnchecked(void)
1319+
{
1320+
return_PyTime_MonotonicUnchecked();
12761321
}
12771322

12781323

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp