[pypy-commit] pypy py3.3: Implement time.clock_gettime(), time.clock_settime(), time.clock_getres() and time.CLOCK_xxx constants.

mjacob noreply at buildbot.pypy.org
Fri Aug 14 01:49:30 CEST 2015


Author: Manuel Jacob <me at manueljacob.de>
Branch: py3.3
Changeset: r78979:0387064aa761
Date: 2015-08-14 01:49 +0200
http://bitbucket.org/pypy/pypy/changeset/0387064aa761/

Log:	Implement time.clock_gettime(), time.clock_settime(),
	time.clock_getres() and time.CLOCK_xxx constants.

diff --git a/pypy/module/time/__init__.py b/pypy/module/time/__init__.py
--- a/pypy/module/time/__init__.py
+++ b/pypy/module/time/__init__.py
@@ -1,5 +1,6 @@
 
 from pypy.interpreter.mixedmodule import MixedModule
+from .interp_time import CLOCK_CONSTANTS, cConfig
 import os
 
 _WIN = os.name == "nt"
@@ -21,8 +22,16 @@
     }
 
     if os.name == "posix":
+        interpleveldefs['clock_gettime'] = 'interp_time.clock_gettime'
+        interpleveldefs['clock_settime'] = 'interp_time.clock_settime'
+        interpleveldefs['clock_getres'] = 'interp_time.clock_getres'
         interpleveldefs['tzset'] = 'interp_time.tzset'
 
+    for constant in CLOCK_CONSTANTS:
+        value = getattr(cConfig, constant)
+        if value is not None:
+            interpleveldefs[constant] = 'space.wrap(interp_time.cConfig.%s)' % constant
+
     appleveldefs = {
         'struct_time': 'app_time.struct_time',
         '__doc__': 'app_time.__doc__',
diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py
--- a/pypy/module/time/interp_time.py
+++ b/pypy/module/time/interp_time.py
@@ -4,8 +4,10 @@
 from pypy.interpreter.gateway import unwrap_spec
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rlib.rarithmetic import intmask
+from rpython.rlib.rtime import c_clock_gettime, TIMESPEC
 from rpython.rlib import rposix
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
+import math
 import os
 import sys
 import time as pytime
@@ -113,6 +115,13 @@
     clock_t = platform.SimpleType("clock_t", rffi.ULONG)
     has_gettimeofday = platform.Has('gettimeofday')
 
+CLOCK_CONSTANTS = ['CLOCK_HIGHRES', 'CLOCK_MONOTONIC', 'CLOCK_MONOTONIC_RAW',
+                   'CLOCK_PROCESS_CPUTIME_ID', 'CLOCK_REALTIME',
+                   'CLOCK_THREAD_CPUTIME_ID']
+
+for constant in CLOCK_CONSTANTS:
+    setattr(CConfig, constant, platform.DefinedConstantInteger(constant))
+
 if _POSIX:
     calling_conv = 'c'
     CConfig.timeval = platform.Struct("struct timeval",
@@ -178,6 +187,12 @@
 c_localtime = external('localtime', [rffi.TIME_TP], TM_P,
                        save_err=rffi.RFFI_SAVE_ERRNO)
 if _POSIX:
+    c_clock_settime = external('clock_settime',
+                               [lltype.Signed, lltype.Ptr(TIMESPEC)], rffi.INT,
+                               save_err=rffi.RFFI_SAVE_ERRNO)
+    c_clock_getres = external('clock_getres',
+                              [lltype.Signed, lltype.Ptr(TIMESPEC)], rffi.INT,
+                              save_err=rffi.RFFI_SAVE_ERRNO)
     c_tzset = external('tzset', [], lltype.Void)
 if _WIN:
     win_eci = ExternalCompilationInfo(
@@ -595,6 +610,39 @@
     return space.wrap(float(tt))
 
 if _POSIX:
+    @unwrap_spec(clk_id='c_int')
+    def clock_gettime(space, clk_id):
+        with lltype.scoped_alloc(TIMESPEC) as timespec:
+            ret = c_clock_gettime(clk_id, timespec)
+            if ret != 0:
+                raise OperationError(space.w_OSError,
+                                     space.wrap(_get_error_msg()))
+            result = (float(rffi.getintfield(timespec, 'c_tv_sec')) +
+                      float(rffi.getintfield(timespec, 'c_tv_nsec')) * 1e-9)
+        return space.wrap(result)
+
+    @unwrap_spec(clk_id='c_int', secs=float)
+    def clock_settime(space, clk_id, secs):
+        with lltype.scoped_alloc(TIMESPEC) as timespec:
+            frac = math.fmod(secs, 1.0)
+            rffi.setintfield(timespec, 'c_tv_sec', int(secs))
+            rffi.setintfield(timespec, 'c_tv_nsec', int(frac * 1e9))
+            ret = c_clock_settime(clk_id, timespec)
+            if ret != 0:
+                raise OperationError(space.w_OSError,
+                                     space.wrap(_get_error_msg()))
+
+    @unwrap_spec(clk_id='c_int')
+    def clock_getres(space, clk_id):
+        with lltype.scoped_alloc(TIMESPEC) as timespec:
+            ret = c_clock_getres(clk_id, timespec)
+            if ret != 0:
+                raise OperationError(space.w_OSError,
+                                     space.wrap(_get_error_msg()))
+            result = (float(rffi.getintfield(timespec, 'c_tv_sec')) +
+                      float(rffi.getintfield(timespec, 'c_tv_nsec')) * 1e-9)
+        return space.wrap(result)
+
     def tzset(space):
         """tzset()
 
diff --git a/pypy/module/time/test/test_time.py b/pypy/module/time/test/test_time.py
--- a/pypy/module/time/test/test_time.py
+++ b/pypy/module/time/test/test_time.py
@@ -34,6 +34,28 @@
         t2 = time.time()
         assert t1 != t2       # the resolution should be at least 0.01 secs
 
+    def test_clock_realtime(self):
+        import os
+        if os.name != "posix":
+            skip("clock_gettime available only under Unix")
+        import time
+        t1 = time.clock_gettime(time.CLOCK_REALTIME)
+        assert isinstance(t1, float)
+        time.sleep(time.clock_getres(time.CLOCK_REALTIME))
+        t2 = time.clock_gettime(time.CLOCK_REALTIME)
+        assert t1 != t2
+
+    def test_clock_monotonic(self):
+        import os
+        if os.name != "posix":
+            skip("clock_gettime available only under Unix")
+        import time
+        t1 = time.clock_gettime(time.CLOCK_MONOTONIC)
+        assert isinstance(t1, float)
+        time.sleep(time.clock_getres(time.CLOCK_MONOTONIC))
+        t2 = time.clock_gettime(time.CLOCK_MONOTONIC)
+        assert t1 < t2
+
     def test_ctime(self):
         import time
         raises(TypeError, time.ctime, "foo")


More information about the pypy-commit mailing list