Commit 573d550b authored by Mark Peek's avatar Mark Peek

First attempt at removing aplib dependencies

parent e18e8a59
# Build directory
build/
# Generated and compiled files
coro/_coro.[ch]
coro/oserrors.[ch]
coro/clocks/tsc_time.c
*.pyc
*.so
...@@ -2,12 +2,8 @@ Coro runs on FreeBSD, Linux and MacOS X on i386 and amd64 architectures. ...@@ -2,12 +2,8 @@ Coro runs on FreeBSD, Linux and MacOS X on i386 and amd64 architectures.
In order to build, it requires: In order to build, it requires:
- cython (/usr/ports/lang/cython on FreeBSD or your package manager of choice on linux). - cython (/usr/ports/lang/cython on FreeBSD or your package manager of choice on linux).
- aplib from the IronPort github area at the same base directory as shrapnel
Since aplib is both a build and runtime requirement, make sure that is To build and install shrapnel:
installed first.
Then build and install shrapnel:
$ python setup.py build $ python setup.py build
# python setup.py install # python setup.py install
...@@ -90,13 +90,13 @@ is allowed to do this. The default is 4. The default may be changed ...@@ -90,13 +90,13 @@ is allowed to do this. The default is 4. The default may be changed
Time Time
==== ====
Shrapnel uses the `aplib.tsc_time` module for handling time. It uses the TSC Shrapnel uses the `tsc_time` module for handling time. It uses the TSC
value for a stable and high-resolution unit of time. See that module's value for a stable and high-resolution unit of time. See that module's
documentation for more detail. documentation for more detail.
A thread is always created when you start the event loop that will A thread is always created when you start the event loop that will
resynchronize the TSC relationship to accomodate any clock drift (see resynchronize the TSC relationship to accomodate any clock drift (see
`tick_updater` and `aplib.tsc_time.update_time_relation`). `tick_updater` and `tsc_time.update_time_relation`).
Exception Notifier Exception Notifier
================== ==================
...@@ -132,7 +132,7 @@ from coro._coro import * ...@@ -132,7 +132,7 @@ from coro._coro import *
from coro._coro import _yield from coro._coro import _yield
from coro import signal_handler from coro import signal_handler
from coro import optional from coro import optional
from aplib import tb from coro import tb
import signal import signal
import sys import sys
...@@ -248,7 +248,7 @@ def tick_updater(): ...@@ -248,7 +248,7 @@ def tick_updater():
global tick_update_interval global tick_update_interval
while 1: while 1:
sleep_relative(tick_update_interval) sleep_relative(tick_update_interval)
aplib.tsc_time.update_time_relation() tsc_time.update_time_relation()
# ============================================================================ # ============================================================================
# waitpid # waitpid
...@@ -382,32 +382,32 @@ def new (fun, *args, **kwargs): ...@@ -382,32 +382,32 @@ def new (fun, *args, **kwargs):
# ============================================================================ # ============================================================================
# time backwards compatibility # time backwards compatibility
# ============================================================================ # ============================================================================
import aplib.tsc_time import coro.clocks.tsc_time as tsc_time
ticks_per_sec = aplib.tsc_time.ticks_per_sec ticks_per_sec = tsc_time.ticks_per_sec
ticks_per_usec = aplib.tsc_time.ticks_per_usec ticks_per_usec = tsc_time.ticks_per_usec
microseconds = 1000000 microseconds = 1000000
absolute_time_to_ticks = aplib.tsc_time.usec_to_ticks absolute_time_to_ticks = tsc_time.usec_to_ticks
ticks_to_absolute_time = aplib.tsc_time.ticks_to_usec ticks_to_absolute_time = tsc_time.ticks_to_usec
absolute_time_to_ticks_safe = aplib.tsc_time.usec_to_ticks_safe absolute_time_to_ticks_safe = tsc_time.usec_to_ticks_safe
ticks_to_absolute_time_safe = aplib.tsc_time.ticks_to_usec_safe ticks_to_absolute_time_safe = tsc_time.ticks_to_usec_safe
absolute_secs_to_ticks = aplib.tsc_time.sec_to_ticks absolute_secs_to_ticks = tsc_time.sec_to_ticks
ticks_to_absolute_secs = aplib.tsc_time.ticks_to_sec ticks_to_absolute_secs = tsc_time.ticks_to_sec
get_now = aplib.tsc_time.rdtsc get_now = tsc_time.rdtsc
update_time_relation = aplib.tsc_time.update_time_relation update_time_relation = tsc_time.update_time_relation
def get_usec(): def get_usec():
"""This is for backwards compatibility and should not be used.""" """This is for backwards compatibility and should not be used."""
return aplib.tsc_time.ticks_to_usec(get_now()) return tsc_time.ticks_to_usec(get_now())
def ctime_ticks(t): def ctime_ticks(t):
"""This is for backwards compatibility and should not be used.""" """This is for backwards compatibility and should not be used."""
return aplib.tsc_time.TSC_from_ticks(t).ctime() return tsc_time.TSC_from_ticks(t).ctime()
def ctime_usec(u): def ctime_usec(u):
"""This is for backwards compatibility and should not be used.""" """This is for backwards compatibility and should not be used."""
return aplib.tsc_time.TSC_from_posix_usec(u).ctime() return tsc_time.TSC_from_posix_usec(u).ctime()
now = get_now() now = get_now()
now_usec = get_usec() now_usec = get_usec()
...@@ -474,7 +474,7 @@ def event_loop (timeout=30): ...@@ -474,7 +474,7 @@ def event_loop (timeout=30):
""" """
global event_loop_is_running, with_timeout, sleep_relative global event_loop_is_running, with_timeout, sleep_relative
# replace time.time with our tsc-based version # replace time.time with our tsc-based version
time.time, time.original_time = aplib.tsc_time.now_raw_posix_fsec, time.time time.time, time.original_time = tsc_time.now_raw_posix_fsec, time.time
with_timeout = _original_with_timeout with_timeout = _original_with_timeout
sleep_relative = _original_sleep_relative sleep_relative = _original_sleep_relative
if install_signal_handlers: if install_signal_handlers:
......
...@@ -66,9 +66,8 @@ include "python.pxi" ...@@ -66,9 +66,8 @@ include "python.pxi"
# Note that this cimports libc. # Note that this cimports libc.
include "pyrex_helpers.pyx" include "pyrex_helpers.pyx"
include "tsc_time_include.pyx" include "tsc_time_include.pyx"
# Ugh, Pyrex doesn't do "import aplib.tsc_time as tsc_time_module" the same as
# Python does. It sets tsc_time_module to `aplib`. from coro.clocks import tsc_time as tsc_time_module
from aplib import tsc_time as tsc_time_module
cdef extern from "stdlib.h": cdef extern from "stdlib.h":
IF UNAME_SYSNAME == "Linux": IF UNAME_SYSNAME == "Linux":
...@@ -778,7 +777,7 @@ def set_exception_notifier (new_func): ...@@ -778,7 +777,7 @@ def set_exception_notifier (new_func):
# every time through __resume/__yield(). # every time through __resume/__yield().
cdef extern void _wrap0 (void *) cdef extern void _wrap0 (void *)
from aplib import tb from coro import tb
cdef public void _wrap1 "_wrap1" (coro co): cdef public void _wrap1 "_wrap1" (coro co):
try: try:
......
# Copyright (c) 2002-2011 IronPort Systems and Cisco Systems
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Pyrex definition file for tsc_time module objects.
# Work around Pyrex's poor recursive import/include support.
cimport libc as _libc
cdef class Time:
cdef readonly _libc.int64_t tsc
cdef c_ctime(self)
cdef c_localtime(self)
cdef c_gmtime(self)
cdef c_mkstr_local(self, char * format)
cdef c_mkstr_utc(self, char * format)
cdef class TSC(Time):
pass
cdef class Posix(Time):
pass
cdef class uPosix(Time):
pass
cdef class fPosix(Time):
pass
# Copyright (c) 2002-2011 IronPort Systems and Cisco Systems
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# $Header: /cvsroot/godspeed/python_modules/tsc_time.pyx,v 1.4 2007/03/20 00:51:42 ehuss Exp $
"""TSC time library.
Introduction
============
This module implements a "Time" object that is based on the TSC value of the
x86 processor. This is a monotonically increasing value that is somewhat
dependable (whereas system time may change). It is also very high resolution
and very efficient to retrieve.
This library is designed to be as high-performance as possible. If you use it
correctly, you can ensure your code maintains that high level of performance.
Objects
=======
There are 4 objects in this module all deriving from the base Time object.
They are:
- ``TSC``: TSC value
- ``Posix``: POSIX, seconds since 1970
- ``uPosix``: POSIX, microseconds since 1970
- ``fPosix``: POSIX, floating-point seconds since 1970
Each of these objects are relatively the same. The main difference is when
adding or comparing the objects, they behave as their type describes.
The base Time object defines methods for converting the TSC value to another
type. They are ``as_posix_sec``, ``as_posix_usec``, and ``as_posix_fsec``.
There are a three classes of functions in the module for creating these
objects. The ``now_*`` functions compute the current time. The ``mktime_*``
functions convert a Python "time tuple" to a Time object. The ``*_from_*``
functions take a raw value (TSC, Posix, etc.) and create a Time object.
Raw Conversions
===============
The module also provides methods for converting raw values from one type to
another. These are the ``*_to_*`` functions, and generally should not be needed
if your code uses Time objects throughout.
Wall Clock Synchronization
==========================
When the module is first imported, it captures the current wall-clock time and
TSC value. This information is used for doing conversions between TSC and
Posix time. It is important to call the ``update_time_relation`` function
whenever the wall-clock is changed. Also, it is a good idea to call it
periodically to retain accuracy. This is necessary because the library uses
the ``ticks_per_sec`` value for conversions. This value is obtained from the
``machdep.tsc_freq`` sysctl, and may be slightly off (my system is about 0.002%
off which is about 10 minutes per year). Long-term computations based on the
``ticks_per_sec`` value should not be trusted to be very accurate.
Accuracy and Precision
======================
The conversion functions use roughly imprecise, but faster integer arithmetic.
The reason it is inaccurate is because it uses the ticks_per_usec value which
is less accurate than ticks_per_sec. To compute the inaccuracy, you can use
the formula::
(1000000 / ticks_per_sec)
This is a rough estimate. On my 3.5 GHz system, this is about 0.027% or about
2.3 hours per year. Slower systems have less accuracy (about 0.09% for a 1 GHz
machine or about 8 hours per year).
To be more accurate, we would either need to use numbers larger than 64 bits
(bignums, Python Longs, 80-bit C doubles, etc.), but it would slow the
conversions down a little (for C doubles it was about 30% slower on my system).
TSC values that are significantly far from the current time should not be
trusted to be very accurate.
External C Access
=================
The C functions in this module are available for direct access from other C
extension modules. For C modules, simply include "tsc_time.h" and call the
initialization function once. For Pyrex modules, include
"tsc_time_include.pyx". See the respective files for more detail.
Signedness
==========
TSC values may be negative (to indicate a time before the computer booted). In
general, this library uses signed data types to avoid signed/unsigned
multiplication/division. A particular exception is the `ticks_per_sec` value
because it is currently defined as a 32-bit number, and we need to support
machines with CPU's faster than 2GHz.
On most POSIX systems, time_t is a signed 32-bit integer (on some it is a
signed 64-bit integer, whose negative value extends past the beginning of the
universe). In theory, a signed 32-bit value can handle negative values from
1901 to 1970 and 1970 to 2038 positive. Some foolish systems have attempted to
define time_t as an unsigned value to extend the overflow point to 2106, but
this is rare.
Notes
=====
The rate of the TSC value may change on systems with thermal and power
throttling. (though rumor has it some processors adjust the TSC rate when
auto-throttling to ensure it runs at a constant speed). This invalidates
assumptions made in this library, so do not use those features.
On SMP kernels, FreeBSD will synchronize the TSC value on all CPU's at
boot time, and the assumption is made that they will remain roughly in sync.
Rumor has it that some motherboards will attempt to keep the TSC value in
sync on all processors over time. AMD CPU's are rumored to be especially
vulnerable to this.
RDTSC
=====
This is detailed low-level information about the rdtsc instruction that is used
to obtain the TSC value.
rdtsc - ReaD TimeStamp Counter
The cycle counter in the Pentium series of processors is incremented once for
every clock cycle. It starts out as 0 on system boot. It is a 64-bit number,
and thus will wrap over in 292 years on a 2 gigahertz processor. It should
keep counting unless the system goes into deep sleep mode.
FYI, the control registers on the Pentium can be configured to restrict RDTSC
to privileged level 0.
The RDTSC instruction is generally not synchronized. Thus, with out of order
execution, it is possible for it to run ahead of other instructions that came
before it. This is mainly only important if you are trying to do exact
profiling of instruction cycles.
Other Counters
==============
Most x86 systems have other hardware timers. They all have different
frequencies, accuracies, performance characteristics, etc. The following is a
list of alternate counters that we may want to investigate:
- Intel 8254 Interval Timer (i8254). This was introduced in the IBM AT (the
8253 was used in the IBM XT).
- ACPI (Advanced Configuration and Power Interface) counter (ACPI was
introduced around 1996).
- HPET (High Precision Event Timer) introduced by Intel around 2004 as a
replacement to the i8254.
Further Reading
===============
Some interesting papers:
- Timecounters: Efficient and precise timekeeping in SMP kernels:
http://phk.freebsd.dk/pubs/timecounter.pdf
- TSC and Power Management Events on AMD Processors:
http://www.opensolaris.org/os/community/performance/technical_docs/amd_tsc_power
TODO
====
- Investigate SMP drift over long periods of time.
- Find a way to detect if the current platform has thermal or power
throttling, and whether or not it compensates the TSC rate to remain constant.
- machdep.tsc_freq is a 32-bit unsigned integer. For systems with CPU's faster
that 4 GHz, this is no longer sufficient.
- Get a better (more accurate) value of machdep.tsc_freq. Investigate
CLK_USE_TSC_CALIBRATION, CLK_USE_I8254_CALIBRATION, CLK_CALIBRATION_LOOP in
FreeBSD kernel which use the mc146818A chip. (CLK_USE_TSC_CALIBRATION seems
to have disappeared, but is available in older kernels.)
- Write something that will periodically adjust the `ticks_per_sec` value to be
more accurate, comparing against the wall clock assuming the wall clock is
adjusted with NTP. See djb's clockspeed for inspiration.
:Variables:
- `ticks_per_sec`: Number of processor ticks per second.
- `ticks_per_usec`: Number of processor ticks per microsecond.
- `relative_usec_time`: Value of POSIX time (in microseconds) that relates
to `relative_tsc_time`.
- `relative_tsc_time`: Value of TSC counter that corresponds to
`relative_usec_time`.
- `relative_sec_time`: Value of POSIX time (in seconds) that relates to
`relative_tsc_time`.
"""
__version__ = '$Revision: 1.4 $'
include "python.pxi"
include "pyrex_helpers.pyx"
import time
from libc cimport uint64_t, int64_t, uint32_t, time_t
cdef extern from "rdtsc.h":
uint64_t _c_rdtsc "rdtsc" ()
cdef extern from "sys/sysctl.h":
int sysctlbyname(char *name, void *oldp, size_t *oldlenp, void *newp,
size_t newlen)
# This is a pointer so that the time shifting functions can replace it.
cdef uint64_t (*c_rdtsc) ()
c_rdtsc = _c_rdtsc
###########################################################################
# Helper functions.
###########################################################################
cdef int64_t c_get_kernel_usec():
global emulation_offset_usec
cdef libc.timeval tv_now
libc.gettimeofday(&tv_now, NULL)
return ((<int64_t>tv_now.tv_sec) * 1000000 + tv_now.tv_usec) + emulation_offset_usec
cdef uint64_t get_ticks_per_sec() except -1:
"""Gets the number of cycles per second for the TSC.
It uses sysctl to find the value.
Returns the ticks per second on success, -1 on failure.
"""
cdef uint64_t value
cdef char buffer[128]
cdef size_t buffer_size
# XXX - Need to find a way to get ticks per sec on Linux, fake it for now
IF UNAME_SYSNAME == "Linux":
return 2793008320
buffer_size = sizeof(buffer)
IF UNAME_SYSNAME == "Darwin":
if sysctlbyname("machdep.tsc.frequency", <void *>&buffer[0], &buffer_size, NULL, 0) == -1:
raise SystemError
ELSE:
# Leave this for backwards compatibility with 32/64-bit legacy systems
if sysctlbyname("machdep.tsc_freq_new", <void *>&buffer[0], &buffer_size, NULL, 0) == -1:
if sysctlbyname("machdep.tsc_freq", <void *>&buffer[0], &buffer_size, NULL, 0) == -1:
# Not all systems have this sysctl that we can build on
if libc.getenv("BUILDING") == NULL:
raise SystemError
else:
return 2793008320
if buffer_size == 4:
value = (<uint32_t *>buffer)[0];
else:
if buffer_size == 8:
value = (<uint64_t *>buffer)[0];
else:
raise SystemError
return value
cdef int64_t _relative_usec_time
cdef int64_t _relative_sec_time
cdef int64_t _relative_tsc_time
# XXX: FreeBSD currently has this as "int" via sysctl. Is this correct? Is
# this correct on AMD64? What shall we do once we exceed 4GHz?
cdef unsigned int _ticks_per_sec
cdef unsigned int _ticks_per_usec
ticks_per_sec = get_ticks_per_sec()
_ticks_per_sec = ticks_per_sec
_ticks_per_usec = _ticks_per_sec / 1000000
ticks_per_sec = _ticks_per_sec
ticks_per_usec = _ticks_per_usec
def get_kernel_usec():
"""Get the current time from the kernel in microseconds.
Avoid using this unless absolutely necessary due to performance reasons.
:Return:
Returns the current time in microseconds.
"""
return c_get_kernel_usec()
def rdtsc():
"""Return the current TSC value."""
return c_rdtsc()
cdef object struct_time
struct_time = time.struct_time
cdef _mk_tt(libc.tm * t):
"""Make a Python time tuple."""
return struct_time((t.tm_year + 1900,
t.tm_mon + 1,
t.tm_mday,
t.tm_hour,
t.tm_min,
t.tm_sec,
(t.tm_wday + 6) % 7,
t.tm_yday + 1,
t.tm_isdst))
cdef _get_tt(tt, libc.tm * t):
"""Convert a Python "time tuple" to a C tm struct."""
if isinstance(tt, struct_time):
# Convert to a tuple, this should be the most efficient way.
tt = tt[:]
elif not PyTuple_CheckExact(tt):
raise TypeError('Expected tuple or struct_time, got %r.' % (type(tt),))
if PyTuple_Size(tt) != 9:
raise ValueError('Must be 9 element tuple, was %r.' % (tt,))
t.tm_year = PyTuple_GET_ITEM_SAFE(tt, 0)
if t.tm_year < 1900:
raise ValueError('2-digit years not supported.')
t.tm_year = t.tm_year - 1900
t.tm_mon = PyTuple_GET_ITEM_SAFE(tt, 1)
t.tm_mon = t.tm_mon - 1
t.tm_mday = PyTuple_GET_ITEM_SAFE(tt, 2)
t.tm_hour = PyTuple_GET_ITEM_SAFE(tt, 3)
t.tm_min = PyTuple_GET_ITEM_SAFE(tt, 4)
t.tm_sec = PyTuple_GET_ITEM_SAFE(tt, 5)
t.tm_wday = PyTuple_GET_ITEM_SAFE(tt, 6)
t.tm_wday = (t.tm_wday + 1) % 7
t.tm_yday = PyTuple_GET_ITEM_SAFE(tt, 7)
t.tm_yday = t.tm_yday - 1
t.tm_isdst = PyTuple_GET_ITEM_SAFE(tt, 8)
cdef _strftime(char * format, libc.tm * t):
cdef char * buffer
cdef libc.size_t i
cdef libc.size_t buflen
cdef libc.size_t format_len
format_len = libc.strlen(format)
i = 1024
while 1:
buffer = <char *> libc.malloc(i)
if buffer == NULL:
raise MemoryError
try:
buflen = libc.strftime(buffer, i, format, t)
if buflen > 0 or i >= 256 * format_len:
# Copied from Python's strftime implementation.
# If the result is 0, but we had a buffer that was 256 times
# greater than the format len, then it's probably not
# failing for lack of room. It's probably just an empty
# result.
return PyString_FromStringAndSize(buffer, buflen)
finally:
libc.free(buffer)
# Double the buffer size and try again.
i = i*2
###########################################################################
# Time relativity used to keep the conversions accurate.
###########################################################################
cdef void c_update_time_relation():
global relative_usec_time, relative_sec_time, relative_tsc_time
global _relative_usec_time, _relative_sec_time, _relative_tsc_time
_relative_tsc_time = <int64_t>c_rdtsc()
_relative_usec_time = c_get_kernel_usec()
_relative_sec_time = _relative_usec_time / 1000000
relative_usec_time = _relative_usec_time
relative_sec_time = _relative_sec_time
relative_tsc_time = _relative_tsc_time
def update_time_relation():
"""Update the relative time stamps.
You should call this whenever you think the clock has been changed. It
should also be called periodically due to inaccuracies in the
``ticks_per_sec`` value.
"""
c_update_time_relation()
c_update_time_relation()
###########################################################################
# Functions for simulating time changes.
###########################################################################
cdef int64_t emulation_offset_usec
cdef int64_t emulation_offset_tsc
cdef uint64_t _rdtsc_emulation():
cdef int64_t s_temp
s_temp = <int64_t>_c_rdtsc()
s_temp + emulation_offset_tsc
return s_temp
def set_time(posix_timestamp):
"""Emulate setting the system time to the given timestamp.
This alters the library to behave as-if the current time is the given time.
Note that this is different than changing the clock on the system.
Changing the clock on the system does not affect TSC values, but this
function does affect TSC values to behave as-if time has elapsed in the
real world.
:Parameters:
- `posix_timestamp`: The POSIX timestamp (in seconds) to set the
current time. Pass in a value of 0 to disable emulation.
"""
global emulation_offset_usec, emulation_offset_tsc, c_rdtsc
cdef libc.timeval tv_now
cdef int64_t diff
if posix_timestamp == 0:
emulation_offset_usec = 0
emulation_offset_tsc = 0
c_rdtsc = _c_rdtsc
else:
libc.gettimeofday(&tv_now, NULL)
diff = posix_timestamp - tv_now.tv_sec
emulation_offset_usec = diff * 1000000
emulation_offset_tsc = diff * _ticks_per_sec
c_rdtsc = _rdtsc_emulation
c_update_time_relation()
def step_time(delta_secs):
"""Emulate changing the system time by the given number of seconds.
See `set_time` for more detail.
:Parameters:
- `delta_secs`: The number of seconds to alter the current time.
"""
global emulation_offset_usec, emulation_offset_tsc, c_rdtsc
emulation_offset_usec = emulation_offset_usec + delta_secs*1000000
emulation_offset_tsc = emulation_offset_tsc + delta_secs*_ticks_per_sec
c_rdtsc = _rdtsc_emulation
c_update_time_relation()
###########################################################################
# C raw conversion functions.
###########################################################################
cdef int64_t c_usec_to_ticks(int64_t t):
return (t - _relative_usec_time) * _ticks_per_usec + _relative_tsc_time
cdef int64_t c_ticks_to_usec(int64_t t):
# A more accurate, but slower version:
# return (1000000.00 * (t-_relative_tsc_time)) / _ticks_per_sec + _relative_usec_time
return (t - _relative_tsc_time) / _ticks_per_usec + _relative_usec_time
cdef int64_t c_sec_to_ticks(int64_t t):
return (t - _relative_sec_time) * _ticks_per_sec + _relative_tsc_time
cdef int64_t c_ticks_to_sec(int64_t t):
return ((t - _relative_tsc_time) / _ticks_per_usec + _relative_usec_time) / 1000000
cdef double c_ticks_to_fsec(int64_t t):
return ((<double>(t - _relative_tsc_time)) / _ticks_per_usec + _relative_usec_time) / 1000000.0
cdef int64_t c_fsec_to_ticks(double t):
return ((<int64_t>(t*1000000)) - _relative_usec_time) * _ticks_per_usec + _relative_tsc_time
###########################################################################
# Python-visable raw conversion functions.
###########################################################################
def usec_to_ticks(int64_t t):
"""Convert POSIX microseconds to ticks.
:Parameters:
- `t`: The time in POSIX microseconds.
:Return:
Returns the time in TSC ticks.
"""
return c_usec_to_ticks(t)
def ticks_to_usec(int64_t t):
"""Convert ticks to POSIX microseconds.
:Parameters:
- `t`: The time in TSC.
:Return:
Returns the time in POSIX microseconds.
"""
return c_ticks_to_usec(t)
def usec_to_ticks_safe(int64_t t):
"""Convert POSIX microseconds to ticks.
This is "safe" in that if the value is zero, then it returns zero.
:Parameters:
- `t`: The time in POSIX microseconds.
:Return:
Returns the time in TSC ticks.
"""
if t == 0:
return 0
else:
return c_usec_to_ticks(t)
def ticks_to_usec_safe(int64_t t):
"""Convert ticks to POSIX microseconds.
This is "safe" in that if the value is zero, then it returns zero.
:Parameters:
- `t`: The time in TSC.
:Return:
Returns the time in POSIX microseconds.
"""
if t == 0:
return 0
else:
return c_ticks_to_usec(t)
def sec_to_ticks(int64_t t):
"""Convert POSIX seconds to ticks.
:Parameters:
- `t`: The time in POSIX seconds (an integer).
:Return:
Returns the time in TSC ticks.
"""
return c_sec_to_ticks(t)
def ticks_to_sec(int64_t t):
"""Convert ticks to POSIX seconds (an integer).
:Parameters:
- `t`: The time in TSC.
:Return:
Returns the time in POSIX microseconds.
"""
return c_ticks_to_sec(t)
def ticks_to_fsec(int64_t t):
"""Convert ticks to POSIX seconds (a floating-point number).
:Parameters:
- `t`: The time in TSC.
:Return:
Returns the time in POSIX microseconds.
"""
return c_ticks_to_fsec(t)
def fsec_to_ticks(double t):
"""Convert POSIX seconds (a floating-point number) to ticks.
:Parameters:
- `t`: The time in POSIX seconds (a float).
:Return:
Returns the time in TSC ticks.
"""
return c_fsec_to_ticks(t)
###########################################################################
# Convenience functions for getting raw "now" values.
###########################################################################
def now_raw_tsc():
"""Get the current time as raw ticks."""
return <int64_t>c_rdtsc()
def now_raw_posix_sec():
"""Get the current time as raw POSIX seconds."""
return c_ticks_to_sec(<int64_t>c_rdtsc())
def now_raw_posix_usec():
"""Get the current time as raw POSIX microseconds."""
return c_ticks_to_usec(<int64_t>c_rdtsc())
def now_raw_posix_fsec():
"""Get the current time as raw POSIX floating-point seconds."""
return c_ticks_to_fsec(<int64_t>c_rdtsc())
###########################################################################
# Time objects.
###########################################################################
cdef time_t _asctime_cache_time
cdef object _asctime_cache_string
cdef class Time:
"""Base time object.
Time object support the following operations:
- Comparison. Comparison is done using the native time object type. For
example, "Posix" objects compare time in POSIX seconds. Thus, if
comparing two Posix objects that have slightly different TSC values, but
due to the loss of precision have the same POSIX value, they will compare
as equal.
Comparison between different types is OK (Posix compared to TSC). You
can also compare a value with Python numeric literals (int, long, float,
etc.).
- Hashing. Hashing is based on the object type.
- Addition and subtraction. This only works between two types of the exact
same type (Posix and Posix for example), or with a Python numeric literal
(int, long, float, etc.).
- int/long/float. Calling the int, long, or float functions on the object
will return an int, long, or float value of the object's type.
:IVariables:
- `tsc`: The time in TSC.
"""
# Defined in tsc_time.pxd.
#cdef readonly int64_t tsc
def __repr__(self):
return '<%s: %s>' % (type(self).__name__, self.c_ctime(),)
def as_posix_sec(self):
"""Return the time as POSIX seconds (an integer).
:Return:
Returns an integer as POSIX seconds.
"""
return c_ticks_to_sec(self.tsc)
def as_posix_usec(self):
"""Return the time as POSIX microseconds (a long).
:Return:
Returns a long as POSIX microseconds.
"""
return c_ticks_to_usec(self.tsc)
def as_posix_fsec(self):
"""Return the time as POSIX seconds (a floating-point number).
:Return:
Returns a float as POSIX seconds.
"""
return c_ticks_to_fsec(self.tsc)
def ctime(self):
"""Return the time as a string.
This returns the time as a classic C-style 24-character time string
in the local timezone in the format 'Sun Jun 20 23:21:05 1993'. This
does *not* include a trailing newline like C does.
:Return:
Returns a string of the local time.
"""
return self.c_ctime()
cdef c_ctime(self):
cdef char * p
cdef time_t posix_sec
global _asctime_cache_string, _asctime_cache_time
# We only compute this once a second. Note that this is a
# global, so it applies to all Time objects, but the most common
# behavior is to look at the current time.
posix_sec = c_ticks_to_sec(self.tsc)
if posix_sec == _asctime_cache_time and _asctime_cache_string is not None:
return _asctime_cache_string
else:
p = libc.ctime(&posix_sec)
p[24] = c'\0'
_asctime_cache_string = p
_asctime_cache_time = posix_sec
return _asctime_cache_string
def localtime(self):
"""Return a Python time-tuple in the local timezone.
:Return:
Returns a `time.struct_time` time-tuple in the local timezone.
"""
return self.c_localtime()
cdef c_localtime(self):
cdef libc.tm * t
cdef time_t posix_sec
posix_sec = c_ticks_to_sec(self.tsc)
t = libc.localtime(&posix_sec)
return _mk_tt(t)
def gmtime(self):
"""Return a Python time-tuple in UTC.
:Return:
Returns a `time.struct_time` time-tuple in UTC.
"""
return self.c_gmtime()
cdef c_gmtime(self):
cdef libc.tm * t
cdef time_t posix_sec
posix_sec = c_ticks_to_sec(self.tsc)
t = libc.gmtime(&posix_sec)
return _mk_tt(t)
def mkstr_local(self, format):
"""Convert time to a string in the local timezone.
:Parameters:
- `format`: The format that you want the string as. See the
``strftime`` function in the `time` module for more details.
:Return:
Returns a string in the local timezone.
"""
return self.c_mkstr_local(format)
cdef c_mkstr_local(self, char * format):
cdef libc.tm * t
cdef time_t posix_sec
posix_sec = c_ticks_to_sec(self.tsc)
t = libc.localtime(&posix_sec)
return _strftime(format, t)
def mkstr_utc(self, format):
"""Convert time to a string in UTC.
:Parameters:
- `format`: The format that you want the string as. See the
``strftime`` function in the `time` module for more details.
:Return:
Returns a string in UTC.
"""
return self.c_mkstr_utc(format)
cdef c_mkstr_utc(self, char * format):
cdef libc.tm * t
cdef time_t posix_sec
posix_sec = c_ticks_to_sec(self.tsc)
t = libc.gmtime(&posix_sec)
return _strftime(format, t)
cdef class TSC(Time):
"""Time in TSC ticks."""
def __hash__(self):
return <int>self.tsc
def __richcmp__(x, y, int op):
cdef int64_t a, b
if isinstance(x, Time):
a = (<Time>x).tsc
else:
a = PyNumber_Int(x)
if isinstance(y, Time):
b = (<Time>y).tsc
else:
b = PyNumber_Int(y)
if op == 0:
return a < b
elif op == 1:
return a <= b
elif op == 2:
return a == b
elif op == 3:
return a != b
elif op == 4:
return a > b
elif op == 5:
return a >= b
else:
raise AssertionError(op)
def __add__(x, y):
cdef TSC t
cdef TSC self
cdef int int_value
cdef long long longlong_value
cdef double double_value
if isinstance(x, TSC):
self = x
other = y
else:
assert isinstance(y, TSC)
self = y
other = x
if PyInt_CheckExact(other):
int_value = other
t = TSC()
t.tsc = self.tsc + int_value
return t
elif PyLong_CheckExact(other):
longlong_value = other
t = TSC()
t.tsc = self.tsc + longlong_value
return t
elif PyFloat_CheckExact(other):
double_value = other
t = TSC()
t.tsc = self.tsc + <int64_t>double_value
return t
else:
raise TypeError('unsupported operand type(s) for +: %r and %r' % (type(x).__name__, type(y).__name__))
def __sub__(x, y):
cdef TSC t
cdef TSC self
cdef int int_value
cdef long long longlong_value
cdef double double_value
if isinstance(x, TSC):
self = x
other = y
else:
assert isinstance(y, TSC)
self = y
other = x
if PyInt_CheckExact(other):
int_value = other
t = TSC()
t.tsc = self.tsc - int_value
return t
elif PyLong_CheckExact(other):
longlong_value = other
t = TSC()
t.tsc = self.tsc - longlong_value
return t
elif PyFloat_CheckExact(other):
double_value = other
t = TSC()
t.tsc = self.tsc - <int64_t>double_value
return t
else:
raise TypeError('unsupported operand type(s) for -: %r and %r' % (type(x).__name__, type(y).__name__))
def __int__(self):
return self.tsc
def __long__(self):
return self.tsc
def __float__(self):
return PyFloat_FromDouble(<double>self.tsc)
cdef class Posix(Time):
"""Time in POSIX seconds."""
def __hash__(self):
return c_ticks_to_sec(self.tsc)
def __richcmp__(x, y, int op):
cdef time_t a, b
if isinstance(x, Time):
a = c_ticks_to_sec((<Time>x).tsc)
else:
a = PyNumber_Int(x)
if isinstance(y, Time):
b = c_ticks_to_sec((<Time>y).tsc)
else:
b = PyNumber_Int(y)
if op == 0:
return a < b
elif op == 1:
return a <= b
elif op == 2:
return a == b
elif op == 3:
return a != b
elif op == 4:
return a > b
elif op == 5:
return a >= b
else:
raise AssertionError(op)
def __add__(x, y):
cdef Posix t
cdef Posix self
cdef int int_value
cdef long long longlong_value
cdef double double_value
if isinstance(x, Posix):
self = x
other = y
else:
assert isinstance(y, Posix)
self = y
other = x
if PyInt_CheckExact(other):
int_value = other
t = Posix()
t.tsc = self.tsc + int_value*_ticks_per_sec
return t
elif PyLong_CheckExact(other):
longlong_value = other
t = Posix()
t.tsc = self.tsc + longlong_value*_ticks_per_sec
return t
elif PyFloat_CheckExact(other):
double_value = other
t = Posix()
t.tsc = self.tsc + <int64_t>(double_value*<double>_ticks_per_sec)
return t
else:
raise TypeError('unsupported operand type(s) for +: %r and %r' % (type(x).__name__, type(y).__name__))
def __sub__(x, y):
cdef Posix t
cdef Posix self
cdef int int_value
cdef long long longlong_value
cdef double double_value
if isinstance(x, Posix):
self = x
other = y
else:
assert isinstance(y, Posix)
self = y
other = x
if PyInt_CheckExact(other):
int_value = other
t = Posix()
t.tsc = self.tsc - int_value*_ticks_per_sec
return t
elif PyLong_CheckExact(other):
longlong_value = other
t = Posix()
t.tsc = self.tsc - longlong_value*_ticks_per_sec
return t
elif PyFloat_CheckExact(other):
double_value = other
t = Posix()
t.tsc = self.tsc - <int64_t>(double_value*<double>_ticks_per_sec)
return t
else:
raise TypeError('unsupported operand type(s) for -: %r and %r' % (type(x).__name__, type(y).__name__))
def __int__(self):
return c_ticks_to_sec(self.tsc)
def __long__(self):
return PyLong_FromLong(c_ticks_to_sec(self.tsc))
def __float__(self):
return PyFloat_FromDouble(<double>c_ticks_to_sec(self.tsc))
cdef class uPosix(Time):
"""Time in POSIX microseconds."""
def __hash__(self):
return <int>c_ticks_to_usec(self.tsc)
def __richcmp__(x, y, int op):
cdef int64_t a, b
if isinstance(x, Time):
a = c_ticks_to_usec((<Time>x).tsc)
else:
a = PyNumber_Int(x)
if isinstance(y, Time):
b = c_ticks_to_usec((<Time>y).tsc)
else:
b = PyNumber_Int(y)
if op == 0:
return a < b
elif op == 1:
return a <= b
elif op == 2:
return a == b
elif op == 3:
return a != b
elif op == 4:
return a > b
elif op == 5:
return a >= b
else:
raise AssertionError(op)
def __add__(x, y):
cdef uPosix t
cdef uPosix self
cdef int int_value
cdef long long longlong_value
cdef double double_value
if isinstance(x, uPosix):
self = x
other = y
else:
assert isinstance(y, uPosix)
self = y
other = x
if PyInt_CheckExact(other):
int_value = other
t = uPosix()
t.tsc = self.tsc + int_value*_ticks_per_usec
return t
elif PyLong_CheckExact(other):
longlong_value = other
t = uPosix()
t.tsc = self.tsc + longlong_value*_ticks_per_usec
return t
elif PyFloat_CheckExact(other):
double_value = other
t = uPosix()
t.tsc = self.tsc + <int64_t>(double_value*<double>_ticks_per_usec)
return t
else:
raise TypeError('unsupported operand type(s) for +: %r and %r' % (type(x).__name__, type(y).__name__))
def __sub__(x, y):
cdef uPosix t
cdef uPosix self
cdef int int_value
cdef long long longlong_value
cdef double double_value
if isinstance(x, uPosix):
self = x
other = y
else:
assert isinstance(y, uPosix)
self = y
other = x
if PyInt_CheckExact(other):
int_value = other
t = uPosix()
t.tsc = self.tsc - int_value*_ticks_per_usec
return t
elif PyLong_CheckExact(other):
longlong_value = other
t = uPosix()
t.tsc = self.tsc - longlong_value*_ticks_per_usec
return t
elif PyFloat_CheckExact(other):
double_value = other
t = uPosix()
t.tsc = self.tsc - <int64_t>(double_value*<double>_ticks_per_usec)
return t
else:
raise TypeError('unsupported operand type(s) for -: %r and %r' % (type(x).__name__, type(y).__name__))
def __int__(self):
return c_ticks_to_usec(self.tsc)
def __long__(self):
return c_ticks_to_usec(self.tsc)
def __float__(self):
return PyFloat_FromDouble(<double>c_ticks_to_usec(self.tsc))
cdef class fPosix(Time):
"""Time in POSIX seconds as a floating-point number."""
def __hash__(self):
return c_ticks_to_sec(self.tsc)
def __richcmp__(x, y, int op):
cdef double a, b
if isinstance(x, Time):
a = c_ticks_to_fsec((<Time>x).tsc)
else:
a = PyNumber_Float(x)
if isinstance(y, Time):
b = c_ticks_to_fsec((<Time>y).tsc)
else:
b = PyNumber_Float(y)
if op == 0:
return a < b
elif op == 1:
return a <= b
elif op == 2:
return a == b
elif op == 3:
return a != b
elif op == 4:
return a > b
elif op == 5:
return a >= b
else:
raise AssertionError(op)
def __add__(x, y):
cdef fPosix t
cdef fPosix self
cdef int int_value
cdef long long longlong_value
cdef double double_value
if isinstance(x, fPosix):
self = x
other = y
else:
assert isinstance(y, fPosix)
self = y
other = x
if PyInt_CheckExact(other):
int_value = other
t = fPosix()
t.tsc = self.tsc + int_value*_ticks_per_sec
return t
elif PyLong_CheckExact(other):
longlong_value = other
t = fPosix()
t.tsc = self.tsc + longlong_value*_ticks_per_sec
return t
elif PyFloat_CheckExact(other):
double_value = other
t = fPosix()
t.tsc = self.tsc + <int64_t>(double_value*<double>_ticks_per_sec)
return t
else:
raise TypeError('unsupported operand type(s) for +: %r and %r' % (type(x).__name__, type(y).__name__))
def __sub__(x, y):
cdef fPosix t
cdef fPosix self
cdef int int_value
cdef long long longlong_value
cdef double double_value
if isinstance(x, fPosix):
self = x
other = y
else:
assert isinstance(y, fPosix)
self = y
other = x
if PyInt_CheckExact(other):
int_value = other
t = fPosix()
t.tsc = self.tsc - int_value*_ticks_per_sec
return t
elif PyLong_CheckExact(other):
longlong_value = other
t = fPosix()
t.tsc = self.tsc - longlong_value*_ticks_per_sec
return t
elif PyFloat_CheckExact(other):
double_value = other
t = fPosix()
t.tsc = self.tsc - <int64_t>(double_value*<double>_ticks_per_sec)
return t
else:
raise TypeError('unsupported operand type(s) for -: %r and %r' % (type(x).__name__, type(y).__name__))
def __int__(self):
return c_ticks_to_sec(self.tsc)
def __long__(self):
return PyLong_FromLong(c_ticks_to_sec(self.tsc))
def __float__(self):
return c_ticks_to_fsec(self.tsc)
###########################################################################
# "Now" constructors
###########################################################################
def now_tsc():
"""Return a TSC object of the current time."""
return c_now_tsc()
def now_posix_sec():
"""Return a Posix object of the current time."""
return c_now_posix_sec()
def now_posix_usec():
"""Return a uPosix object of the current time."""
return c_now_posix_usec()
def now_posix_fsec():
"""Return an fPosix object of the current time."""
return c_now_posix_fsec()
cdef TSC c_now_tsc():
cdef TSC t
t = TSC()
t.tsc = <int64_t>c_rdtsc()
return t
cdef Posix c_now_posix_sec():
cdef Posix t
t = Posix()
t.tsc = <int64_t>c_rdtsc()
return t
cdef uPosix c_now_posix_usec():
cdef uPosix t
t = uPosix()
t.tsc = <int64_t>c_rdtsc()
return t
cdef fPosix c_now_posix_fsec():
cdef fPosix t
t = fPosix()
t.tsc = <int64_t>c_rdtsc()
return t
###########################################################################
# "mktime" constructors
###########################################################################
def mktime_tsc(tt):
"""Convert a Python time-tuple to a TSC object."""
cdef TSC t
cdef time_t posix
cdef libc.tm tm_st
_get_tt(tt, &tm_st)
posix = libc.mktime(&tm_st)
t = TSC()
t.tsc = c_sec_to_ticks(posix)
return t
def mktime_posix_sec(tt):
"""Convert a Python time-tuple to a Posix object."""
cdef Posix t
cdef time_t posix
cdef libc.tm tm_st
_get_tt(tt, &tm_st)
posix = libc.mktime(&tm_st)
t = Posix()
t.tsc = c_sec_to_ticks(posix)
return t
def mktime_posix_usec(tt):
"""Convert a Python time-tuple to a uPosix object."""
cdef uPosix t
cdef time_t posix
cdef libc.tm tm_st
_get_tt(tt, &tm_st)
posix = libc.mktime(&tm_st)
t = uPosix()
t.tsc = c_sec_to_ticks(posix)
return t
def mktime_posix_fsec(tt):
"""Convert a Python time-tuple to an fPosix object."""
cdef fPosix t
cdef time_t posix
cdef libc.tm tm_st
_get_tt(tt, &tm_st)
posix = libc.mktime(&tm_st)
t = fPosix()
t.tsc = c_sec_to_ticks(posix)
return t
###########################################################################
# "numeric" constructors
###########################################################################
def TSC_from_ticks(int64_t t):
"""Convert a raw TSC value to a TSC object."""
cdef TSC v
v = TSC()
v.tsc = t
return v
def TSC_from_posix_sec(time_t t):
"""Convert a raw POSIX seconds value to a TSC object."""
cdef TSC v
v = TSC()
v.tsc = c_sec_to_ticks(t)
return v
def TSC_from_posix_usec(int64_t t):
"""Convert a raw POSIX microseconds value to a TSC object."""
cdef TSC v
v = TSC()
v.tsc = c_usec_to_ticks(t)
return v
def TSC_from_posix_fsec(double t):
"""Convert a raw POSIX floating-point seconds value to a TSC object."""
cdef TSC v
v = TSC()
v.tsc = c_usec_to_ticks(<int64_t>(t*1000000.0))
return v
###########################################################################
def Posix_from_ticks(int64_t t):
"""Convert a raw TSC value to a Posix object."""
cdef Posix v
v = Posix()
v.tsc = t
return v
def Posix_from_posix_sec(time_t t):
"""Convert a raw POSIX seconds value to a Posix object."""
cdef Posix v
v = Posix()
v.tsc = c_sec_to_ticks(t)
return v
def Posix_from_posix_usec(int64_t t):
"""Convert a raw POSIX microseconds value to a Posix object."""
cdef Posix v
v = Posix()
v.tsc = c_usec_to_ticks(t)
return v
def Posix_from_posix_fsec(double t):
"""Convert a raw POSIX floating-point seconds value to a Posix object."""
cdef Posix v
v = Posix()
v.tsc = c_usec_to_ticks(<int64_t>(t*1000000.0))
return v
###########################################################################
def uPosix_from_ticks(int64_t t):
"""Convert a raw TSC value to a uPosix object."""
cdef uPosix v
v = uPosix()
v.tsc = t
return v
def uPosix_from_posix_sec(time_t t):
"""Convert a raw POSIX seconds value to a uPosix object."""
cdef uPosix v
v = uPosix()
v.tsc = c_sec_to_ticks(t)
return v
def uPosix_from_posix_usec(int64_t t):
"""Convert a raw POSIX microseconds value to a uPosix object."""
cdef uPosix v
v = uPosix()
v.tsc = c_usec_to_ticks(t)
return v
def uPosix_from_posix_fsec(double t):
"""Convert a raw POSIX floating-point seconds value to a uPosix object."""
cdef uPosix v
v = uPosix()
v.tsc = c_usec_to_ticks(<int64_t>(t*1000000.0))
return v
###########################################################################
def fPosix_from_ticks(int64_t t):
"""Convert a raw TSC value to an fPosix object."""
cdef fPosix v
v = fPosix()
v.tsc = t
return v
def fPosix_from_posix_sec(time_t t):
"""Convert a raw POSIX seconds value to an fPosix object."""
cdef fPosix v
v = fPosix()
v.tsc = c_sec_to_ticks(t)
return v
def fPosix_from_posix_usec(int64_t t):
"""Convert a raw POSIX microseconds value to an fPosix object."""
cdef fPosix v
v = fPosix()
v.tsc = c_usec_to_ticks(t)
return v
def fPosix_from_posix_fsec(double t):
"""Convert a raw POSIX floating-point seconds value to an fPosix object."""
cdef fPosix v
v = fPosix()
v.tsc = c_usec_to_ticks(<int64_t>(t*1000000.0))
return v
###########################################################################
# Provide access to other C modules.
###########################################################################
cdef void * __ptr_array[12]
__ptr_array[0] = &c_usec_to_ticks
__ptr_array[1] = &c_ticks_to_usec
__ptr_array[2] = &c_sec_to_ticks
__ptr_array[3] = &c_ticks_to_sec
__ptr_array[4] = &c_ticks_to_fsec
__ptr_array[5] = &c_fsec_to_ticks
__ptr_array[6] = &c_update_time_relation
__ptr_array[7] = &c_now_tsc
__ptr_array[8] = &c_now_posix_sec
__ptr_array[9] = &c_now_posix_usec
__ptr_array[10] = &c_now_posix_fsec
__ptr_array[11] = c_rdtsc
_extern_pointers = PyCObject_FromVoidPtr(<void *>__ptr_array, NULL)
# Copyright (c) 2002-2011 IronPort Systems and Cisco Systems
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""OSError mapping.
This module maps OSErrors to specific, catchable exceptions. For example, an
OSError with an errno of ENOENT will be raised as the ENOENT exception. All
exceptions derive from OSError, so it is compatible with regular OSError
handling.
"""
include "python.pxi"
import errno
import new
import sys
cimport libc
err_map = {}
def map_exception(e):
"""Raise an errno-specific exception.
:Parameters:
- `e`: The OSError instance.
"""
# Ignoring e.filename since it seems less than useful to me.
try:
raise err_map[e.errno](e.errno, e.strerror)
except KeyError:
raise e
def raise_oserror(int error_number):
"""Raise an OSError exception by errno.
:Parameters:
- `error_number`: The errno value to raise.
"""
map_exception(OSError(error_number, libc.strerror(error_number)))
__m = sys.modules['coro.oserrors']
__g = __m.__dict__
for errcode, errname in errno.errorcode.items():
# Not sure why __module__ is not getting set properly. Python looks at
# globals() to fine __name__ to set the value, and it appears to be
# set to __main__ for some odd reason.
c = new.classobj(errname, (OSError,), {'__module__': 'coro.oserrors'})
err_map[errcode] = c
__g[errname] = c
...@@ -31,7 +31,6 @@ __socket_version__ = "$Id: //prod/main/ap/shrapnel/coro/socket.pyx#57 $" ...@@ -31,7 +31,6 @@ __socket_version__ = "$Id: //prod/main/ap/shrapnel/coro/socket.pyx#57 $"
import socket as __socketmodule import socket as __socketmodule
from aplib.net.ip import is_ipv6, is_ipv4
IF UNAME_SYSNAME == "Linux": IF UNAME_SYSNAME == "Linux":
cdef extern from "stdint.h": cdef extern from "stdint.h":
ctypedef unsigned char uint8_t ctypedef unsigned char uint8_t
...@@ -1542,28 +1541,6 @@ def make_socket (int domain, int stype): ...@@ -1542,28 +1541,6 @@ def make_socket (int domain, int stype):
""" """
return sock (domain, stype) return sock (domain, stype)
def make_socket_for_ip(ip, stype=SOCK_STREAM):
"""Create a socket object with the correct address family for ip.
:Parameters:
- `ip`: An IP address as a string
- `stype`: The socket type (see `SOCK`).
:Return:
Returns a socket object.
:Exceptions:
- `OSError`: OS-level error.
- `ValueError`: Invalid IP address.
"""
if is_ipv4(ip):
return make_socket(AF_INET, stype)
elif is_ipv6(ip):
return make_socket(AF_INET6, stype)
else:
raise ValueError('Invalid IP address')
def has_ipv6(): def has_ipv6():
"""Whether or not this system can create an IPv6 socket. """Whether or not this system can create an IPv6 socket.
......
# Copyright (c) 2002-2011 IronPort Systems and Cisco Systems
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Compact stack trace functions.
This module provides some functions to get a stack trace string.
These stack traces are much more compact than the ones generated by the
traceback module.
"""
import os
import sys
def _get_module_name(n):
try:
path, filename = os.path.split(n)
path, directory = os.path.split(path)
#name, ext = os.path.splitext(filename)
if directory:
return '/'.join((directory, filename))
else:
return filename
except:
return '???'
def stack_string(f=None):
"""Return a compact string representing the current call stack.
:Parameters:
- `f`: Frame object. If not specified, will use the current call
position.
:Return:
Returns a string of the current stack trace.
"""
if f is None:
try:
raise ZeroDivisionError
except ZeroDivisionError:
f = sys.exc_info()[2].tb_frame.f_back
stack = []
while f is not None:
stack.append(
_get_module_name(f.f_code.co_filename) + ' ' +
f.f_code.co_name + '|' +
str(f.f_lineno)
)
f = f.f_back
return '[' + ('] ['.join(stack))+ ']'
def traceback_string(t=None, v=None, tb=None):
"""Returns a compact string representing the current exception.
If an exception is not provided as an argument, then it will get the
current exception from `sys.exc_info`.
:Parameters:
- `t`: Exception type.
- `v`: Exception value.
- `tb`: Traceback object.
:Return:
Returns a string of the current exception and stack trace.
"""
if t is None:
t,v,tb = sys.exc_info()
tbinfo = []
if tb is None:
# this should never happen, but then again, lots of things
# should never happen but do
return 'traceback is None!!!'
while tb is not None:
tbinfo.append (
_get_module_name (tb.tb_frame.f_code.co_filename) + ' ' +
tb.tb_frame.f_code.co_name + '|' +
str(tb.tb_lineno)
)
tb = tb.tb_next
# just to be safe
del tb
first = tbinfo[-1]
info = '[' + ('] ['.join (tbinfo)) + ']'
return repr(((first), str(t), str(v), info))
...@@ -47,7 +47,7 @@ __version__ = '$Revision: #1 $' ...@@ -47,7 +47,7 @@ __version__ = '$Revision: #1 $'
import coro import coro
import signal import signal
import sys import sys
from aplib import tb from coro import tb
import unittest import unittest
exc_str_list = [] exc_str_list = []
......
/*
Copyright (c) 2002-2011 IronPort Systems and Cisco Systems
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
Helper functions for Pyrex.
These will be (hopefully) inlined into your code. Say:
include "pyrex_helpers.pyx"
in your Pyrex file to include these functions.
*/
#ifndef _PYREX_HELPERS_H_
#define _PYREX_HELPERS_H_
#include "Python.h"
#define PyINLINE_FUNC(RTYPE) static __attribute__ ((no_instrument_function)) inline RTYPE
/* Support varargs support.
If there is a C type that you need that is not here, feel free to add it.
Someday Pyrex may have native support for this.
*/
#define va_int(ap) va_arg(ap, int)
#define va_charptr(ap) va_arg(ap, char *)
/* Convenience/performance. */
#define IMAX(a,b) ((a) > (b) ? (a) : (b))
#define IMIN(a,b) ((a) < (b) ? (a) : (b))
/* Converting Python builtins to direct calls. */
#define callable(o) PyCallable_Check(o)
#define type(o) PyObject_Type(o)
/* Abstract functions. */
PyINLINE_FUNC(PyObject *)
PySequence_Fast_GET_ITEM_SAFE (PyObject * o, int i)
{
PyObject * x = PySequence_Fast_GET_ITEM(o, i);
Py_INCREF(x);
return x;
}
PyINLINE_FUNC(int)
cmp (PyObject * o1, PyObject * o2)
{
int result;
if(PyObject_Cmp(o1, o2, &result)) {
return -1;
} else {
return result;
}
}
/* List functions. */
PyINLINE_FUNC(PyObject *)
PyList_GET_ITEM_SAFE (PyObject * l, int i)
{
PyObject * x = PyList_GET_ITEM (l, i);
Py_INCREF (x);
return x;
}
PyINLINE_FUNC(void)
PyList_SET_ITEM_SAFE (PyObject * l, int i, PyObject * v)
{
PyList_SET_ITEM (l, i, v);
Py_INCREF (v);
}
PyINLINE_FUNC(PyObject *)
PyList_GetItem_SAFE (PyObject * l, int i)
{
PyObject * x = PyList_GetItem (l, i);
Py_INCREF (x);
return x;
}
PyINLINE_FUNC(void)
PyList_SetItem_SAFE (PyObject * l, int i, PyObject * v)
{
PyList_SetItem (l, i, v);
Py_INCREF (v);
}
/* Tuple functions. */
PyINLINE_FUNC(PyObject *)
PyTuple_GET_ITEM_SAFE (PyObject * l, int i)
{
PyObject * x = PyTuple_GET_ITEM (l, i);
Py_INCREF (x);
return x;
}
PyINLINE_FUNC(void)
PyTuple_SET_ITEM_SAFE (PyObject * l, int i, PyObject * v)
{
PyTuple_SET_ITEM (l, i, v);
Py_INCREF (v);
}
PyINLINE_FUNC(PyObject *)
PyTuple_GetItem_SAFE (PyObject * l, int i)
{
PyObject * x = PyTuple_GetItem (l, i);
Py_INCREF (x);
return x;
}
PyINLINE_FUNC(void)
PyTuple_SetItem_SAFE (PyObject * l, int i, PyObject * v)
{
PyTuple_SetItem (l, i, v);
Py_INCREF (v);
}
/* Dict functions. */
/*
Note, you *must* set ``instead`` to a real Python object, you cannot set it
to NULL. Suggest using None.
*/
PyINLINE_FUNC(PyObject *)
PyDict_GET_ITEM_SAFE (PyObject * d, PyObject * k, PyObject * instead)
{
PyObject * r = PyDict_GetItem (d, k);
if (r == NULL) {
r = instead;
}
Py_INCREF (r);
return r;
}
/* Memory functions. */
/*
These functions are "safe" in that they set MemoryError if it fails.
Note that "free" doesn't do anything special, it's just here to maintain a
consistent naming scheme.
*/
PyINLINE_FUNC(void *)
Pyrex_Malloc_SAFE(size_t size)
{
void * r;
r = PyMem_Malloc(size);
if (r == NULL) {
PyErr_NoMemory();
return NULL;
} else {
return r;
}
}
PyINLINE_FUNC(void *)
Pyrex_Realloc_SAFE(void * ptr, size_t size)
{
void * r;
r = PyMem_Realloc(ptr, size);
if (r == NULL) {
PyErr_NoMemory();
return NULL;
} else {
return r;
}
}
PyINLINE_FUNC(void)
Pyrex_Free_SAFE(void * ptr)
{
PyMem_Free(ptr);
}
/* Number functions. */
PyINLINE_FUNC(PyObject *)
minimal_ulonglong(unsigned long long value)
{
if (value > PyInt_GetMax()) {
return PyLong_FromUnsignedLongLong(value);
} else {
return PyInt_FromLong(value);
}
}
PyINLINE_FUNC(PyObject *)
minimal_long_long(long long value)
{
if (value > PyInt_GetMax() || value < -PyInt_GetMax()-1) {
return PyLong_FromLongLong(value);
} else {
return PyInt_FromLong(value);
}
}
PyINLINE_FUNC(PyObject *)
minimal_ulong(unsigned long value)
{
if (value > PyInt_GetMax()) {
return PyLong_FromUnsignedLong(value);
} else {
return PyInt_FromLong(value);
}
}
#endif
/*
Copyright (c) 2002-2011 IronPort Systems and Cisco Systems
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _RDTSC_H_
#define _RDTSC_H_
/*
rdtsc - ReaD TimeStamp Counter
The cycle counter in the Pentium series of processors is incremented
once for every clock cycle. It starts out as 0 on system boot.
It is a 64-bit number, and thus will wrap over in 292 years on a
2 gigahertz processor. It should keep counting unless the system
goes into deep sleep mode.
There is still some uncertainty about the P4 Xeon processor which
has the ability to lower its clock cycle when a temperature
threshold is met. Does this also change the frequency of the TSC?
FYI, the control registers on the Pentium can be configured to
restrict RDTSC to privileged level 0.
The RDTSC instruction is generally not synchronized. Thus, with
out of order execution, it is possible for it to run ahead of
other instructions that came before it. This is mainly only important
if you are trying to do exact profiling of instruction cycles.
I for the life of me can't find the number of actual cycles it takes
to read the counter for the Pentium 4. It's 11 cycles on the AMD
Athlon.
FreeBSD does not use the TSC for two apparent reasons: It is difficult
to synchronize on an SMP machine, and it is difficult to account for
time on a machine with APM enabled. Neither of these should affect us.
Some notes about FreeBSD and frequency counters:
- The TSC frequency can be found via sysctl as machdep.tsc_freq.
- FreeBSD will not bother to compute tsc_freq if you are building an SMP
kernel, or you have APM enabled.
- By default, FreeBSD will assume the i8254 timer frequency is 1193182
- If you compile with CLK_USE_I8254_CALIBRATION, it will try to determine
what the actual i8254 frequency is using the mc146818A chip.
- If you compile with CLK_USE_TSC_CALIBRATION, it will try to determine
what the actual TSC frequency is using the mc146818A chip. Otherwise
it will use a less acurate approximation using the i8254 chip.
- If you compile with CLK_CALIBRATION_LOOP, then during bootup it will
recompute the clock frequencies over and over again until you press
a key on the console (debugging to see if the clock calibration
routines are correct?).
*/
static inline
uint64_t
rdtsc(void)
{
uint32_t a, d;
asm volatile ("rdtsc" : "=a"(a), "=d"(d));
return (((uint64_t) d << 32) | a);
}
#endif /* _RDTSC_H_ */
/*
Copyright (c) 2002-2011 IronPort Systems and Cisco Systems
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This header file provides a method to access the C functions from the tsc_time
module directly.
To use, include this header file in your C extension module. In the
initmodulename function, be sure to call init_tsc_time_pointers().
The raw conversion functions can be called directly like this:
int64_t t = usec_to_ticks(somevalue);
The constructors can be called like this:
TSC * t = now_tsc();
printf("%llu\n", t.tsc);
The structures are provided so that you can access the "tsc" value directly.
The type objects are also available if you need to do type comparisons, but I
suspect this won't be necessary.
Note that there is a small memory leak because there is no finalizer here (when
Python exits).
*/
#ifndef _TSC_TIME_H_
#define _TSC_TIME_H_
#include "Python.h"
#include <inttypes.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
Pointers to the raw low-level conversion functions.
*/
static int64_t (*usec_to_ticks) (int64_t);
static int64_t (*ticks_to_usec) (int64_t);
static int64_t (*sec_to_ticks) (int64_t);
static int64_t (*ticks_to_sec) (int64_t);
static double (*ticks_to_fsec) (int64_t);
static int64_t (*fsec_to_ticks) (double);
static void (*update_time_relation) (void);
static int64_t (*rdtsc) (void);
typedef struct Time {
PyObject_HEAD
int64_t tsc;
} Time;
typedef struct TSC {
PyObject_HEAD
int64_t tsc;
} TSC;
typedef struct Posix {
PyObject_HEAD
int64_t tsc;
} Posix;
typedef struct uPosix {
PyObject_HEAD
int64_t tsc;
} uPosix;
typedef struct fPosix {
PyObject_HEAD
int64_t tsc;
} fPosix;
static PyObject * Time_Type = NULL;
static PyObject * TSC_Type = NULL;
static PyObject * Posix_Type = NULL;
static PyObject * uPosix_Type = NULL;
static PyObject * fPosix_Type = NULL;
/*
Pointers to construction functions.
*/
static TSC * (*now_tsc)(void);
static Posix * (*now_posix_sec)(void);
static uPosix * (*now_posix_usec)(void);
static fPosix * (*now_posix_fsec)(void);
/*
Initialize pointers to the tsc_time module.
Returns 0 on success, -1 on failure (with python exception set).
*/
int
init_tsc_time_pointers(void)
{
PyObject * m = NULL;
PyObject * c_obj = NULL;
void ** c_ptr;
if (Time_Type != NULL) {
// Already initialized.
return 0;
}
m = PyImport_ImportModule("coro.clocks.tsc_time");
if (m == NULL) {
goto fail;
}
c_obj = PyObject_GetAttrString(m, "_extern_pointers");
if (c_obj == NULL) {
goto fail;
}
c_ptr = (void **) PyCObject_AsVoidPtr(c_obj);
if (c_ptr == NULL) {
goto fail;
}
usec_to_ticks = (int64_t (*)(int64_t)) c_ptr[0];
ticks_to_usec = (int64_t (*)(int64_t)) c_ptr[1];
sec_to_ticks = (int64_t (*)(int64_t)) c_ptr[2];
ticks_to_sec = (int64_t (*)(int64_t)) c_ptr[3];
ticks_to_fsec = (double (*)(int64_t)) c_ptr[4];
fsec_to_ticks = (int64_t (*)(double)) c_ptr[5];
update_time_relation = (void (*)(void)) c_ptr[6];
now_tsc = (TSC * (*)(void)) c_ptr[7];
now_posix_sec = (Posix * (*)(void)) c_ptr[8];
now_posix_usec = (uPosix * (*)(void)) c_ptr[9];
now_posix_fsec = (fPosix * (*)(void)) c_ptr[10];
rdtsc = (int64_t (*)(void)) c_ptr[11];
Time_Type = PyObject_GetAttrString(m, "Time");
TSC_Type = PyObject_GetAttrString(m, "TSC");
Posix_Type = PyObject_GetAttrString(m, "Posix");
uPosix_Type = PyObject_GetAttrString(m, "uPosix");
fPosix_Type = PyObject_GetAttrString(m, "fPosix");
Py_DECREF(m);
Py_DECREF(c_obj);
return 0;
fail:
Py_XDECREF(m);
Py_XDECREF(c_obj);
return -1;
}
#ifdef __cplusplus
} /* extern C */
#endif
#endif /* _TSC_TIME_H_ */
This directory contains a collection of generic Pyrex include files.
Do not put any pyrex modules in here.
# Copyright (c) 2002-2011 IronPort Systems and Cisco Systems
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Definitions from libc.
cdef extern char ** environ
cdef extern from "inttypes.h":
ctypedef char int8_t
ctypedef unsigned char uint8_t
ctypedef short int16_t
ctypedef unsigned short uint16_t
ctypedef int int32_t
ctypedef unsigned int uint32_t
ctypedef long long int64_t
ctypedef unsigned long long uint64_t
ctypedef long intptr_t
ctypedef unsigned long uintptr_t
cdef extern from "sys/types.h":
ctypedef unsigned long size_t
ctypedef long ssize_t
ctypedef int64_t off_t
ctypedef uint16_t mode_t
ctypedef int32_t pid_t
ctypedef long time_t
ctypedef long suseconds_t
ctypedef uint32_t gid_t
ctypedef int64_t id_t
ctypedef uint32_t uid_t
ctypedef uint32_t fixpt_t
ctypedef uint32_t dev_t
ctypedef long segsz_t
ctypedef unsigned long vm_size_t
ctypedef unsigned char u_char
ctypedef unsigned short u_short
ctypedef unsigned int u_int
ctypedef unsigned long u_long
ctypedef unsigned short ushort # Sys V compatibility
ctypedef unsigned int uint # Sys V compatibility
cdef extern from "stdarg.h":
# The type of va_list is not a standard definition.
# This should be a rather opaque type.
ctypedef void * va_list
# va_arg support is not possible in Pyrex. Some hard-coded types
# are available in pyrex_helpers.pyx.
void va_start(va_list ap, last)
void va_copy(va_list dest, va_list src)
void va_end(va_list ap)
cdef extern from "stdio.h":
ctypedef struct FILE:
pass
void perror(char *string)
int printf (char * format, ...)
int fprintf (FILE * stream, char * format, ...)
int sprintf (char * str, char * format, ...)
int snprintf(char * str, size_t size, char * format, ...)
int asprintf(char **ret, char *format, ...)
int vprintf (char * format, va_list ap)
int vfprintf(FILE * stream, char * format, va_list ap)
int vsprintf(char * str, char * format, va_list ap)
int vsnprintf(char * str, size_t size, char * format, va_list ap)
int vasprintf(char **ret, char *format, va_list ap)
FILE * stderr
FILE * stdin
FILE * stdout
cdef extern from "ctype.h":
int isalnum (int)
int isalpha (int)
int iscntrl (int)
int isdigit (int)
int isgraph (int)
int islower (int)
int isprint (int)
int ispunct (int)
int isspace (int)
int isupper (int)
int isxdigit (int)
int tolower (int)
int toupper (int)
cdef extern from "errno.h":
extern int errno
cdef enum enum_errno:
EPERM
ENOENT
ESRCH
EINTR
EIO
ENXIO
E2BIG
ENOEXEC
EBADF
ECHILD
EDEADLK
ENOMEM
EACCES
EFAULT
ENOTBLK
EBUSY
EEXIST
EXDEV
ENODEV
ENOTDIR
EISDIR
EINVAL
ENFILE
EMFILE
ENOTTY
ETXTBSY
EFBIG
ENOSPC
ESPIPE
EROFS
EMLINK
EPIPE
EDOM
ERANGE
EAGAIN
EWOULDBLOCK
EINPROGRESS
EALREADY
ENOTSOCK
EDESTADDRREQ
EMSGSIZE
EPROTOTYPE
ENOPROTOOPT
EPROTONOSUPPORT
ESOCKTNOSUPPORT
EOPNOTSUPP
ENOTSUP
EPFNOSUPPORT
EAFNOSUPPORT
EADDRINUSE
EADDRNOTAVAIL
ENETDOWN
ENETUNREACH
ENETRESET
ECONNABORTED
ECONNRESET
ENOBUFS
EISCONN
ENOTCONN
ESHUTDOWN
ETOOMANYREFS
ETIMEDOUT
ECONNREFUSED
ELOOP
ENAMETOOLONG
EHOSTDOWN
EHOSTUNREACH
ENOTEMPTY
EPROCLIM
EUSERS
EDQUOT
ESTALE
EREMOTE
EBADRPC
ERPCMISMATCH
EPROGUNAVAIL
EPROGMISMATCH
EPROCUNAVAIL
ENOLCK
ENOSYS
EFTYPE
EAUTH
ENEEDAUTH
EIDRM
ENOMSG
EOVERFLOW
ECANCELED
EILSEQ
ENOATTR
EDOOFUS
EBADMSG
EMULTIHOP
ENOLINK
EPROTO
cdef extern from "stdlib.h":
void * alloca (size_t size)
void abort ()
int atoi (char *nptr)
char * getenv(char *name)
int setenv(char *name, char *value, int overwrite)
int putenv(char *string)
void unsetenv(char *name)
void * malloc(size_t size)
void * calloc(size_t number, size_t size)
void * realloc(void *ptr, size_t size)
void free(void *ptr)
int daemon(int nochdir, int noclose)
cdef extern from "string.h":
void * memset (void *b, int c, size_t len)
void * memcpy (void *dst, void *src, size_t len)
size_t strlen (char *s)
int memcmp (void *b1, void *b2, size_t len)
char * strerror(int errnum)
int strerror_r(int errnum, char *strerrbuf, size_t buflen)
int strncmp(char *s1, char *s2, size_t len)
cdef extern from "unistd.h":
int pipe(int *)
int close(int)
pid_t tcgetpgrp(int)
pid_t getpgrp()
pid_t getpgid(pid_t)
pid_t fork()
pid_t getpid()
pid_t getppid()
int setpgid(pid_t pid, pid_t pgrp)
int setpgrp(pid_t pid, pid_t pgrp)
int tcsetpgrp(int fd, pid_t pgrp_id)
int dup(int oldd)
int dup2(int oldd, int newd)
void _exit(int status)
long sysconf(int name)
int chdir(char *path)
int fchdir(int fd)
int execl(char *path, char *arg, ...)
int execlp(char *file, char *arg, ...)
int execle(char *path, char *arg, ...)
int exect(char *path, char *argv[], char *envp[])
int execv(char *path, char *argv[])
int execvp(char *file, char *argv[])
int execvP(char *file, char *search_path, char *argv[])
int execve(char *path, char *argv[], char *envp[])
int getgrouplist(char *name, gid_t basegid, gid_t *groups, int *ngroups)
int setgroups(int ngroups, gid_t *gidset)
int getgroups(int gidsetlen, gid_t *gidset)
int initgroups(char *name, gid_t basegid)
cdef enum:
NGROUPS_MAX
cdef enum sysconf_vars:
_SC_ARG_MAX
_SC_CHILD_MAX
_SC_CLK_TCK
_SC_NGROUPS_MAX
_SC_OPEN_MAX
_SC_JOB_CONTROL
_SC_SAVED_IDS
_SC_VERSION
_SC_BC_BASE_MAX
_SC_BC_DIM_MAX
_SC_BC_SCALE_MAX
_SC_BC_STRING_MAX
_SC_COLL_WEIGHTS_MAX
_SC_EXPR_NEST_MAX
_SC_LINE_MAX
_SC_RE_DUP_MAX
_SC_2_VERSION
_SC_2_C_BIND
_SC_2_C_DEV
_SC_2_CHAR_TERM
_SC_2_FORT_DEV
_SC_2_FORT_RUN
_SC_2_LOCALEDEF
_SC_2_SW_DEV
_SC_2_UPE
_SC_STREAM_MAX
_SC_TZNAME_MAX
cdef extern from "fcntl.h":
int open(char *, int, ...)
cdef enum open_flags:
O_RDONLY
O_WRONLY
O_RDWR
O_NONBLOCK
O_APPEND
O_CREAT
O_TRUNC
O_EXCL
O_SHLOCK
O_EXLOCK
O_DIRECT
O_FSYNC
O_NOFOLLOW
cdef extern from "signal.h":
ctypedef void (*sig_t)(int)
cdef extern sig_t SIG_DFL
cdef extern sig_t SIG_IGN
cdef extern sig_t SIG_ERR
ctypedef struct sigset_t:
pass
ctypedef struct struct_sigaction "struct sigaction":
sig_t sa_handler
int sa_flags
sigset_t sa_mask
int sigaction(int sig, struct_sigaction *act, struct_sigaction *oact)
int sigprocmask(int how, sigset_t *set, sigset_t *oset)
int sigemptyset(sigset_t *set)
int sigfillset(sigset_t *set)
int sigaddset(sigset_t *set, int signo)
int sigdelset(sigset_t *set, int signo)
int sigismember(sigset_t *set, int signo)
sig_t signal(int sig, sig_t func)
int kill (pid_t pid, int sig)
cdef enum __signals:
SIGHUP
SIGINT
SIGQUIT
SIGILL
SIGTRAP
SIGABRT
SIGIOT
SIGEMT
SIGFPE
SIGKILL
SIGBUS
SIGSEGV
SIGSYS
SIGPIPE
SIGALRM
SIGTERM
SIGURG
SIGSTOP
SIGTSTP
SIGCONT
SIGCHLD
SIGTTIN
SIGTTOU
SIGIO
SIGXCPU
SIGXFSZ
SIGVTALRM
SIGPROF
SIGWINCH
SIGINFO
SIGUSR1
SIGUSR2
SIGTHR
SIGLWP
cdef enum __sigprocmask_flags:
SIG_BLOCK
SIG_UNBLOCK
SIG_SETMASK
cdef extern from "time.h":
cdef struct tm:
int tm_sec
int tm_min
int tm_hour
int tm_mday
int tm_mon
int tm_year
int tm_wday
int tm_yday
int tm_isdst
char *tm_zone
long tm_gmtoff
char * ctime(time_t *clock)
tm * localtime(time_t *clock)
tm * gmtime(time_t *clock)
size_t strftime(char * buf, size_t maxsize, char * format, tm * timeptr)
time_t mktime(tm *)
cdef extern from "sys/time.h":
cdef struct timeval:
time_t tv_sec
suseconds_t tv_usec
cdef struct timezone:
int tz_minuteswest
int dsttime
int gettimeofday(timeval *tp, timezone *tzp)
cdef extern from "sys/resource.h":
cdef struct rusage:
timeval ru_utime
timeval ru_stime
long ru_maxrss
long ru_ixrss
long ru_idrss
long ru_isrss
long ru_minflt
long ru_majflt
long ru_nswap
long ru_inblock
long ru_oublock
long ru_msgsnd
long ru_msgrcv
long ru_nsignals
long ru_nvcsw
long ru_nivcsw
int getpriority(int which, int who)
int setpriority(int which, int who, int prio)
enum PRIO_WHICH:
PRIO_PROCESS
PRIO_PGRP
PRIO_USER
cdef extern from "sys/wait.h":
pid_t wait(int *status)
pid_t waitpid(pid_t wpid, int *status, int options)
pid_t wait3(int *status, int options, rusage *rusage)
pid_t wait4(pid_t wpid, int *status, int options, rusage *rusage)
cdef extern from "limits.h":
# Defining most of these as "int" since Pyrex normally isn't very picky
# about the type, and it's good enough for these values.
int CHAR_BIT
int CHAR_MAX
int INT_MAX
int LONG_BIT
long LONG_MAX
int SCHAR_MAX
int SHRT_MAX
int SSIZE_MAX
int UCHAR_MAX
unsigned int UINT_MAX
unsigned long ULONG_MAX
int USHRT_MAX
int WORD_BIT
int CHAR_MIN
int INT_MIN
long LONG_MIN
int SCHAR_MIN
int SHRT_MIN
# Copyright (c) 2002-2011 IronPort Systems and Cisco Systems
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Pyrex interface file for inline helpers.
# Use the "include" statement to include these functions.
# You must include "python.pxi" before this file.
cdef object oserrors
from coro import oserrors
cimport libc
cdef raise_oserror():
oserrors.map_exception(OSError(libc.errno, libc.strerror(libc.errno)))
cdef raise_oserror_with_errno(int e):
oserrors.map_exception(OSError(e, libc.strerror(e)))
cdef object __builtin__
import __builtin__
cdef object bool
bool = __builtin__.bool
cdef extern from "pyrex_helpers.h":
int va_int(libc.va_list)
char * va_charptr(libc.va_list)
object PySequence_Fast_GET_ITEM_SAFE (object, int)
object PyList_GET_ITEM_SAFE (object, int)
void PyList_SET_ITEM_SAFE (object, int, object)
object PyList_GetItem_SAFE (object, int)
void PyList_SetItem_SAFE (object, int, object)
object PyTuple_GET_ITEM_SAFE (object, int)
void PyTuple_SET_ITEM_SAFE (object, int, object)
object PyTuple_GetItem_SAFE (object, int)
void PyTuple_SetItem_SAFE (object, int, object)
object PyDict_GET_ITEM_SAFE (object, object, object)
void * Pyrex_Malloc_SAFE (libc.size_t) except NULL
void * Pyrex_Realloc_SAFE (void *, libc.size_t) except NULL
void Pyrex_Free_SAFE (void *)
object minimal_ulonglong (unsigned long long)
object minimal_long_long (long long)
object minimal_ulong (unsigned long)
int callable (object) # Cannot fail.
int cmp (object, object) except? -1
object type (object)
int IMAX (int, int)
int IMIN (int, int)
# Copyright (c) 2002-2011 IronPort Systems and Cisco Systems
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# XXX:
# - Need to support "long long" definitions that are different for different platforms.
# - Support unicode platform dependencies.
# - Add unicode calls.
# - Add setobject calls.
cdef extern from "sys/types.h":
ctypedef unsigned int size_t
ctypedef int ssize_t
cdef extern from "stdio.h":
ctypedef struct FILE:
pass
cdef extern from "Python.h":
# XXX: This is platform dependent.
ctypedef unsigned short Py_UNICODE
ctypedef ssize_t Py_ssize_t
ctypedef struct PyTypeObject:
pass
ctypedef struct PyObject:
Py_ssize_t ob_refcnt
PyTypeObject * ob_type
###############################################################################################
# bool
###############################################################################################
PyObject * Py_False
PyObject * Py_True
PyTypeObject PyBool_Type
int PyBool_Check (object) # Always succeeds.
object PyBool_FromLong (long)
###############################################################################################
# buffer
###############################################################################################
PyTypeObject PyBuffer_Type
int Py_END_OF_BUFFER
int PyBuffer_Check (object) # Always succeeds.
object PyBuffer_FromMemory (void *, Py_ssize_t)
object PyBuffer_FromObject (object, Py_ssize_t, Py_ssize_t)
object PyBuffer_FromReadWriteMemory (void *, Py_ssize_t)
object PyBuffer_FromReadWriteObject (object, Py_ssize_t, Py_ssize_t)
object PyBuffer_New (Py_ssize_t)
int PyObject_AsCharBuffer (object, char **, Py_ssize_t *) except -1
int PyObject_AsReadBuffer (object, void **, Py_ssize_t *) except -1
int PyObject_AsWriteBuffer (object, void **, Py_ssize_t *) except -1
int PyObject_CheckReadBuffer (object) # Always succeeds.
###############################################################################################
# cobject
###############################################################################################
PyTypeObject PyCObject_Type
int PyCObject_Check(object) # Always succeeds.
object PyCObject_FromVoidPtr(void *, void (*)(void*))
object PyCObject_FromVoidPtrAndDesc(void *, void *, void (*)(void*,void*))
void * PyCObject_AsVoidPtr(object) except NULL
void * PyCObject_GetDesc(object) except NULL
void * PyCObject_Import(char *, char *) except NULL
###############################################################################################
# compile
###############################################################################################
ctypedef struct PyCodeObject:
int co_argcount
int co_nlocals
int co_stacksize
int co_flags
PyObject *co_code
PyObject *co_consts
PyObject *co_names
PyObject *co_varnames
PyObject *co_freevars
PyObject *co_cellvars
PyObject *co_filename
PyObject *co_name
int co_firstlineno
PyObject *co_lnotab
int PyCode_Addr2Line(PyCodeObject *, int)
###############################################################################################
# complex
###############################################################################################
ctypedef struct Py_complex:
double real
double imag
PyTypeObject PyComplex_Type
Py_complex PyComplex_AsCComplex (object) # Always succeeds.
int PyComplex_Check (object) # Always succeeds.
int PyComplex_CheckExact (object) # Always succeeds.
object PyComplex_FromCComplex (Py_complex)
object PyComplex_FromDoubles (double, double)
double PyComplex_ImagAsDouble (object) except? -1
double PyComplex_RealAsDouble (object) except? -1
Py_complex _Py_c_diff (Py_complex, Py_complex)
Py_complex _Py_c_neg (Py_complex)
Py_complex _Py_c_pow (Py_complex, Py_complex)
Py_complex _Py_c_prod (Py_complex, Py_complex)
Py_complex _Py_c_quot (Py_complex, Py_complex)
Py_complex _Py_c_sum (Py_complex, Py_complex)
###############################################################################################
# dict
###############################################################################################
PyTypeObject PyDict_Type
int PyDict_Check (object) # Always succeeds.
int PyDict_CheckExact (object) # Always succeeds.
void PyDict_Clear (object)
int PyDict_Contains (object, object) except -1
object PyDict_Copy (object)
int PyDict_DelItem (object, object) except -1
int PyDict_DelItemString (object, char *) except -1
object PyDict_Items (object)
object PyDict_Keys (object)
int PyDict_Merge (object, object, int) except -1
int PyDict_MergeFromSeq2 (object, object, int) except -1
object PyDict_New ()
# XXX: Pyrex doesn't support pointer to a python object?
#int PyDict_Next (object, Py_ssize_t *, object *, object *) # Always succeeds.
int PyDict_SetItem (object, object, object) except -1
int PyDict_SetItemString (object, char *, object) except -1
Py_ssize_t PyDict_Size (object) except -1
int PyDict_Update (object, object) except -1
object PyDict_Values (object)
# XXX: Borrowed reference. No exception on NULL.
#object PyDict_GetItem (object, object)
# XXX: Borrowed reference. No exception on NULL
#object PyDict_GetItemString (object, char *)
###############################################################################################
# float
###############################################################################################
PyTypeObject PyFloat_Type
int _PyFloat_Pack4 (double, unsigned char *, int) except -1
int _PyFloat_Pack8 (double, unsigned char *, int) except -1
double _PyFloat_Unpack4 (unsigned char *, int) except? -1
double _PyFloat_Unpack8 (unsigned char *, int) except? -1
double PyFloat_AS_DOUBLE (object)
double PyFloat_AsDouble (object) except? -1
void PyFloat_AsReprString (char*, object)
void PyFloat_AsString (char*, object)
int PyFloat_Check (object) # Always succeeds.
int PyFloat_CheckExact (object) # Always succeeds.
object PyFloat_FromDouble (double)
object PyFloat_FromString (object, char**)
###############################################################################################
# frame
###############################################################################################
ctypedef struct PyFrameObject:
PyFrameObject *f_back
PyCodeObject *f_code
PyObject *f_builtins
PyObject *f_globals
PyObject *f_locals
PyObject *f_trace
PyObject *f_exc_type
PyObject *f_exc_value
PyObject *f_exc_traceback
int f_lasti
int f_lineno
int f_restricted
int f_iblock
int f_nlocals
int f_ncells
int f_nfreevars
int f_stacksize
###############################################################################################
# int
###############################################################################################
PyTypeObject PyInt_Type
long PyInt_AS_LONG (object) # Always succeeds.
long PyInt_AsLong (object) except? -1
Py_ssize_t PyInt_AsSsize_t (object) except? -1
unsigned long long PyInt_AsUnsignedLongLongMask (object) except? -1
unsigned long PyInt_AsUnsignedLongMask (object) except? -1
int PyInt_Check (object) # Always succeeds.
int PyInt_CheckExact (object) # Always succeeds.
object PyInt_FromLong (long)
object PyInt_FromSsize_t (Py_ssize_t)
object PyInt_FromString (char*, char**, int)
object PyInt_FromUnicode (Py_UNICODE*, Py_ssize_t, int)
long PyInt_GetMax () # Always succeeds.
###############################################################################################
# import
###############################################################################################
object PyImport_ImportModule(char *name)
object PyImport_ImportModuleNoBlock(char *name)
object PyImport_ImportModuleEx(char *name, object globals, object locals, object fromlist)
object PyImport_ImportModuleLevel(char *name, object globals, object locals, object fromlist, int level)
object PyImport_Import(object name)
object PyImport_ReloadModule(object m)
object PyImport_AddModule(char *name)
object PyImport_ExecCodeModule(char *name, object co)
long PyImport_GetMagicNumber()
object PyImport_GetModuleDict()
object PyImport_GetImporter(object path)
###############################################################################################
# iterator
###############################################################################################
int PyIter_Check (object) # Always succeeds.
object PyIter_Next (object)
###############################################################################################
# list
###############################################################################################
PyTypeObject PyList_Type
int PyList_Append (object, object) except -1
object PyList_AsTuple (object)
int PyList_Check (object) # Always succeeds.
int PyList_CheckExact (object) # Always succeeds.
int PyList_GET_SIZE (object) # Always suceeds.
object PyList_GetSlice (object, Py_ssize_t, Py_ssize_t)
int PyList_Insert (object, Py_ssize_t, object) except -1
object PyList_New (Py_ssize_t)
int PyList_Reverse (object) except -1
int PyList_SetSlice (object, Py_ssize_t, Py_ssize_t, object) except -1
Py_ssize_t PyList_Size (object) except -1
int PyList_Sort (object) except -1
###############################################################################################
# long
###############################################################################################
PyTypeObject PyLong_Type
int _PyLong_AsByteArray (object, unsigned char *, size_t, int, int) except -1
object _PyLong_FromByteArray (unsigned char *, size_t, int, int)
size_t _PyLong_NumBits (object) except -1
int _PyLong_Sign (object) # No error.
long PyLong_AsLong (object) except? -1
long long PyLong_AsLongLong (object) except? -1
unsigned long PyLong_AsUnsignedLong (object) except? -1
unsigned long PyLong_AsUnsignedLongMask (object) except? -1
unsigned long long PyLong_AsUnsignedLongLong (object) except? -1
unsigned long long PyLong_AsUnsignedLongLongMask (object) except? -1
int PyLong_Check (object) # Always succeeds.
int PyLong_CheckExact (object) # Always succeeds.
object PyLong_FromDouble (double)
object PyLong_FromLong (long)
object PyLong_FromLongLong (long long)
object PyLong_FromUnsignedLong (unsigned long)
object PyLong_FromUnsignedLongLong (unsigned long long)
double PyLong_AsDouble (object) except? -1
object PyLong_FromVoidPtr (void *)
void * PyLong_AsVoidPtr (object) except NULL
object PyLong_FromString (char *, char **, int)
object PyLong_FromUnicode (Py_UNICODE*, Py_ssize_t, int)
###############################################################################################
# mapping
###############################################################################################
int PyMapping_Check (object) # Always succeeds.
int PyMapping_DelItem (object, object) except -1
int PyMapping_DelItemString (object, char *) except -1
object PyMapping_GetItemString (object, char *)
int PyMapping_HasKey (object, object) # Always succeeds.
int PyMapping_HasKeyString (object, char *) # Always succeeds.
object PyMapping_Items (object)
object PyMapping_Keys (object)
Py_ssize_t PyMapping_Length (object) except -1
int PyMapping_SetItemString (object, char *, object) except -1
Py_ssize_t PyMapping_Size (object) except -1
object PyMapping_Values (object)
###############################################################################################
# mem
###############################################################################################
void PyMem_Free (void * p)
void * PyMem_Malloc (size_t n)
void * PyMem_Realloc (void *, size_t)
###############################################################################################
# modsupport
###############################################################################################
object Py_BuildValue (char *, ...)
object Py_VaBuildValue (char *, va_list)
###############################################################################################
# number
###############################################################################################
object PyNumber_Absolute (object)
object PyNumber_Add (object, object)
object PyNumber_And (object, object)
Py_ssize_t PyNumber_AsSsize_t (object, object) except? -1
int PyNumber_Check (object) # Always succeeds.
# XXX: Pyrex doesn't support pointer to python object?
#int PyNumber_Coerce (object*, object*) except -1
object PyNumber_Divide (object, object)
object PyNumber_Divmod (object, object)
object PyNumber_Float (object)
object PyNumber_FloorDivide (object, object)
object PyNumber_InPlaceAdd (object, object)
object PyNumber_InPlaceAnd (object, object)
object PyNumber_InPlaceDivide (object, object)
object PyNumber_InPlaceFloorDivide (object, object)
object PyNumber_InPlaceLshift (object, object)
object PyNumber_InPlaceMultiply (object, object)
object PyNumber_InPlaceOr (object, object)
object PyNumber_InPlacePower (object, object, object)
object PyNumber_InPlaceRemainder (object, object)
object PyNumber_InPlaceRshift (object, object)
object PyNumber_InPlaceSubtract (object, object)
object PyNumber_InPlaceTrueDivide (object, object)
object PyNumber_InPlaceXor (object, object)
object PyNumber_Int (object)
object PyNumber_Invert (object)
object PyNumber_Long (object)
object PyNumber_Lshift (object, object)
object PyNumber_Multiply (object, object)
object PyNumber_Negative (object)
object PyNumber_Or (object, object)
object PyNumber_Positive (object)
object PyNumber_Power (object, object, object)
object PyNumber_Remainder (object, object)
object PyNumber_Rshift (object, object)
object PyNumber_Subtract (object, object)
object PyNumber_TrueDivide (object, object)
object PyNumber_Xor (object, object)
###############################################################################################
# object
###############################################################################################
int PyCallable_Check (object) # Always succeeds.
int PyObject_AsFileDescriptor (object) except -1
object PyObject_Call (object, object, object)
object PyObject_CallFunction (object, char *, ...)
object PyObject_CallFunctionObjArgs (object, ...)
object PyObject_CallMethod (object, char *, char *, ...)
object PyObject_CallMethodObjArgs (object, object, ...)
object PyObject_CallObject (object, object)
int PyObject_Cmp (object, object, int *result) except -1
# Use PyObject_Cmp instead.
#int PyObject_Compare (object, object)
int PyObject_DelAttr (object, object) except -1
int PyObject_DelAttrString (object, char *) except -1
int PyObject_DelItem (object, object) except -1
int PyObject_DelItemString (object, char *) except -1
object PyObject_Dir (object)
object PyObject_GetAttr (object, object)
object PyObject_GetAttrString (object, char *)
object PyObject_GetItem (object, object)
object PyObject_GetIter (object)
int PyObject_HasAttr (object, object) # Always succeeds.
int PyObject_HasAttrString (object, char *) # Always succeeds.
long PyObject_Hash (object) except -1
int PyObject_IsInstance (object, object) except -1
int PyObject_IsSubclass (object, object) except -1
int PyObject_IsTrue (object) except -1
Py_ssize_t PyObject_Length (object) except -1
int PyObject_Not (object) except -1
int PyObject_Print (object, FILE *, int) except -1
object PyObject_Repr (object)
object PyObject_RichCompare (object, object, int)
int PyObject_RichCompareBool (object, object, int) except -1
int PyObject_SetAttr (object, object, object) except -1
int PyObject_SetAttrString (object, char *, object) except -1
int PyObject_SetItem (object, object, object) except -1
Py_ssize_t PyObject_Size (object) except -1
object PyObject_Str (object)
object PyObject_Type (object)
int PyObject_TypeCheck (object, object) # Always succeeds.
object PyObject_Unicode (object)
###############################################################################################
# pyerrors
###############################################################################################
int PyErr_BadArgument ()
void PyErr_BadInternalCall ()
int PyErr_CheckSignals ()
void PyErr_Clear ()
int PyErr_ExceptionMatches (object)
object PyErr_Format (object, char *, ...)
int PyErr_GivenExceptionMatches (object, object)
object PyErr_NoMemory ()
object PyErr_Occurred ()
void PyErr_Restore (object, object, object)
object PyErr_SetFromErrno (object)
object PyErr_SetFromErrnoWithFilename (object, char *)
object PyErr_SetFromErrnoWithFilenameObject (object, object)
void PyErr_SetInterrupt ()
void PyErr_SetNone (object)
void PyErr_SetObject (object, object)
void PyErr_SetString (object, char *)
int PyErr_Warn (object, char *)
int PyErr_WarnExplicit (object, char *, char *, int, char *, object)
void PyErr_WriteUnraisable (object)
###############################################################################################
# pyeval
# Be extremely careful with these functions.
###############################################################################################
ctypedef struct PyThreadState:
PyFrameObject * frame
int recursion_depth
void * curexc_type, * curexc_value, * curexc_traceback
void * exc_type, * exc_value, * exc_traceback
void PyEval_AcquireLock ()
void PyEval_ReleaseLock ()
void PyEval_AcquireThread (PyThreadState *)
void PyEval_ReleaseThread (PyThreadState *)
PyThreadState* PyEval_SaveThread ()
void PyEval_RestoreThread (PyThreadState *)
###############################################################################################
# pystate
# Be extremely careful with these functions. Read PEP 311 for more detail.
###############################################################################################
ctypedef int PyGILState_STATE
PyGILState_STATE PyGILState_Ensure ()
void PyGILState_Release (PyGILState_STATE)
ctypedef struct PyInterpreterState:
pass
PyThreadState* PyThreadState_New (PyInterpreterState *)
void PyThreadState_Clear (PyThreadState *)
void PyThreadState_Delete (PyThreadState *)
PyThreadState* PyThreadState_Get ()
PyThreadState* PyThreadState_Swap (PyThreadState *tstate)
# XXX: Borrowed reference.
#object PyThreadState_GetDict ()
###############################################################################################
# run
# Functions for embedded interpreters are not included.
###############################################################################################
ctypedef struct PyCompilerFlags:
int cf_flags
ctypedef struct _node:
pass
ctypedef void (*PyOS_sighandler_t)(int)
void PyErr_Display (object, object, object)
void PyErr_Print ()
void PyErr_PrintEx (int)
char * PyOS_Readline (FILE *, FILE *, char *)
PyOS_sighandler_t PyOS_getsig (int)
PyOS_sighandler_t PyOS_setsig (int, PyOS_sighandler_t)
_node * PyParser_SimpleParseFile (FILE *, char *, int) except NULL
_node * PyParser_SimpleParseFileFlags (FILE *, char *, int,
int) except NULL
_node * PyParser_SimpleParseString (char *, int) except NULL
_node * PyParser_SimpleParseStringFlagsFilename(char *, char *,
int, int) except NULL
_node * PyParser_SimpleParseStringFlags (char *, int, int) except NULL
int PyRun_AnyFile (FILE *, char *) except -1
int PyRun_AnyFileEx (FILE *, char *, int) except -1
int PyRun_AnyFileExFlags (FILE *, char *, int,
PyCompilerFlags *) except -1
int PyRun_AnyFileFlags (FILE *, char *,
PyCompilerFlags *) except -1
object PyRun_File (FILE *, char *, int,
object, object)
object PyRun_FileEx (FILE *, char *, int,
object, object, int)
object PyRun_FileExFlags (FILE *, char *, int,
object, object, int,
PyCompilerFlags *)
object PyRun_FileFlags (FILE *, char *, int,
object, object,
PyCompilerFlags *)
int PyRun_InteractiveLoop (FILE *, char *) except -1
int PyRun_InteractiveLoopFlags (FILE *, char *,
PyCompilerFlags *) except -1
int PyRun_InteractiveOne (FILE *, char *) except -1
int PyRun_InteractiveOneFlags (FILE *, char *,
PyCompilerFlags *) except -1
int PyRun_SimpleFile (FILE *, char *) except -1
int PyRun_SimpleFileEx (FILE *, char *, int) except -1
int PyRun_SimpleFileExFlags (FILE *, char *, int,
PyCompilerFlags *) except -1
int PyRun_SimpleString (char *) except -1
int PyRun_SimpleStringFlags (char *, PyCompilerFlags *) except -1
object PyRun_String (char *, int, object,
object)
object PyRun_StringFlags (char *, int, object,
object, PyCompilerFlags *)
int Py_AtExit (void (*func)())
object Py_CompileString (char *, char *, int)
object Py_CompileStringFlags (char *, char *, int, PyCompilerFlags *)
void Py_Exit (int)
int Py_FdIsInteractive (FILE *, char *) # Always succeeds.
char * Py_GetBuildInfo ()
char * Py_GetCompiler ()
char * Py_GetCopyright ()
char * Py_GetExecPrefix ()
char * Py_GetPath ()
char * Py_GetPlatform ()
char * Py_GetPrefix ()
char * Py_GetProgramFullPath ()
char * Py_GetProgramName ()
char * Py_GetPythonHome ()
char * Py_GetVersion ()
###############################################################################################
# sequence
###############################################################################################
int PySequence_Check (object) # Always succeeds.
object PySequence_Concat (object, object)
int PySequence_Contains (object, object) except -1
Py_ssize_t PySequence_Count (object, object) except -1
int PySequence_DelItem (object, Py_ssize_t) except -1
int PySequence_DelSlice (object, Py_ssize_t, Py_ssize_t) except -1
object PySequence_Fast (object, char *)
int PySequence_Fast_GET_SIZE (object)
object PySequence_GetItem (object, Py_ssize_t)
object PySequence_GetSlice (object, Py_ssize_t, Py_ssize_t)
object PySequence_ITEM (object, int)
int PySequence_In (object, object) except -1
object PySequence_InPlaceConcat (object, object)
object PySequence_InPlaceRepeat (object, Py_ssize_t)
Py_ssize_t PySequence_Index (object, object) except -1
Py_ssize_t PySequence_Length (object) except -1
object PySequence_List (object)
object PySequence_Repeat (object, Py_ssize_t)
int PySequence_SetItem (object, Py_ssize_t, object) except -1
int PySequence_SetSlice (object, Py_ssize_t, Py_ssize_t, object) except -1
Py_ssize_t PySequence_Size (object) except -1
object PySequence_Tuple (object)
###############################################################################################
# string
###############################################################################################
PyTypeObject PyString_Type
# Pyrex cannot support resizing because you have no choice but to use
# realloc which may call free() on the object, and there's no way to tell
# Pyrex to "forget" reference counting for the object.
#int _PyString_Resize (object *, Py_ssize_t) except -1
char * PyString_AS_STRING (object) # Always succeeds.
object PyString_AsDecodedObject (object, char *, char *)
object PyString_AsEncodedObject (object, char *, char *)
object PyString_AsEncodedString (object, char *, char *)
char * PyString_AsString (object) except NULL
int PyString_AsStringAndSize (object, char **, Py_ssize_t *) except -1
int PyString_Check (object) # Always succeeds.
int PyString_CHECK_INTERNED (object) # Always succeeds.
int PyString_CheckExact (object) # Always succeeds.
# XXX: Pyrex doesn't support pointer to a python object?
#void PyString_Concat (object *, object)
# XXX: Pyrex doesn't support pointer to a python object?
#void PyString_ConcatAndDel (object *, object)
object PyString_Decode (char *, int, char *, char *)
object PyString_DecodeEscape (char *, int, char *, int, char *)
object PyString_Encode (char *, int, char *, char *)
object PyString_Format (object, object)
object PyString_FromFormat (char*, ...)
object PyString_FromFormatV (char*, va_list)
object PyString_FromString (char *)
object PyString_FromStringAndSize (char *, Py_ssize_t)
Py_ssize_t PyString_GET_SIZE (object) # Always succeeds.
object PyString_InternFromString (char *)
# XXX: Pyrex doesn't support pointer to a python object?
#void PyString_InternImmortal (object*)
# XXX: Pyrex doesn't support pointer to a python object?
#void PyString_InternInPlace (object*)
object PyString_Repr (object, int)
Py_ssize_t PyString_Size (object) except -1
# Disgusting hack to access internal object values.
ctypedef struct PyStringObject:
int ob_refcnt
PyTypeObject * ob_type
int ob_size
long ob_shash
int ob_sstate
char * ob_sval
###############################################################################################
# tuple
###############################################################################################
PyTypeObject PyTuple_Type
# See PyString_Resize note about resizing.
#int _PyTuple_Resize (object*, Py_ssize_t) except -1
int PyTuple_Check (object) # Always succeeds.
int PyTuple_CheckExact (object) # Always succeeds.
Py_ssize_t PyTuple_GET_SIZE (object) # Always succeeds.
object PyTuple_GetSlice (object, Py_ssize_t, Py_ssize_t)
object PyTuple_New (Py_ssize_t)
object PyTuple_Pack (Py_ssize_t, ...)
Py_ssize_t PyTuple_Size (object) except -1
###############################################################################################
# Dangerous things!
# Do not use these unless you really, really know what you are doing.
###############################################################################################
void Py_INCREF (object)
void Py_XINCREF (object)
void Py_DECREF (object)
void Py_XDECREF (object)
void Py_CLEAR (object)
# XXX: Stolen reference.
void PyTuple_SET_ITEM (object, Py_ssize_t, value)
# XXX: Borrowed reference.
object PyTuple_GET_ITEM (object, Py_ssize_t)
# XXX: Borrowed reference.
object PyTuple_GetItem (object, Py_ssize_t)
# XXX: Stolen reference.
int PyTuple_SetItem (object, Py_ssize_t, object) except -1
# XXX: Steals reference.
int PyList_SetItem (object, Py_ssize_t, object) except -1
# XXX: Borrowed reference
object PyList_GetItem (object, Py_ssize_t)
# XXX: Borrowed reference, no NULL on error.
object PyList_GET_ITEM (object, Py_ssize_t)
# XXX: Stolen reference.
void PyList_SET_ITEM (object, Py_ssize_t, object)
# XXX: Borrowed reference.
object PySequence_Fast_GET_ITEM (object, Py_ssize_t)
# First parameter _must_ be a PyStringObject.
object _PyString_Join (object, object)
# Copyright (c) 2002-2011 IronPort Systems and Cisco Systems
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# This include file makes it possible to directly access the C functions from
# the tsc_time module. To use it, you need to put this at the top of your
# Pyrex file:
#
# cimport libc
# include "python.pxi"
# include "tsc_time_include.pyx"
#
# This will also implicitly cimport the tsc_time module so that you can have
# direct access to the type objects. This allows you to do something like this:
#
# cdef tsc_time.TSC t
# t = now_tsc()
# print t.tsc
#
# This will allow direct C access to the member variables of the Time objects.
cimport coro.clocks.tsc_time as tsc_time
cdef extern from "tsc_time.h":
# Raw conversion functions.
libc.int64_t c_usec_to_ticks "usec_to_ticks" (libc.int64_t)
libc.int64_t c_ticks_to_usec "ticks_to_usec" (libc.int64_t)
libc.int64_t c_sec_to_ticks "sec_to_ticks" (libc.int64_t)
libc.int64_t c_ticks_to_sec "ticks_to_sec" (libc.int64_t)
double c_ticks_to_fsec "ticks_to_fsec" (libc.int64_t)
libc.int64_t c_fsec_to_ticks "fsec_to_ticks" (double)
void c_update_time_relation "update_time_relation" ()
libc.int64_t c_rdtsc "rdtsc" ()
# Constructors.
tsc_time.TSC now_tsc()
tsc_time.Posix now_posix_sec()
tsc_time.uPosix now_posix_usec()
tsc_time.fPosix now_posix_fsec()
int init_tsc_time_pointers() except -1
init_tsc_time_pointers()
...@@ -11,10 +11,7 @@ from Cython.Distutils.extension import Extension ...@@ -11,10 +11,7 @@ from Cython.Distutils.extension import Extension
import glob import glob
import os import os
if os.getenv('IPROOT'): include_dir = os.getcwd()
include_dir = os.path.join( os.getenv('IPROOT'), 'ap', 'aplib')
else:
include_dir = os.path.join( os.getcwd(), '..', 'aplib')
def newer(x, y): def newer(x, y):
x_mtime = os.path.getmtime(x) x_mtime = os.path.getmtime(x)
...@@ -65,13 +62,32 @@ setup ( ...@@ -65,13 +62,32 @@ setup (
os.path.join(include_dir, 'pyrex', 'libc.pxd'), os.path.join(include_dir, 'pyrex', 'libc.pxd'),
] ]
), ),
pyrex_include_dirs=[os.path.join(include_dir, 'pyrex')], pyrex_include_dirs=[
os.path.join(include_dir, '.'),
os.path.join(include_dir, 'pyrex'),
],
#include_dirs=[os.path.join(include_dir, 'pyrex')], #include_dirs=[os.path.join(include_dir, 'pyrex')],
include_dirs=[os.path.join(include_dir, 'include')], include_dirs=[
os.path.join(include_dir, '.'),
os.path.join(include_dir, 'include'),
],
#pyrex_compile_time_env={'COMPILE_LIO': check_lio(), #pyrex_compile_time_env={'COMPILE_LIO': check_lio(),
# 'CORO_DEBUG': True, # 'CORO_DEBUG': True,
# }, # },
), ),
Extension(
'coro.oserrors',
['coro/oserrors.pyx', ],
),
Extension(
'coro.clocks.tsc_time',
['coro/clocks/tsc_time.pyx', ],
pyrex_include_dirs=[os.path.join(include_dir, 'pyrex')],
include_dirs=[
os.path.join(include_dir, '.'),
os.path.join(include_dir, 'include'),
],
),
], ],
#packages=find_packages(), #packages=find_packages(),
packages=['coro'], packages=['coro'],
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
""" """
from aplib import oserrors from coro import oserrors
import coro import coro
import coro_unittest import coro_unittest
import os import os
......
...@@ -6,7 +6,7 @@ import coro ...@@ -6,7 +6,7 @@ import coro
import coro_unittest import coro_unittest
import os import os
import unittest import unittest
from aplib import oserrors from coro import oserrors
class ForceSend(coro.Interrupted): class ForceSend(coro.Interrupted):
pass pass
......
# Copyright (c) 2002-2011 IronPort Systems and Cisco Systems
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Unittests for the tsc_time module."""
__version__ = '$Revision: #2 $'
import struct
#import sysctl
import time
import unittest
from coro.clocks import tsc_time
class Test(unittest.TestCase):
# Stub test until we have a working sysctl
#def test_ticks_per_sec(self):
# freq = struct.unpack('I', sysctl.sysctl('machdep.tsc_freq'))[0]
# self.assertEqual(freq,
# tsc_time.ticks_per_sec
# )
# self.assertEqual(freq / 1000000,
# tsc_time.ticks_per_usec
# )
def _assert_close(self, a, b, diff):
low = a - diff
high = a + diff
self.assert_(low <= b <= high, '%r %r ~ %r' % (a, b, diff))
def test_raw_conversion(self):
now_t = tsc_time.now_tsc().tsc
now_up = tsc_time.get_kernel_usec()
now_p = now_up / 1000000
now_fp = float(now_up) / 1000000
# Conversion looses some accuracy.
ticks_close = (tsc_time.ticks_per_sec / 10.0)
p_close = 0
up_close = 100000
fp_close = 0.1
self._assert_close(now_t,
tsc_time.usec_to_ticks(now_up),
ticks_close
)
self._assert_close(now_up,
tsc_time.ticks_to_usec(now_t),
up_close
)
self._assert_close(now_t,
tsc_time.usec_to_ticks_safe(now_up),
ticks_close
)
self._assert_close(now_up,
tsc_time.ticks_to_usec_safe(now_t),
up_close
)
self._assert_close(now_t,
tsc_time.sec_to_ticks(now_p),
tsc_time.ticks_per_sec
)
self._assert_close(now_p,
tsc_time.ticks_to_sec(now_t),
p_close
)
self._assert_close(now_fp,
tsc_time.ticks_to_fsec(now_t),
fp_close
)
self._assert_close(now_t,
tsc_time.fsec_to_ticks(now_fp),
ticks_close
)
def test_time_methods(self):
t = tsc_time.now_tsc()
now_up = tsc_time.get_kernel_usec()
now_fp = float(now_up) / 1000000
self.assertEqual(time.ctime(now_fp), t.ctime())
self.assertEqual(time.localtime(now_fp), t.localtime())
self.assertEqual(time.gmtime(now_fp), t.gmtime())
self.assertEqual(time.strftime('%a %b %d %H:%M:%S %Y', time.localtime(now_fp)),
t.mkstr_local('%a %b %d %H:%M:%S %Y'))
self.assertEqual(time.strftime('%a %b %d %H:%M:%S %Y', time.gmtime(now_fp)),
t.mkstr_utc('%a %b %d %H:%M:%S %Y'))
def test_comparison(self):
t = tsc_time.now_tsc()
t2 = tsc_time.now_tsc()
self.assert_(t2 > t)
self.assert_(t < t2)
self.assert_(t.tsc + 1 > t)
self.assert_(t.tsc - 1 < t)
self.assert_(t.tsc + 1L > t)
self.assert_(t.tsc - 1L < t)
# Floating point uses larger numbers because of a loss in precision
# when converting to floating point, ex:
# >>> float(28536304964998994L)
# 28536304964998992.0
self.assert_(t.tsc + 1000.0 > t)
self.assert_(t.tsc - 1000.0 < t)
t = tsc_time.now_posix_sec()
time.sleep(2)
t2 = tsc_time.now_posix_sec()
self.assert_(t2 > t)
self.assert_(t < t2)
self.assert_(int(t) + 1 > t)
self.assert_(int(t) - 1 < t)
self.assert_(int(t) + 1L > t)
self.assert_(int(t) - 1L < t)
self.assert_(int(t) + 1.0 > t)
self.assert_(int(t) - 1.0 < t)
t = tsc_time.now_posix_usec()
time.sleep(0.1)
t2 = tsc_time.now_posix_usec()
self.assert_(t2 > t)
self.assert_(t < t2)
self.assert_(int(t) + 1 > t)
self.assert_(int(t) - 1 < t)
self.assert_(int(t) + 1L > t)
self.assert_(int(t) - 1L < t)
self.assert_(int(t) + 1.0 > t)
self.assert_(int(t) - 1.0 < t)
t = tsc_time.now_posix_fsec()
time.sleep(0.1)
t2 = tsc_time.now_posix_fsec()
self.assert_(t2 > t)
self.assert_(t < t2)
self.assert_(int(t) + 1 > t)
self.assert_(int(t) - 1 < t)
self.assert_(int(t) + 1L > t)
self.assert_(int(t) - 1L < t)
self.assert_(int(t) + 1.0 > t)
self.assert_(int(t) - 1.0 < t)
def test_math(self):
t = tsc_time.now_tsc()
self.assertEqual(t + 1, t.tsc + 1)
self.assertEqual(t - 1, t.tsc - 1)
self.assertEqual(t + 1L, t.tsc + 1)
self.assertEqual(t - 1L, t.tsc - 1)
# Removing floating point comparison because large floating point
# numbers loose precision, ex:
# >>> float(28536304964998994L)
# 28536304964998992.0
#self.assertEqual(t + 1.0, t.tsc + 1)
#self.assertEqual(t - 1.0, t.tsc - 1)
self.assertRaises(TypeError, lambda: t + 'hi')
self.assertRaises(TypeError, lambda: t - 'hi')
t = tsc_time.now_posix_sec()
self.assertEqual(t + 1, t.as_posix_sec() + 1)
self.assertEqual(t - 1, t.as_posix_sec() - 1)
self.assertEqual(t + 1L, t.as_posix_sec() + 1)
self.assertEqual(t - 1L, t.as_posix_sec() - 1)
self.assertEqual(t + 1.0, t.as_posix_sec() + 1)
self.assertEqual(t - 1.0, t.as_posix_sec() - 1)
self.assertRaises(TypeError, lambda: t + 'hi')
self.assertRaises(TypeError, lambda: t - 'hi')
t = tsc_time.now_posix_usec()
self.assertEqual(t + 1, t.as_posix_usec() + 1)
self.assertEqual(t - 1, t.as_posix_usec() - 1)
self.assertEqual(t + 1L, t.as_posix_usec() + 1)
self.assertEqual(t - 1L, t.as_posix_usec() - 1)
self.assertEqual(t + 1.0, t.as_posix_usec() + 1)
self.assertEqual(t - 1.0, t.as_posix_usec() - 1)
self.assertRaises(TypeError, lambda: t + 'hi')
self.assertRaises(TypeError, lambda: t - 'hi')
t = tsc_time.now_posix_fsec()
# We lose some precision with double conversions done in C versus
# Python's conversions.
self._assert_close(t + 1, t.as_posix_fsec() + 1, 0.001)
self._assert_close(t - 1, t.as_posix_fsec() - 1, 0.001)
self._assert_close(t + 1L, t.as_posix_fsec() + 1, 0.001)
self._assert_close(t - 1L, t.as_posix_fsec() - 1, 0.001)
self._assert_close(t + 1.0, t.as_posix_fsec() + 1, 0.001)
self._assert_close(t - 1.0, t.as_posix_fsec() - 1, 0.001)
self.assertRaises(TypeError, lambda: t + 'hi')
self.assertRaises(TypeError, lambda: t - 'hi')
def test_types(self):
t = tsc_time.now_tsc()
self.assertEqual(int(t), t.tsc)
self.assertEqual(long(t), t.tsc)
self.assertEqual(float(t), float(t.tsc))
t = tsc_time.now_posix_sec()
self.assertEqual(int(t), t.as_posix_sec())
self.assertEqual(long(t), t.as_posix_sec())
self.assertEqual(float(t), float(t.as_posix_sec()))
t = tsc_time.now_posix_usec()
self.assertEqual(int(t), t.as_posix_usec())
self.assertEqual(long(t), t.as_posix_usec())
self.assertEqual(float(t), float(t.as_posix_usec()))
t = tsc_time.now_posix_fsec()
self.assertEqual(int(t), t.as_posix_sec())
self.assertEqual(long(t), t.as_posix_sec())
self.assertEqual(float(t), t.as_posix_fsec())
def test_mktime(self):
for mktime_type in (tsc_time.mktime_tsc,
tsc_time.mktime_posix_sec,
tsc_time.mktime_posix_usec,
tsc_time.mktime_posix_fsec):
tt = time.localtime()
t = mktime_type(tt)
self.assertEqual(t.localtime(), tt)
def test_from(self):
now_tsc = tsc_time.now_tsc()
self.assertEqual(now_tsc.tsc,
tsc_time.TSC_from_ticks(now_tsc.tsc).tsc)
self.assertEqual(tsc_time.sec_to_ticks(now_tsc.as_posix_sec()),
tsc_time.TSC_from_posix_sec(now_tsc.as_posix_sec()).tsc)
self.assertEqual(tsc_time.usec_to_ticks(now_tsc.as_posix_usec()),
tsc_time.TSC_from_posix_usec(now_tsc.as_posix_usec()).tsc)
self.assertEqual(tsc_time.fsec_to_ticks(now_tsc.as_posix_fsec()),
tsc_time.TSC_from_posix_fsec(now_tsc.as_posix_fsec()).tsc)
self.assertEqual(now_tsc.tsc,
tsc_time.Posix_from_ticks(now_tsc.tsc).tsc)
self.assertEqual(tsc_time.sec_to_ticks(now_tsc.as_posix_sec()),
tsc_time.Posix_from_posix_sec(now_tsc.as_posix_sec()).tsc)
self.assertEqual(tsc_time.usec_to_ticks(now_tsc.as_posix_usec()),
tsc_time.Posix_from_posix_usec(now_tsc.as_posix_usec()).tsc)
self.assertEqual(tsc_time.fsec_to_ticks(now_tsc.as_posix_fsec()),
tsc_time.Posix_from_posix_fsec(now_tsc.as_posix_fsec()).tsc)
self.assertEqual(now_tsc.tsc,
tsc_time.uPosix_from_ticks(now_tsc.tsc).tsc)
self.assertEqual(tsc_time.sec_to_ticks(now_tsc.as_posix_sec()),
tsc_time.uPosix_from_posix_sec(now_tsc.as_posix_sec()).tsc)
self.assertEqual(tsc_time.usec_to_ticks(now_tsc.as_posix_usec()),
tsc_time.uPosix_from_posix_usec(now_tsc.as_posix_usec()).tsc)
self.assertEqual(tsc_time.fsec_to_ticks(now_tsc.as_posix_fsec()),
tsc_time.uPosix_from_posix_fsec(now_tsc.as_posix_fsec()).tsc)
self.assertEqual(now_tsc.tsc,
tsc_time.fPosix_from_ticks(now_tsc.tsc).tsc)
self.assertEqual(tsc_time.sec_to_ticks(now_tsc.as_posix_sec()),
tsc_time.fPosix_from_posix_sec(now_tsc.as_posix_sec()).tsc)
self.assertEqual(tsc_time.usec_to_ticks(now_tsc.as_posix_usec()),
tsc_time.fPosix_from_posix_usec(now_tsc.as_posix_usec()).tsc)
self.assertEqual(tsc_time.fsec_to_ticks(now_tsc.as_posix_fsec()),
tsc_time.fPosix_from_posix_fsec(now_tsc.as_posix_fsec()).tsc)
def test_negative_time(self):
now_tsc = tsc_time.now_tsc()
diff = 10 * 60 * tsc_time.ticks_per_sec
ago = now_tsc - diff
self._assert_close(ago.as_posix_sec(),
now_tsc.as_posix_sec() - 10 * 60,
1
)
self._assert_close(ago.as_posix_usec(),
now_tsc.as_posix_usec() - 10 * 60 * 1000000,
1000000
)
self._assert_close(ago.as_posix_fsec(),
now_tsc.as_posix_fsec() - 10 * 60,
0.3
)
# Microseconds in 1 year.
diff = long(365 * 24 * 60 * 60 * 1000000)
now_usec = tsc_time.now_posix_usec()
ago = now_usec - diff
self._assert_close(now_usec.as_posix_usec() - diff,
ago.as_posix_usec(),
10
)
year_ago = now_usec.as_posix_usec() - diff
year_ago_tsc = tsc_time.TSC_from_posix_usec(year_ago)
self._assert_close(year_ago_tsc.as_posix_usec(),
year_ago,
10
)
if __name__ == '__main__':
unittest.main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment