From 663f3f3c5817a1a0f63476b9df1f21628f658479 Mon Sep 17 00:00:00 2001 From: Leonid Yuriev Date: Mon, 22 Jul 2019 00:19:15 +0300 Subject: [PATCH] mdbx: conditionally use cacheflush() for linux < 2.6.11 Change-Id: Id34c67797e14f709f767bf1b687319cd2dfef874 --- src/lck-linux.c | 22 ++++++++++++++++++++++ src/mdbx.c | 31 +++++++++++++++++++++---------- src/osal.h | 4 ++++ 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/lck-linux.c b/src/lck-linux.c index e48d8e11..5eeaccc6 100644 --- a/src/lck-linux.c +++ b/src/lck-linux.c @@ -19,6 +19,7 @@ #endif #include "./bits.h" +#include /* Some platforms define the EOWNERDEAD error code * even though they don't support Robust Mutexes. @@ -36,10 +37,31 @@ #endif #endif /* MDBX_USE_ROBUST */ +uint32_t linux_kernel_version; + /*----------------------------------------------------------------------------*/ /* rthc */ static __cold __attribute__((constructor)) void mdbx_global_constructor(void) { + struct utsname buffer; + if (uname(&buffer) == 0) { + int i = 0; + char *p = buffer.release; + while (*p && i < 4) { + if (*p >= '0' && *p <= '9') { + long number = strtol(p, &p, 10); + if (number > 0) { + if (number > 255) + number = 255; + linux_kernel_version += number << (24 - i * 8); + } + ++i; + } else { + ++p; + } + } + } + mdbx_rthc_global_init(); } diff --git a/src/mdbx.c b/src/mdbx.c index 3703d7a9..35c831f6 100644 --- a/src/mdbx.c +++ b/src/mdbx.c @@ -4639,9 +4639,17 @@ static int mdbx_page_flush(MDBX_txn *txn, pgno_t keep) { mdbx_debug("Write error: %s", mdbx_strerror(rc)); return rc; } -#if MDBX_CPU_CACHE_MMAP_NONCOHERENT == 1 - mdbx_invalidate_mmap_noncoherent_cache(env->me_map + wpos, wsize); -#endif + +#if MDBX_CPU_CACHE_MMAP_NONCOHERENT +#if defined(__linux__) || defined(__gnu_linux__) + if (linux_kernel_version >= 0x02060b00) + /* Linux kernels older than version 2.6.11 ignore the addr and nbytes + * arguments, making this function fairly expensive. Therefore, the + * whole cache is always flushed. */ +#endif /* Linux */ + mdbx_invalidate_mmap_noncoherent_cache(env->me_map + wpos, wsize); +#endif /* MDBX_CPU_CACHE_MMAP_NONCOHERENT */ + n = 0; } if (i > pagecount) @@ -4657,13 +4665,16 @@ static int mdbx_page_flush(MDBX_txn *txn, pgno_t keep) { n++; } -#if MDBX_CPU_CACHE_MMAP_NONCOHERENT > 1 - /* Linux kernels older than version 2.6.11 ignore the addr and nbytes - * arguments, making this function fairly expensive. Therefore, the whole - * cache is always flushed. */ - mdbx_invalidate_mmap_noncoherent_cache(env->me_map, - pgno2bytes(env, txn->mt_next_pgno)); -#endif +#if MDBX_CPU_CACHE_MMAP_NONCOHERENT && \ + (defined(__linux__) || defined(__gnu_linux__)) + if (linux_kernel_version < 0x02060b00) { + /* Linux kernels older than version 2.6.11 ignore the addr and nbytes + * arguments, making this function fairly expensive. Therefore, the whole + * cache is always flushed. */ + mdbx_invalidate_mmap_noncoherent_cache(env->me_map, + pgno2bytes(env, txn->mt_next_pgno)); + } +#endif /* MDBX_CPU_CACHE_MMAP_NONCOHERENT && Linux */ for (i = keep; ++i <= pagecount;) { dp = dl[i].ptr; diff --git a/src/osal.h b/src/osal.h index ec6c1a10..6d40d6fa 100644 --- a/src/osal.h +++ b/src/osal.h @@ -462,6 +462,10 @@ int mdbx_vasprintf(char **strp, const char *fmt, va_list ap); /* max bytes to write in one call */ #define MAX_WRITE UINT32_C(0x3fff0000) +#if defined(__linux__) || defined(__gnu_linux__) +extern uint32_t linux_kernel_version; +#endif /* Linux */ + /* Get the size of a memory page for the system. * This is the basic size that the platform's memory manager uses, and is * fundamental to the use of memory-mapped files. */