From 5693fad51d8e0ca7c63059a66c59d6c00706c17d Mon Sep 17 00:00:00 2001 From: Leonid Yuriev Date: Tue, 1 Oct 2019 13:53:52 +0300 Subject: [PATCH] mdbx: add mdbx_osal_monotime_to_16dot16(). Change-Id: Ia65057def67cebf67252a77665efde4223b14d10 --- src/elements/core.c | 14 ++++++++++++++ src/elements/osal.c | 35 ++++++++++++++++++++++++++++++----- src/elements/osal.h | 1 + 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/elements/core.c b/src/elements/core.c index 98bd9249..67ed37aa 100644 --- a/src/elements/core.c +++ b/src/elements/core.c @@ -505,6 +505,20 @@ __cold void mdbx_rthc_global_init(void) { mdbx_trace("pid %d, &mdbx_rthc_key = %p, value 0x%x", mdbx_getpid(), &rthc_key, (unsigned)rthc_key); #endif + /* checking time conversion, this also avoids racing on 32-bit architectures + * during writing calculated 64-bit ratio(s) into memory. */ + uint32_t proba = UINT32_MAX; + while (true) { + unsigned time_conversion_checkup = + mdbx_osal_monotime_to_16dot16(mdbx_osal_16dot16_to_monotime(proba)); + unsigned one_more = (proba < UINT32_MAX) ? proba + 1 : proba; + unsigned one_less = (proba > 0) ? proba - 1 : proba; + mdbx_ensure(nullptr, time_conversion_checkup >= one_less && + time_conversion_checkup <= one_more); + if (proba == 0) + break; + proba >>= 1; + } } /* dtor called for thread, i.e. for all mdbx's environment objects */ diff --git a/src/elements/osal.c b/src/elements/osal.c index 70357da0..3cd139c4 100644 --- a/src/elements/osal.c +++ b/src/elements/osal.c @@ -1344,26 +1344,51 @@ static __cold clockid_t choice_monoclock() { } #endif +/*----------------------------------------------------------------------------*/ + +#if defined(_WIN32) || defined(_WIN64) +static LARGE_INTEGER performance_frequency; +#elif defined(__APPLE__) || defined(__MACH__) +static uint64_t ratio_16dot16_to_monotine; +#endif + MDBX_INTERNAL_FUNC uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16) { #if defined(_WIN32) || defined(_WIN64) - static LARGE_INTEGER performance_frequency; - if (performance_frequency.QuadPart == 0) + if (unlikely(performance_frequency.QuadPart == 0)) QueryPerformanceFrequency(&performance_frequency); const uint64_t ratio = performance_frequency.QuadPart; #elif defined(__APPLE__) || defined(__MACH__) - static uint64_t ratio; - if (!ratio) { + if (unlikely(ratio_16dot16_to_monotine == 0)) { mach_timebase_info_data_t ti; mach_timebase_info(&ti); - ratio = UINT64_C(1000000000) * ti.denom / ti.numer; + ratio_16dot16_to_monotine = UINT64_C(1000000000) * ti.denom / ti.numer; } + const uint64_t ratio = ratio_16dot16_to_monotine; #else const uint64_t ratio = UINT64_C(1000000000); #endif return (ratio * seconds_16dot16 + 32768) >> 16; } +MDBX_INTERNAL_FUNC uint32_t mdbx_osal_monotime_to_16dot16(uint64_t monotime) { + static uint64_t limit; + if (unlikely(monotime > limit)) { + if (limit != 0) + return UINT32_MAX; + limit = mdbx_osal_16dot16_to_monotime(UINT32_MAX - 1); + if (monotime > limit) + return UINT32_MAX; + } +#if defined(_WIN32) || defined(_WIN64) + return (uint32_t)((monotime << 16) / performance_frequency.QuadPart); +#elif defined(__APPLE__) || defined(__MACH__) + return (uint32_t)((monotime << 16) / ratio_16dot16_to_monotine); +#else + return (uint32_t)(monotime * 128 / 1953125); +#endif +} + MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void) { #if defined(_WIN32) || defined(_WIN64) LARGE_INTEGER counter; diff --git a/src/elements/osal.h b/src/elements/osal.h index 5e089745..8c17047d 100644 --- a/src/elements/osal.h +++ b/src/elements/osal.h @@ -646,6 +646,7 @@ MDBX_INTERNAL_FUNC void __maybe_unused mdbx_osal_jitter(bool tiny); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16); +MDBX_INTERNAL_FUNC uint32_t mdbx_osal_monotime_to_16dot16(uint64_t monotime); /*----------------------------------------------------------------------------*/ /* lck stuff */