Skip to content

Commit

Permalink
feat: add cython monotonic_time_coarse implementation (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco authored Dec 1, 2023
1 parent 29a6ee2 commit ae3abb8
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 1 deletion.
10 changes: 9 additions & 1 deletion build_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
language="c",
)

time_module = Extension(
"bluetooth_data_tools._time_impl",
[
join("src", "bluetooth_data_tools", "_time_impl.pyx"),
],
language="c",
)


class BuildExt(build_ext):
def build_extensions(self) -> None:
Expand All @@ -36,7 +44,7 @@ def build(setup_kwargs: Any) -> None:
setup_kwargs.update(
dict(
ext_modules=cythonize(
[utils_module, "src/bluetooth_data_tools/gap.py"],
[time_module, utils_module, "src/bluetooth_data_tools/gap.py"],
compiler_directives={"language_level": "3"}, # Python 3
),
cmdclass=dict(build_ext=BuildExt),
Expand Down
2 changes: 2 additions & 0 deletions src/bluetooth_data_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
parse_advertisement_data_tuple,
)
from .privacy import get_cipher_for_irk, resolve_private_address
from .time import monotonic_time_coarse
from .utils import int_to_bluetooth_address

__version__ = "1.15.0"
Expand All @@ -31,6 +32,7 @@
"calculate_distance_meters",
"get_cipher_for_irk",
"resolve_private_address",
"monotonic_time_coarse",
]


Expand Down
11 changes: 11 additions & 0 deletions src/bluetooth_data_tools/_time_impl.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import cython

from posix.time cimport clock_gettime, timespec


def _monotonic_time_coarse():
cdef timespec ts
cdef double current
clock_gettime(6, &ts)
current = ts.tv_sec + (ts.tv_nsec / 1000000000.)
return current
49 changes: 49 additions & 0 deletions src/bluetooth_data_tools/time.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""Bluetooth time utils."""
from __future__ import annotations

import platform
import time
from contextlib import suppress
from functools import partial

CLOCK_MONOTONIC_COARSE = 6


def __gen_monotonic_time_coarse() -> partial[float]:
"""Return a function that provides monotonic time in seconds.
This is the coarse version of time_monotonic, which is faster but less accurate.
Since many arm64 and 32-bit platforms don't support VDSO with time.monotonic
because of errata, we can't rely on the kernel to provide a fast
monotonic time.
https://lore.kernel.org/lkml/[email protected]/
"""
# We use a partial here since its implementation is in native code
# which allows us to avoid the overhead of the global lookup
# of CLOCK_MONOTONIC_COARSE.
return partial(time.clock_gettime, CLOCK_MONOTONIC_COARSE)


monotonic_time_coarse = time.monotonic
_USE_COARSE_MONOTONIC_TIME = False

with suppress(Exception):
if (
platform.system() == "Linux"
and abs(time.monotonic() - __gen_monotonic_time_coarse()()) < 1
):
monotonic_time_coarse = __gen_monotonic_time_coarse()
_USE_COARSE_MONOTONIC_TIME = True

if _USE_COARSE_MONOTONIC_TIME:
with suppress(ImportError):
from ._time_impl import ( # type: ignore[no-redef] # noqa: F811 F401
_monotonic_time_coarse as monotonic_time_coarse,
)


__all__ = [
"monotonic_time_coarse",
]

0 comments on commit ae3abb8

Please sign in to comment.