Closed gavv closed 9 months ago
Hi @gavv, this comment isn't directly related to this PR, just some thoughts. it was a little bit tricky for me to find out where was the actual conversation of the fraction part of timestamps. I was playing a little bit with a code, and tried to make it more understandable, at least for me.
namespace {
uint64_t bits_pack(uint32_t hi, uint32_t lo) {
return ((uint64_t)hi << 32) | (lo & 0x00000000FFFFFFFFULL);
}
void bits_unpack(uint64_t value, uint32_t& hi, uint32_t& lo) {
hi = (value & 0xFFFFFFFF00000000ULL) >> 32;
lo = value & 0xFFFFFFFFULL;
}
} // namespace
ntp_timestamp_t nanoseconds_2_ntp(core::nanoseconds_t ns_delta) {
roc_panic_if_msg(ns_delta < 0, "ntp: can not convert negative delta to ntp");
const uint32_t seconds = (uint32_t)(ns_delta / core::Second);
const uint32_t fraction = (uint32_t)ns_delta - seconds * core::Second;
const uint32_t nans = ((uint64_t)fraction << 32) / core::Second;
return bits_pack(seconds, nans);
}
core::nanoseconds_t ntp_2_nanoseconds(ntp_timestamp_t ntp_delta) {
uint32_t hi = 0;
uint32_t lo = 0;
bits_unpack(ntp_delta, hi, lo);
const core::nanoseconds_t seconds = (core::nanoseconds_t)hi;
const core::nanoseconds_t nans = (core::nanoseconds_t)(lo * core::Second) >> 32;
return seconds * core::Second + nans;
}
Now, it seems clear how the fractional part should be computed:
core::Second / (1 << 32)
(1 << 32) / core::Second
Also, I want to mention the following resources that were very helpful with understanding NTP and UNIX timestamps:
Nice, applied suggested refactoring: 73bff5db5cb9322a3efff9dacc0a6360d3f00536 (with some small changes)
Fixes #546.
unix_2_ntp() and ntp_2_unix() are updated according to RFC 2030.
ntp_equal_delta() is removed because it was never used and proper implementation is not trivial.