@@ -91,39 +91,44 @@ pyclock(void)
9191/* Win32 has better clock replacement; we have our own version, due to Mark
9292 Hammond and Tim Peters */
9393static PyObject *
94- time_clock ( PyObject * self , PyObject * unused )
94+ win32_clock ( int fallback )
9595{
96- static LARGE_INTEGER ctrStart ;
97- static double divisor = 0.0 ;
96+ static LONGLONG cpu_frequency = 0 ;
97+ static LONGLONG ctrStart ;
9898 LARGE_INTEGER now ;
9999 double diff ;
100100
101- if (divisor == 0. 0 ) {
101+ if (cpu_frequency == 0 ) {
102102 LARGE_INTEGER freq ;
103- QueryPerformanceCounter (& ctrStart );
103+ QueryPerformanceCounter (& now );
104+ ctrStart = now .QuadPart ;
104105 if (!QueryPerformanceFrequency (& freq ) || freq .QuadPart == 0 ) {
105106 /* Unlikely to happen - this works on all intel
106107 machines at least! Revert to clock() */
107- return pyclock ();
108+ if (fallback )
109+ return pyclock ();
110+ else
111+ return PyErr_SetFromWindowsErr (0 );
108112 }
109- divisor = ( double ) freq .QuadPart ;
113+ cpu_frequency = freq .QuadPart ;
110114 }
111115 QueryPerformanceCounter (& now );
112- diff = (double )(now .QuadPart - ctrStart . QuadPart );
113- return PyFloat_FromDouble (diff / divisor );
116+ diff = (double )(now .QuadPart - ctrStart );
117+ return PyFloat_FromDouble (diff / ( double ) cpu_frequency );
114118}
119+ #endif
115120
116- #elif defined(HAVE_CLOCK )
117-
121+ #if (defined(MS_WINDOWS ) && !defined(__BORLANDC__ )) || defined(HAVE_CLOCK )
118122static PyObject *
119123time_clock (PyObject * self , PyObject * unused )
120124{
125+ #if defined(MS_WINDOWS ) && !defined(__BORLANDC__ )
126+ return win32_clock (1 );
127+ #else
121128 return pyclock ();
129+ #endif
122130}
123- #endif /* HAVE_CLOCK */
124-
125131
126- #ifdef HAVE_CLOCK
127132PyDoc_STRVAR (clock_doc ,
128133"clock() -> floating point number\n\
129134\n\
@@ -767,7 +772,7 @@ static PyObject *
767772time_wallclock (PyObject * self , PyObject * unused )
768773{
769774#if defined(MS_WINDOWS ) && !defined(__BORLANDC__ )
770- return time_clock ( self , NULL );
775+ return win32_clock ( 1 );
771776#elif defined(HAVE_CLOCK_GETTIME ) && defined(CLOCK_MONOTONIC )
772777 static int clk_index = 0 ;
773778 clockid_t clk_ids [] = {
@@ -809,6 +814,50 @@ required, i.e. when \"processor time\" is inappropriate. The reference point\n\
809814of the returned value is undefined so only the difference of consecutive\n\
810815calls is valid." );
811816
817+ #if (defined(MS_WINDOWS ) && !defined(__BORLANDC__ )) \
818+ || (defined(HAVE_CLOCK_GETTIME ) && defined(CLOCK_MONOTONIC ))
819+ # define HAVE_PYTIME_MONOTONIC
820+ #endif
821+
822+ #ifdef HAVE_PYTIME_MONOTONIC
823+ static PyObject *
824+ time_monotonic (PyObject * self , PyObject * unused )
825+ {
826+ #if defined(MS_WINDOWS ) && !defined(__BORLANDC__ )
827+ return win32_clock (0 );
828+ #else
829+ static int clk_index = 0 ;
830+ clockid_t clk_ids [] = {
831+ #ifdef CLOCK_MONOTONIC_RAW
832+ CLOCK_MONOTONIC_RAW ,
833+ #endif
834+ CLOCK_MONOTONIC
835+ };
836+ int ret ;
837+ struct timespec tp ;
838+
839+ while (0 <= clk_index ) {
840+ clockid_t clk_id = clk_ids [clk_index ];
841+ ret = clock_gettime (clk_id , & tp );
842+ if (ret == 0 )
843+ return PyFloat_FromDouble (tp .tv_sec + tp .tv_nsec * 1e-9 );
844+
845+ clk_index ++ ;
846+ if (Py_ARRAY_LENGTH (clk_ids ) <= clk_index )
847+ clk_index = -1 ;
848+ }
849+ PyErr_SetFromErrno (PyExc_OSError );
850+ return NULL ;
851+ #endif
852+ }
853+
854+ PyDoc_STRVAR (monotonic_doc ,
855+ "monotonic() -> float\n\
856+ \n\
857+ Monotonic clock. The reference point of the returned value is undefined so\n\
858+ only the difference of consecutive calls is valid." );
859+ #endif
860+
812861static void
813862PyInit_timezone (PyObject * m ) {
814863 /* This code moved from PyInit_time wholesale to allow calling it from
@@ -937,6 +986,9 @@ static PyMethodDef time_methods[] = {
937986#ifdef HAVE_MKTIME
938987 {"mktime" , time_mktime , METH_O , mktime_doc },
939988#endif
989+ #ifdef HAVE_PYTIME_MONOTONIC
990+ {"monotonic" , time_monotonic , METH_NOARGS , monotonic_doc },
991+ #endif
940992#ifdef HAVE_STRFTIME
941993 {"strftime" , time_strftime , METH_VARARGS , strftime_doc },
942994#endif
0 commit comments