Author: Amaury Forgeot d'Arc <amaur...@gmail.com> Branch: more-rposix Changeset: r77011:4aa53f36a6e2 Date: 2015-05-02 00:03 +0200 http://bitbucket.org/pypy/pypy/changeset/4aa53f36a6e2/
Log: Move module/ll_time.py to rlib/rtime.py 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,6 +4,7 @@ from pypy.interpreter.gateway import unwrap_spec from rpython.rtyper.lltypesystem import lltype from rpython.rlib.rarithmetic import intmask +from rpython.rlib import rtime # Register functions from rpython.rlib import rposix from rpython.translator.tool.cbuild import ExternalCompilationInfo import os @@ -482,13 +483,6 @@ secs = pytime.time() return space.wrap(secs) -if _WIN: - class PCCache: - pass - pccache = PCCache() - pccache.divisor = 0.0 - pccache.ctrStart = 0 - def clock(space): """clock() -> floating point number diff --git a/rpython/rlib/rtime.py b/rpython/rlib/rtime.py new file mode 100644 --- /dev/null +++ b/rpython/rlib/rtime.py @@ -0,0 +1,233 @@ +""" +RPython implementations of time.time(), time.clock(), time.select(). +""" + +import sys +import math +import time as pytime +from rpython.translator.tool.cbuild import ExternalCompilationInfo +from rpython.rtyper.tool import rffi_platform +from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib.objectmodel import register_replacement_for +from rpython.rlib import rposix + +_WIN32 = sys.platform.startswith('win') + +if _WIN32: + TIME_H = 'time.h' + FTIME = '_ftime64' + STRUCT_TIMEB = 'struct __timeb64' + includes = ['winsock2.h', 'windows.h', + TIME_H, 'sys/types.h', 'sys/timeb.h'] + need_rusage = False +else: + TIME_H = 'sys/time.h' + FTIME = 'ftime' + STRUCT_TIMEB = 'struct timeb' + includes = [TIME_H, 'time.h', 'errno.h', 'sys/select.h', + 'sys/types.h', 'unistd.h', + 'sys/time.h', 'sys/resource.h'] + + if not sys.platform.startswith("openbsd"): + includes.append('sys/timeb.h') + + need_rusage = True + + +eci = ExternalCompilationInfo(includes=includes) + +class CConfig: + _compilation_info_ = eci + TIMEVAL = rffi_platform.Struct('struct timeval', [('tv_sec', rffi.INT), + ('tv_usec', rffi.INT)]) + HAVE_GETTIMEOFDAY = rffi_platform.Has('gettimeofday') + HAVE_FTIME = rffi_platform.Has(FTIME) + if need_rusage: + RUSAGE = rffi_platform.Struct('struct rusage', [('ru_utime', TIMEVAL), + ('ru_stime', TIMEVAL)]) + +if sys.platform.startswith('freebsd') or sys.platform.startswith('netbsd'): + libraries = ['compat'] +elif sys.platform == 'linux2': + libraries = ['rt'] +else: + libraries = [] + +class CConfigForFTime: + _compilation_info_ = ExternalCompilationInfo( + includes=[TIME_H, 'sys/timeb.h'], + libraries=libraries + ) + TIMEB = rffi_platform.Struct(STRUCT_TIMEB, [('time', rffi.INT), + ('millitm', rffi.INT)]) + +class CConfigForClockGetTime: + _compilation_info_ = ExternalCompilationInfo( + includes=['time.h'], + libraries=libraries + ) + TIMESPEC = rffi_platform.Struct('struct timespec', [('tv_sec', rffi.LONG), + ('tv_nsec', rffi.LONG)]) + +constant_names = ['RUSAGE_SELF', 'EINTR', 'CLOCK_PROCESS_CPUTIME_ID'] +for const in constant_names: + setattr(CConfig, const, rffi_platform.DefinedConstantInteger(const)) +defs_names = ['GETTIMEOFDAY_NO_TZ'] +for const in defs_names: + setattr(CConfig, const, rffi_platform.Defined(const)) + +def decode_timeval(t): + return (float(rffi.getintfield(t, 'c_tv_sec')) + + float(rffi.getintfield(t, 'c_tv_usec')) * 0.000001) + + +def external(name, args, result, compilation_info=eci, **kwds): + return rffi.llexternal(name, args, result, + compilation_info=compilation_info, **kwds) + +def replace_time_function(name): + func = getattr(pytime, name, None) + if func is None: + return lambda f: f + return register_replacement_for( + func, + sandboxed_name='ll_time.ll_time_%s' % name) + +config = rffi_platform.configure(CConfig) +globals().update(config) + +# Note: time.time() is used by the framework GC during collect(), +# which means that we have to be very careful about not allocating +# GC memory here. This is the reason for the _nowrapper=True. +if HAVE_GETTIMEOFDAY: + if GETTIMEOFDAY_NO_TZ: + c_gettimeofday = external('gettimeofday', + [lltype.Ptr(TIMEVAL)], rffi.INT, + _nowrapper=True, releasegil=False) + else: + c_gettimeofday = external('gettimeofday', + [lltype.Ptr(TIMEVAL), rffi.VOIDP], rffi.INT, + _nowrapper=True, releasegil=False) +if HAVE_FTIME: + globals().update(rffi_platform.configure(CConfigForFTime)) + c_ftime = external(FTIME, [lltype.Ptr(TIMEB)], + lltype.Void, + _nowrapper=True, releasegil=False) +c_time = external('time', [rffi.VOIDP], rffi.TIME_T, + _nowrapper=True, releasegil=False) + + +@replace_time_function('time') +def time(): + void = lltype.nullptr(rffi.VOIDP.TO) + result = -1.0 + if HAVE_GETTIMEOFDAY: + with lltype.scoped_alloc(TIMEVAL) as t: + errcode = -1 + if GETTIMEOFDAY_NO_TZ: + errcode = c_gettimeofday(t) + else: + errcode = c_gettimeofday(t, void) + + if rffi.cast(rffi.LONG, errcode) == 0: + result = decode_timeval(t) + if result != -1: + return result + else: # assume using ftime(3) + t = lltype.malloc(TIMEB, flavor='raw') + c_ftime(t) + result = (float(intmask(t.c_time)) + + float(intmask(t.c_millitm)) * 0.001) + lltype.free(t, flavor='raw') + return result + return float(c_time(void)) + + +# _______________________________________________________________ +# time.clock() + +if _WIN32: + # hacking to avoid LARGE_INTEGER which is a union... + A = lltype.FixedSizeArray(lltype.SignedLongLong, 1) + QueryPerformanceCounter = external( + 'QueryPerformanceCounter', [lltype.Ptr(A)], lltype.Void, + releasegil=False) + QueryPerformanceFrequency = self.llexternal( + 'QueryPerformanceFrequency', [lltype.Ptr(A)], rffi.INT, + releasegil=False) + class State(object): + divisor = 0.0 + counter_start = 0 + state = State() +elif CLOCK_PROCESS_CPUTIME_ID is not None: + # Linux and other POSIX systems with clock_gettime() + globals().update(rffi_platform.configure(CConfigForClockGetTime)) + TIMESPEC = TIMESPEC + CLOCK_PROCESS_CPUTIME_ID = CLOCK_PROCESS_CPUTIME_ID + c_clock_gettime = external('clock_gettime', + [lltype.Signed, lltype.Ptr(TIMESPEC)], + rffi.INT, releasegil=False) +else: + RUSAGE = self.RUSAGE + RUSAGE_SELF = self.RUSAGE_SELF or 0 + c_getrusage = self.llexternal('getrusage', + [rffi.INT, lltype.Ptr(RUSAGE)], + lltype.Void, + releasegil=False) + +@replace_time_function('clock') +def clock(): + if _WIN32: + a = lltype.malloc(A, flavor='raw') + if state.divisor == 0.0: + QueryPerformanceCounter(a) + state.counter_start = a[0] + QueryPerformanceFrequency(a) + state.divisor = float(a[0]) + QueryPerformanceCounter(a) + diff = a[0] - state.counter_start + lltype.free(a, flavor='raw') + return float(diff) / state.divisor + elif CLOCK_PROCESS_CPUTIME_ID is not None: + with lltype.scoped_alloc(TIMESPEC) as a: + c_clock_gettime(CLOCK_PROCESS_CPUTIME_ID, a) + result = (float(rffi.getintfield(a, 'c_tv_sec')) + + float(rffi.getintfield(a, 'c_tv_nsec')) * 0.000000001) + return result + else: + with lltype.scoped_alloc(RUSAGE) as a: + c_getrusage(RUSAGE_SELF, a) + result = (decode_timeval(a.c_ru_utime) + + decode_timeval(a.c_ru_stime)) + return result + +# _______________________________________________________________ +# time.sleep() + +if _WIN32: + Sleep = external('Sleep', [rffi.ULONG], lltype.Void) +else: + c_select = external('select', [rffi.INT, rffi.VOIDP, + rffi.VOIDP, rffi.VOIDP, + lltype.Ptr(TIMEVAL)], rffi.INT, + save_err=rffi.RFFI_SAVE_ERRNO) + +@replace_time_function('sleep') +def sleep(secs): + if _WIN32: + millisecs = secs * 1000.0 + while millisecs > UINT_MAX: + Sleep(UINT_MAX) + millisecs -= UINT_MAX + Sleep(rffi.cast(rffi.ULONG, int(millisecs))) + else: + void = lltype.nullptr(rffi.VOIDP.TO) + with lltype.scoped_alloc(TIMEVAL) as t: + frac = math.fmod(secs, 1.0) + rffi.setintfield(t, 'c_tv_sec', int(secs)) + rffi.setintfield(t, 'c_tv_usec', int(frac*1000000.0)) + + if rffi.cast(rffi.LONG, c_select(0, void, void, void, t)) != 0: + errno = rposix.get_saved_errno() + if errno != EINTR: + raise OSError(errno, "Select failed") diff --git a/rpython/rtyper/module/test/test_ll_time.py b/rpython/rlib/test/test_rtime.py rename from rpython/rtyper/module/test/test_ll_time.py rename to rpython/rlib/test/test_rtime.py --- a/rpython/rtyper/module/test/test_ll_time.py +++ b/rpython/rlib/test/test_rtime.py @@ -1,6 +1,6 @@ from rpython.rtyper.test.tool import BaseRtypingTest -#from rpython.translator.c.test.test_genc import compile +from rpython.rlib import rtime # Register functions import time, sys diff --git a/rpython/rtyper/extfuncregistry.py b/rpython/rtyper/extfuncregistry.py --- a/rpython/rtyper/extfuncregistry.py +++ b/rpython/rtyper/extfuncregistry.py @@ -7,7 +7,6 @@ import math from rpython.rtyper.lltypesystem.module import ll_math -from rpython.rtyper.module import ll_time from rpython.rlib import rfloat # the following functions all take one float, return one float diff --git a/rpython/rtyper/module/ll_time.py b/rpython/rtyper/module/ll_time.py deleted file mode 100644 --- a/rpython/rtyper/module/ll_time.py +++ /dev/null @@ -1,239 +0,0 @@ -""" -Low-level implementations for the external functions of the 'time' module. -""" - -import time, sys, math -from errno import EINTR -from rpython.rtyper.lltypesystem import rffi -from rpython.rtyper.tool import rffi_platform as platform -from rpython.rtyper.lltypesystem import lltype -from rpython.rtyper.extfunc import BaseLazyRegistering, registering, extdef -from rpython.rlib import rposix -from rpython.rlib.rarithmetic import intmask, UINT_MAX -from rpython.translator.tool.cbuild import ExternalCompilationInfo - -if sys.platform == 'win32': - TIME_H = 'time.h' - FTIME = '_ftime64' - STRUCT_TIMEB = 'struct __timeb64' - includes = ['winsock2.h', 'windows.h', - TIME_H, 'sys/types.h', 'sys/timeb.h'] - need_rusage = False -else: - TIME_H = 'sys/time.h' - FTIME = 'ftime' - STRUCT_TIMEB = 'struct timeb' - includes = [TIME_H, 'time.h', 'errno.h', 'sys/select.h', - 'sys/types.h', 'unistd.h', - 'sys/time.h', 'sys/resource.h'] - - if not sys.platform.startswith("openbsd"): - includes.append('sys/timeb.h') - - need_rusage = True - - -class CConfig: - _compilation_info_ = ExternalCompilationInfo( - includes=includes - ) - TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.INT), - ('tv_usec', rffi.INT)]) - HAVE_GETTIMEOFDAY = platform.Has('gettimeofday') - HAVE_FTIME = platform.Has(FTIME) - if need_rusage: - RUSAGE = platform.Struct('struct rusage', [('ru_utime', TIMEVAL), - ('ru_stime', TIMEVAL)]) - -if sys.platform.startswith('freebsd') or sys.platform.startswith('netbsd'): - libraries = ['compat'] -elif sys.platform == 'linux2': - libraries = ['rt'] -else: - libraries = [] - -class CConfigForFTime: - _compilation_info_ = ExternalCompilationInfo( - includes=[TIME_H, 'sys/timeb.h'], - libraries=libraries - ) - TIMEB = platform.Struct(STRUCT_TIMEB, [('time', rffi.INT), - ('millitm', rffi.INT)]) - -class CConfigForClockGetTime: - _compilation_info_ = ExternalCompilationInfo( - includes=['time.h'], - libraries=libraries - ) - TIMESPEC = platform.Struct('struct timespec', [('tv_sec', rffi.LONG), - ('tv_nsec', rffi.LONG)]) - -constant_names = ['RUSAGE_SELF', 'EINTR', 'CLOCK_PROCESS_CPUTIME_ID'] -for const in constant_names: - setattr(CConfig, const, platform.DefinedConstantInteger(const)) -defs_names = ['GETTIMEOFDAY_NO_TZ'] -for const in defs_names: - setattr(CConfig, const, platform.Defined(const)) - -def decode_timeval(t): - return (float(rffi.getintfield(t, 'c_tv_sec')) + - float(rffi.getintfield(t, 'c_tv_usec')) * 0.000001) - -class RegisterTime(BaseLazyRegistering): - def __init__(self): - self.configure(CConfig) - self.TIMEVALP = lltype.Ptr(self.TIMEVAL) - - @registering(time.time) - def register_time_time(self): - # Note: time.time() is used by the framework GC during collect(), - # which means that we have to be very careful about not allocating - # GC memory here. This is the reason for the _nowrapper=True. - - # AWFUL - if self.HAVE_GETTIMEOFDAY: - if self.GETTIMEOFDAY_NO_TZ: - c_gettimeofday = self.llexternal('gettimeofday', - [self.TIMEVALP], rffi.INT, - _nowrapper=True, releasegil=False) - else: - c_gettimeofday = self.llexternal('gettimeofday', - [self.TIMEVALP, rffi.VOIDP], rffi.INT, - _nowrapper=True, releasegil=False) - c_ftime = None # We have gettimeofday(2), so force ftime(3) OFF. - else: - c_gettimeofday = None - - # Only look for ftime(3) if gettimeofday(2) was not found. - if self.HAVE_FTIME: - self.configure(CConfigForFTime) - c_ftime = self.llexternal(FTIME, [lltype.Ptr(self.TIMEB)], - lltype.Void, - _nowrapper=True, releasegil=False) - else: - c_ftime = None # to not confuse the flow space - - c_time = self.llexternal('time', [rffi.VOIDP], rffi.TIME_T, - _nowrapper=True, releasegil=False) - - def time_time_llimpl(): - void = lltype.nullptr(rffi.VOIDP.TO) - result = -1.0 - if self.HAVE_GETTIMEOFDAY: - t = lltype.malloc(self.TIMEVAL, flavor='raw') - - errcode = -1 - if self.GETTIMEOFDAY_NO_TZ: - errcode = c_gettimeofday(t) - else: - errcode = c_gettimeofday(t, void) - - if rffi.cast(rffi.LONG, errcode) == 0: - result = decode_timeval(t) - lltype.free(t, flavor='raw') - if result != -1: - return result - else: # assume using ftime(3) - t = lltype.malloc(self.TIMEB, flavor='raw') - c_ftime(t) - result = (float(intmask(t.c_time)) + - float(intmask(t.c_millitm)) * 0.001) - lltype.free(t, flavor='raw') - return result - return float(c_time(void)) - - return extdef([], float, llimpl=time_time_llimpl, - export_name='ll_time.ll_time_time') - - @registering(time.clock) - def register_time_clock(self): - if sys.platform == 'win32': - # hacking to avoid LARGE_INTEGER which is a union... - A = lltype.FixedSizeArray(lltype.SignedLongLong, 1) - QueryPerformanceCounter = self.llexternal( - 'QueryPerformanceCounter', [lltype.Ptr(A)], lltype.Void, - releasegil=False) - QueryPerformanceFrequency = self.llexternal( - 'QueryPerformanceFrequency', [lltype.Ptr(A)], rffi.INT, - releasegil=False) - class State(object): - pass - state = State() - state.divisor = 0.0 - state.counter_start = 0 - def time_clock_llimpl(): - a = lltype.malloc(A, flavor='raw') - if state.divisor == 0.0: - QueryPerformanceCounter(a) - state.counter_start = a[0] - QueryPerformanceFrequency(a) - state.divisor = float(a[0]) - QueryPerformanceCounter(a) - diff = a[0] - state.counter_start - lltype.free(a, flavor='raw') - return float(diff) / state.divisor - elif self.CLOCK_PROCESS_CPUTIME_ID is not None: - # Linux and other POSIX systems with clock_gettime() - self.configure(CConfigForClockGetTime) - TIMESPEC = self.TIMESPEC - CLOCK_PROCESS_CPUTIME_ID = self.CLOCK_PROCESS_CPUTIME_ID - c_clock_gettime = self.llexternal('clock_gettime', - [lltype.Signed, lltype.Ptr(TIMESPEC)], - rffi.INT, releasegil=False) - def time_clock_llimpl(): - a = lltype.malloc(TIMESPEC, flavor='raw') - c_clock_gettime(CLOCK_PROCESS_CPUTIME_ID, a) - result = (float(rffi.getintfield(a, 'c_tv_sec')) + - float(rffi.getintfield(a, 'c_tv_nsec')) * 0.000000001) - lltype.free(a, flavor='raw') - return result - else: - RUSAGE = self.RUSAGE - RUSAGE_SELF = self.RUSAGE_SELF or 0 - c_getrusage = self.llexternal('getrusage', - [rffi.INT, lltype.Ptr(RUSAGE)], - lltype.Void, - releasegil=False) - def time_clock_llimpl(): - a = lltype.malloc(RUSAGE, flavor='raw') - c_getrusage(RUSAGE_SELF, a) - result = (decode_timeval(a.c_ru_utime) + - decode_timeval(a.c_ru_stime)) - lltype.free(a, flavor='raw') - return result - - return extdef([], float, llimpl=time_clock_llimpl, - export_name='ll_time.ll_time_clock') - - @registering(time.sleep) - def register_time_sleep(self): - if sys.platform == 'win32': - Sleep = self.llexternal('Sleep', [rffi.ULONG], lltype.Void) - def time_sleep_llimpl(secs): - millisecs = secs * 1000.0 - while millisecs > UINT_MAX: - Sleep(UINT_MAX) - millisecs -= UINT_MAX - Sleep(rffi.cast(rffi.ULONG, int(millisecs))) - else: - c_select = self.llexternal('select', [rffi.INT, rffi.VOIDP, - rffi.VOIDP, rffi.VOIDP, - self.TIMEVALP], rffi.INT, - save_err=rffi.RFFI_SAVE_ERRNO) - def time_sleep_llimpl(secs): - void = lltype.nullptr(rffi.VOIDP.TO) - t = lltype.malloc(self.TIMEVAL, flavor='raw') - try: - frac = math.fmod(secs, 1.0) - rffi.setintfield(t, 'c_tv_sec', int(secs)) - rffi.setintfield(t, 'c_tv_usec', int(frac*1000000.0)) - - if rffi.cast(rffi.LONG, c_select(0, void, void, void, t)) != 0: - errno = rposix.get_saved_errno() - if errno != EINTR: - raise OSError(errno, "Select failed") - finally: - lltype.free(t, flavor='raw') - - return extdef([float], None, llimpl=time_sleep_llimpl, - export_name='ll_time.ll_time_sleep') _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit