diff options
author | George Hazan <ghazan@miranda.im> | 2018-03-30 22:50:46 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2018-03-30 22:50:46 +0300 |
commit | 628f23ab62e342bb0b1dddedb563e7f13faf9528 (patch) | |
tree | 55c97c8453e2dc0036dfa65fb5eb268c886ada13 /plugins/Dbx_mdbx | |
parent | 67cd8dbde997606b40bd7dc2712ccc4c66d8d06f (diff) |
merge with the final version of libmdbx
Diffstat (limited to 'plugins/Dbx_mdbx')
24 files changed, 648 insertions, 314 deletions
diff --git a/plugins/Dbx_mdbx/src/libmdbx/Makefile b/plugins/Dbx_mdbx/src/libmdbx/Makefile index c434dbdd56..0552412ed0 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/Makefile +++ b/plugins/Dbx_mdbx/src/libmdbx/Makefile @@ -23,23 +23,21 @@ suffix ?= CC ?= gcc CXX ?= g++ -XCFLAGS ?= -DNDEBUG=1 -DMDBX_DEBUG=0 -DLIBMDBX_EXPORTS=1 +ifeq ($(shell (export LC_ALL=C; ($(CC) --version 2>&1; $(CC) -v 2>&1) | grep -q -i 'e2k' && echo yes)),yes) +CFLAGS ?= -O3 -g3 -Wall -Werror -Wextra -ffunction-sections -fPIC -fvisibility=hidden +else CFLAGS ?= -O2 -g3 -Wall -Werror -Wextra -ffunction-sections -fPIC -fvisibility=hidden -CFLAGS += -D_GNU_SOURCE=1 -std=gnu11 -pthread $(XCFLAGS) - -# temporary workaround for lcc's bug -TARGET_ARCH_e2k = $(shell (export LC_ALL=C; ($(CC) --version 2>&1; $(CC) -v 2>&1) | grep -q -i 'e2k' && echo yes || echo no)) -ifeq ($(TARGET_ARCH_e2k),yes) -TARGET_ARCH := e2k -CFLAGS += -mtune=native -Wno-alignment-reduction-ignored endif +XCFLAGS ?= -DNDEBUG=1 -DMDBX_DEBUG=0 -DLIBMDBX_EXPORTS=1 +CFLAGS += -D_GNU_SOURCE=1 -std=gnu11 -pthread $(XCFLAGS) CXXFLAGS = -std=c++11 $(filter-out -std=gnu11,$(CFLAGS)) -TESTDB ?= $(shell [ -d /dev/shm ] && echo /dev/shm || echo /tmp)/mdbx-check.db -TESTLOG ?= $(shell [ -d /dev/shm ] && echo /dev/shm || echo /tmp)/mdbx-check.log +TESTDB ?= $(shell [ -d /dev/shm ] && echo /dev/shm || echo /tmp)/mdbx-test.db +TESTLOG ?= $(shell [ -d /dev/shm ] && echo /dev/shm || echo /tmp)/mdbx-test.log # LY: '--no-as-needed,-lrt' for ability to built with modern glibc, but then run with the old LDFLAGS ?= -Wl,--gc-sections,-z,relro,-O,--no-as-needed,-lrt +EXE_LDFLAGS ?= $(LDFLAGS) -static # LY: just for benchmarking IOARENA ?= $(shell \ @@ -90,6 +88,12 @@ clean: check: all rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; test/test --pathname=$(TESTDB) --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) && ./mdbx_chk -vvn $(TESTDB) +check-singleprocess: all + rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; test/test --pathname=$(TESTDB) --dont-cleanup-after --hill | tee -a $(TESTLOG) | tail -n 42) && ./mdbx_chk -vvn $(TESTDB) + +check-fault: all + rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; test/test --pathname=$(TESTDB) --inject-writefault=42 --dump-config --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) && ./mdbx_chk -vvn $(TESTDB) + define core-rule $(patsubst %.c,%.o,$(1)): $(1) $(CORE_INC) mdbx.h Makefile $(CC) $(CFLAGS) -c $(1) -o $$@ @@ -111,10 +115,12 @@ libmdbx.so: $(CORE_OBJ) $(CC) $(CFLAGS) -save-temps $^ -pthread -shared $(LDFLAGS) -o $@ mdbx_%: src/tools/mdbx_%.c libmdbx.a - $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ + $(CC) $(CFLAGS) $^ $(EXE_LDFLAGS) -o $@ test/test: $(TEST_OBJ) libmdbx.a - $(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@ + $(CXX) $(CXXFLAGS) $^ $(EXE_LDFLAGS) -o $@ + +############################################################################### ifneq ($(wildcard $(IOARENA)),) @@ -163,6 +169,8 @@ bench-quartet: bench-mdbx_$(NN).txt bench-lmdb_$(NN).txt bench-rocksdb_$(NN).txt endif +############################################################################### + ci-rule = ( CC=$$(which $1); if [ -n "$$CC" ]; then \ echo -n "probe by $2 ($$(readlink -f $$(which $$CC))): " && \ $(MAKE) clean >$1.log 2>$1.err && \ @@ -178,3 +186,36 @@ ci: @$(call ci-rule,gcc,GCC) @$(call ci-rule,clang,clang LLVM) @$(call ci-rule,icc,Intel C) + +############################################################################### + +CROSS_LIST = alpha-linux-gnu-gcc mips-linux-gnu-gcc \ + powerpc64-linux-gnu-gcc powerpc-linux-gnu-gcc \ + arm-linux-gnueabihf-gcc aarch64-linux-gnu-gcc + +# hppa-linux-gnu-gcc - don't supported by current qemu release +# s390x-linux-gnu-gcc - qemu troubles (hang/abort) +# sh4-linux-gnu-gcc - qemu troubles (pread syscall, etc) +# mips64-linux-gnuabi64-gcc - qemu troubles (pread syscall, etc) +# sparc64-linux-gnu-gcc - qemu troubles (fcntl for F_SETLK/F_GETLK) +CROSS_LIST_NOQEMU = hppa-linux-gnu-gcc s390x-linux-gnu-gcc \ + sh4-linux-gnu-gcc mips64-linux-gnuabi64-gcc sparc64-linux-gnu-gcc + +cross-gcc: + @echo "CORRESPONDING CROSS-COMPILERs ARE REQUIRED." + @echo "FOR INSTANCE: apt install g++-aarch64-linux-gnu g++-alpha-linux-gnu g++-arm-linux-gnueabihf g++-hppa-linux-gnu g++-mips-linux-gnu g++-mips64-linux-gnuabi64 g++-powerpc-linux-gnu g++-powerpc64-linux-gnu g++-s390x-linux-gnu g++-sh4-linux-gnu" + @for CC in $(CROSS_LIST_NOQEMU) $(CROSS_LIST); do \ + echo "===================== $$CC"; \ + $(MAKE) clean && CC=$$CC CXX=$$(echo $$CC | sed 's/-gcc/-g++/') EXE_LDFLAGS=-static $(MAKE) all || exit $$?; \ + done + +# +# Unfortunately qemu don't provide robust support for futexes. +# Therefore it is impossible to run full multi-process tests. +cross-qemu: + @echo "CORRESPONDING CROSS-COMPILERs AND QEMUs ARE REQUIRED." + @echo "FOR INSTANCE: apt install binfmt-support qemu-user-static qemu-user qemu-system-arm qemu-system-mips qemu-system-misc qemu-system-ppc qemu-system-sparc g++-aarch64-linux-gnu g++-alpha-linux-gnu g++-arm-linux-gnueabihf g++-hppa-linux-gnu g++-mips-linux-gnu g++-mips64-linux-gnuabi64 g++-powerpc-linux-gnu g++-powerpc64-linux-gnu g++-s390x-linux-gnu g++-sh4-linux-gnu" + @for CC in $(CROSS_LIST); do \ + echo "===================== $$CC + qemu"; \ + $(MAKE) clean && CC=$$CC CXX=$$(echo $$CC | sed 's/-gcc/-g++/') EXE_LDFLAGS=-static $(MAKE) check-singleprocess || exit $$?; \ + done diff --git a/plugins/Dbx_mdbx/src/libmdbx/README-RU.md b/plugins/Dbx_mdbx/src/libmdbx/README-RU.md index 679146fd81..095a25984f 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/README-RU.md +++ b/plugins/Dbx_mdbx/src/libmdbx/README-RU.md @@ -12,13 +12,24 @@ and [by Yandex](https://translate.yandex.ru/translate?url=https%3A%2F%2Fgithub.c ### Project Status -**Now MDBX is under _active development_** and until 2018Q2 is expected a big -change both of API and database format. Unfortunately those update will lead to -loss of compatibility with previous versions. -The aim of this revolution in providing a clearer robust API and adding new -features, including the database properties. +**Сейчас MDBX _активно перерабатывается_** и к середине 2018 +ожидается большое измените как API, так и формата базы данных. +К сожалению, обновление приведет к потере совместимости с +предыдущими версиями. +Цель этой революции в обеспечении более четкого надежного +API и добавлении новых функции, а также в наделении базы данных +новыми свойствами. + +В настоящее время MDBX предназначена для Linux, а также +поддерживает Windows (начиная с Windows Server 2008) в качестве +дополнительно платформы. Поддержка других ОС может быть +обеспечена на коммерческой основе. Однако такие +усовершенствования (т. е. pull-requests) могут быть приняты в +мейнстрим только в том случае, если будет доступен +соответствующий публичный и бесплатный сервис непрерывной +интеграции (aka Countinious Integration). ## Содержание @@ -43,7 +54,7 @@ features, including the database properties. _libmdbx_ - это встраиваемый key-value движок хранения со специфическим набором свойств и возможностей, ориентированный на создание уникальных -легковесных решений с предельной производительностью. +легковесных решений с предельной производительностью под Linux и Windows. _libmdbx_ позволяет множеству процессов совместно читать и обновлять несколько key-value таблиц с соблюдением [ACID](https://ru.wikipedia.org/wiki/ACID), diff --git a/plugins/Dbx_mdbx/src/libmdbx/README.md b/plugins/Dbx_mdbx/src/libmdbx/README.md index fb5e2e7538..216c997f08 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/README.md +++ b/plugins/Dbx_mdbx/src/libmdbx/README.md @@ -9,9 +9,17 @@ libmdbx ### Project Status -**MDBX is under _active development_**, database format and API aren't stable -at least until 2018Q2. New version won't be backwards compatible. -Main focus of the rework is to provide clear and robust API and new features. +**MDBX is under _active development_**, database format and +API aren't stable at least until 2018Q3. New version won't be +backwards compatible. Main focus of the rework is to provide +clear and robust API and new features. + +Nowadays MDBX intended for Linux and support Windows (since +Windows Server 2008) as complementary platform. Support for +other OS could be implemented on commercial basis. However such +enhancements (i.e. pull requests) could be accepted in +mainstream only when corresponding public and free Countinious +Integration service will be available. ## Contents @@ -34,7 +42,7 @@ Main focus of the rework is to provide clear and robust API and new features. ## Overview -_libmdbx_ is an embedded lightweight key-value database engine oriented for performance. +_libmdbx_ is an embedded lightweight key-value database engine oriented for performance under Linux and Windows. _libmdbx_ allows multiple processes to read and update several key-value tables concurrently, while being [ACID](https://en.wikipedia.org/wiki/ACID)-compliant, with minimal overhead and operation cost of Olog(N). @@ -233,7 +241,7 @@ scanning data directory. Because of this syncing data to disk might be quite resource intensive and be main performance bottleneck during intensive write workload. > As compromise _libmdbx_ allows several modes of lazy and/or periodic syncing, including `MAPASYNC` mode, which modificate - > data in memory and asynchronously syncs data to disc, moment to sync is picked by OS. + > data in memory and asynchronously syncs data to disk, moment to sync is picked by OS. > > Although this should be used with care, synchronous transactions in a DB with transaction journal will require 2 IOPS > minimum (probably 3-4 in practice) because of filesystem overhead, overhead depends on filesystem, not on record @@ -339,7 +347,7 @@ Improvements over LMDB This allows to minimize reclaim loop and make it execution time independent from total page count. This results in OS kernel cache mechanisms working with maximum efficiency. - In case of using disc controllers or storages with + In case of using disk controllers or storages with [BBWC](https://en.wikipedia.org/wiki/Disk_buffer#Write_acceleration) this may greatly improve write performance. @@ -378,7 +386,7 @@ Improvements over LMDB 9. Check if there is a row with data after current cursor position via `mdbx_cursor_eof()`. -10. Ability to explicitly request update of current record without creating new record. Implemented as `MDBX_CURRENT` flag +10. Ability to explicitly request update of present record without creating new record. Implemented as `MDBX_CURRENT` flag for `mdbx_put()`. 11. Ability to update or delete record and get previous value via `mdbx_replace()` Also can update specific multi-value. @@ -419,7 +427,7 @@ Improvements over LMDB 22. Additional error code `MDBX_EMULTIVAL`, which is returned by `mdbx_put()` and `mdbx_replace()` in case is ambiguous update or delete. -23. Ability to get value by key and duplicates count by `mdbx_get_ex()` +23. Ability to get value by key and duplicates count by `mdbx_get_ex()`. 24. Functions `mdbx_cursor_on_first() and mdbx_cursor_on_last(), which allows to know if cursor is currently on first or last position respectively. diff --git a/plugins/Dbx_mdbx/src/libmdbx/TODO.md b/plugins/Dbx_mdbx/src/libmdbx/TODO.md index 1af7e004bb..32c4f0ac25 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/TODO.md +++ b/plugins/Dbx_mdbx/src/libmdbx/TODO.md @@ -21,7 +21,7 @@ Тесты ===== - [ ] Тестирование поддержки lockless-режима. -- [ ] Додумать имя и размещение тестовой БД по-умолчанию. +- [x] Додумать имя и размещение тестовой БД по-умолчанию. - [ ] Реализовать cleanup в тесте. - [ ] usage для теста. - [ ] Логирование в файл, плюс более полный progress bar. diff --git a/plugins/Dbx_mdbx/src/libmdbx/mdbx.h b/plugins/Dbx_mdbx/src/libmdbx/mdbx.h index 2cf3273b06..36146fb685 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/mdbx.h +++ b/plugins/Dbx_mdbx/src/libmdbx/mdbx.h @@ -982,6 +982,15 @@ LIBMDBX_API int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags, * [in] txn A transaction handle returned by mdbx_txn_begin() */ LIBMDBX_API MDBX_env *mdbx_txn_env(MDBX_txn *txn); +/* Return the transaction's flags. + * + * This returns the flags associated with this transaction. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * + * Returns A transaction flags, valid if input is an active transaction. */ +LIBMDBX_API int mdbx_txn_flags(MDBX_txn *txn); + /* Return the transaction's ID. * * This returns the identifier associated with this transaction. For a @@ -1818,6 +1827,42 @@ LIBMDBX_API int mdbx_cursor_get_attr(MDBX_cursor *mc, MDBX_val *key, LIBMDBX_API int mdbx_get_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, mdbx_attr_t *attrptr); +/*----------------------------------------------------------------------------*/ +/* LY: temporary workaround for Elbrus's memcmp() bug. */ +#ifndef __GLIBC_PREREQ +#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) +#define __GLIBC_PREREQ(maj, min) \ + ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)) +#else +#define __GLIBC_PREREQ(maj, min) (0) +#endif +#endif /* __GLIBC_PREREQ */ +#if defined(__e2k__) && !__GLIBC_PREREQ(2, 24) +LIBMDBX_API int mdbx_e2k_memcmp_bug_workaround(const void *s1, const void *s2, + size_t n); +LIBMDBX_API int mdbx_e2k_strcmp_bug_workaround(const char *s1, const char *s2); +LIBMDBX_API int mdbx_e2k_strncmp_bug_workaround(const char *s1, const char *s2, + size_t n); +LIBMDBX_API size_t mdbx_e2k_strlen_bug_workaround(const char *s); +LIBMDBX_API size_t mdbx_e2k_strnlen_bug_workaround(const char *s, + size_t maxlen); +#include <string.h> +#include <strings.h> +#undef memcmp +#define memcmp mdbx_e2k_memcmp_bug_workaround +#undef bcmp +#define bcmp mdbx_e2k_memcmp_bug_workaround +#undef strcmp +#define strcmp mdbx_e2k_strcmp_bug_workaround +#undef strncmp +#define strncmp mdbx_e2k_strncmp_bug_workaround +#undef strlen +#define strlen mdbx_e2k_strlen_bug_workaround +#undef strnlen +#define strnlen mdbx_e2k_strnlen_bug_workaround + +#endif /* Elbrus's memcmp() bug. */ + #ifdef __cplusplus } #endif diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/bits.h b/plugins/Dbx_mdbx/src/libmdbx/src/bits.h index 67def2ed90..7f69cdc066 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/src/bits.h +++ b/plugins/Dbx_mdbx/src/libmdbx/src/bits.h @@ -55,6 +55,7 @@ #pragma warning(disable : 4310) /* cast truncates constant value */ #pragma warning(disable : 4820) /* bytes padding added after data member for aligment */ #pragma warning(disable : 4548) /* expression before comma has no effect; expected expression with side - effect */ +#pragma warning(disable : 4366) /* the result of the unary '&' operator may be unaligned */ #endif /* _MSC_VER (warnings) */ #include "../mdbx.h" @@ -89,26 +90,29 @@ #endif /* __SANITIZE_THREAD__ */ #if __has_warning("-Wconstant-logical-operand") -#if defined(__clang__) -#pragma clang diagnostic ignored "-Wconstant-logical-operand" -#elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wconstant-logical-operand" -#else -#pragma warning disable "constant-logical-operand" -#endif +# if defined(__clang__) +# pragma clang diagnostic ignored "-Wconstant-logical-operand" +# elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wconstant-logical-operand" +# else +# pragma warning disable "constant-logical-operand" +# endif #endif /* -Wconstant-logical-operand */ -#if __has_warning("-Walignment-reduction-ignored") || defined(__e2k__) || defined(__ICC) -#if defined(__ICC) -#pragma warning(disable: 3453 1366) -#elif defined(__clang__) -#pragma clang diagnostic ignored "-Walignment-reduction-ignored" -#elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Walignment-reduction-ignored" -#else -#pragma warning disable "alignment-reduction-ignored" -#endif -#endif /* -Wno-constant-logical-operand */ +#if defined(__LCC__) && (__LCC__ <= 121) + /* bug #2798 */ +# pragma diag_suppress alignment_reduction_ignored +#elif defined(__ICC) +# pragma warning(disable: 3453 1366) +#elif __has_warning("-Walignment-reduction-ignored") +# if defined(__clang__) +# pragma clang diagnostic ignored "-Walignment-reduction-ignored" +# elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Walignment-reduction-ignored" +# else +# pragma warning disable "alignment-reduction-ignored" +# endif +#endif /* -Walignment-reduction-ignored */ #include "./osal.h" @@ -249,7 +253,7 @@ typedef struct MDBX_reader { uint8_t pad[MDBX_CACHELINE_SIZE - (sizeof(txnid_t) + sizeof(mdbx_pid_t) + sizeof(mdbx_tid_t)) % MDBX_CACHELINE_SIZE]; -} __cache_aligned MDBX_reader; +} MDBX_reader; /* Information about a single database in the environment. */ typedef struct MDBX_db { @@ -407,47 +411,53 @@ typedef struct MDBX_lockinfo { /* Flags which environment was opened. */ volatile uint32_t mti_envmode; - union { #ifdef MDBX_OSAL_LOCK + /* Mutex protecting write access to this table. */ + union { MDBX_OSAL_LOCK mti_wmutex; -#endif - uint64_t align_wmutex; + uint8_t pad_mti_wmutex[MDBX_OSAL_LOCK_SIZE % sizeof(size_t)]; }; +#endif +#define MDBX_lockinfo_SIZE_A \ + (8 /* mti_magic_and_version */ + 4 /* mti_os_and_format */ + \ + 4 /* mti_envmode */ + MDBX_OSAL_LOCK_SIZE /* mti_wmutex */ + \ + MDBX_OSAL_LOCK_SIZE % sizeof(size_t) /* pad_mti_wmutex */) - union { - /* The number of slots that have been used in the reader table. - * This always records the maximum count, it is not decremented - * when readers release their slots. */ - volatile unsigned __cache_aligned mti_numreaders; - uint64_t align_numreaders; - }; + /* cache-line alignment */ + uint8_t + pad_a[MDBX_CACHELINE_SIZE - MDBX_lockinfo_SIZE_A % MDBX_CACHELINE_SIZE]; + + /* The number of slots that have been used in the reader table. + * This always records the maximum count, it is not decremented + * when readers release their slots. */ + volatile unsigned mti_numreaders; - union { #ifdef MDBX_OSAL_LOCK - /* Mutex protecting access to this table. */ + /* Mutex protecting readers registration access to this table. */ + union { MDBX_OSAL_LOCK mti_rmutex; -#endif - uint64_t align_rmutex; + uint8_t pad_mti_rmutex[MDBX_OSAL_LOCK_SIZE % sizeof(size_t)]; }; +#endif - union { - volatile txnid_t mti_oldest; - uint64_t align_oldest; - }; + volatile txnid_t mti_oldest; + volatile uint32_t mti_readers_refresh_flag; - union { - volatile uint32_t mti_readers_refresh_flag; - uint64_t align_reader_finished_flag; - }; +#define MDBX_lockinfo_SIZE_B \ + (sizeof(unsigned) /* mti_numreaders */ + \ + MDBX_OSAL_LOCK_SIZE /* mti_rmutex */ + sizeof(txnid_t) /* mti_oldest */ + \ + sizeof(uint32_t) /* mti_readers_refresh_flag */ + \ + MDBX_OSAL_LOCK_SIZE % sizeof(size_t) /* pad_mti_rmutex */) - uint8_t pad_align[MDBX_CACHELINE_SIZE - sizeof(uint64_t) * 7]; + /* cache-line alignment */ + uint8_t + pad_b[MDBX_CACHELINE_SIZE - MDBX_lockinfo_SIZE_B % MDBX_CACHELINE_SIZE]; + + MDBX_reader mti_readers[1]; - MDBX_reader __cache_aligned mti_readers[1]; } MDBX_lockinfo; -#ifdef _MSC_VER #pragma pack(pop) -#endif /* MSVC: Enable aligment */ #define MDBX_LOCKINFO_WHOLE_SIZE \ ((sizeof(MDBX_lockinfo) + MDBX_CACHELINE_SIZE - 1) & \ diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/defs.h b/plugins/Dbx_mdbx/src/libmdbx/src/defs.h index 7c3bc1d540..6da5a96363 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/src/defs.h +++ b/plugins/Dbx_mdbx/src/libmdbx/src/defs.h @@ -192,16 +192,6 @@ # endif #endif /* __prefetch */ -#ifndef __aligned -# if defined(__GNUC__) || __has_attribute(aligned) -# define __aligned(N) __attribute__((aligned(N))) -# elif defined(_MSC_VER) -# define __aligned(N) __declspec(align(N)) -# else -# define __aligned(N) -# endif -#endif /* __aligned */ - #ifndef __noreturn # if defined(__GNUC__) || __has_attribute(noreturn) # define __noreturn __attribute__((noreturn)) diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c b/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c index aac32704a9..7845e6d733 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c +++ b/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c @@ -37,6 +37,117 @@ #include "./bits.h" +/* LY: temporary workaround for Elbrus's memcmp() bug. */ +#if defined(__e2k__) && !__GLIBC_PREREQ(2, 24) +int __hot mdbx_e2k_memcmp_bug_workaround(const void *s1, const void *s2, + size_t n) { + if (unlikely(n > 42 + /* LY: align followed access if reasonable possible */ && + (((uintptr_t)s1) & 7) != 0 && + (((uintptr_t)s1) & 7) == (((uintptr_t)s2) & 7))) { + if (((uintptr_t)s1) & 1) { + const int diff = *(uint8_t *)s1 - *(uint8_t *)s2; + if (diff) + return diff; + s1 = (char *)s1 + 1; + s2 = (char *)s2 + 1; + n -= 1; + } + + if (((uintptr_t)s1) & 2) { + const uint16_t a = *(uint16_t *)s1; + const uint16_t b = *(uint16_t *)s2; + if (likely(a != b)) + return (__builtin_bswap16(a) > __builtin_bswap16(b)) ? 1 : -1; + s1 = (char *)s1 + 2; + s2 = (char *)s2 + 2; + n -= 2; + } + + if (((uintptr_t)s1) & 4) { + const uint32_t a = *(uint32_t *)s1; + const uint32_t b = *(uint32_t *)s2; + if (likely(a != b)) + return (__builtin_bswap32(a) > __builtin_bswap32(b)) ? 1 : -1; + s1 = (char *)s1 + 4; + s2 = (char *)s2 + 4; + n -= 4; + } + } + + while (n >= 8) { + const uint64_t a = *(uint64_t *)s1; + const uint64_t b = *(uint64_t *)s2; + if (likely(a != b)) + return (__builtin_bswap64(a) > __builtin_bswap64(b)) ? 1 : -1; + s1 = (char *)s1 + 8; + s2 = (char *)s2 + 8; + n -= 8; + } + + if (n & 4) { + const uint32_t a = *(uint32_t *)s1; + const uint32_t b = *(uint32_t *)s2; + if (likely(a != b)) + return (__builtin_bswap32(a) > __builtin_bswap32(b)) ? 1 : -1; + s1 = (char *)s1 + 4; + s2 = (char *)s2 + 4; + } + + if (n & 2) { + const uint16_t a = *(uint16_t *)s1; + const uint16_t b = *(uint16_t *)s2; + if (likely(a != b)) + return (__builtin_bswap16(a) > __builtin_bswap16(b)) ? 1 : -1; + s1 = (char *)s1 + 2; + s2 = (char *)s2 + 2; + } + + return (n & 1) ? *(uint8_t *)s1 - *(uint8_t *)s2 : 0; +} + +int __hot mdbx_e2k_strcmp_bug_workaround(const char *s1, const char *s2) { + while (true) { + int diff = *(uint8_t *)s1 - *(uint8_t *)s2; + if (likely(diff != 0) || *s1 == '\0') + return diff; + s1 += 1; + s2 += 1; + } +} + +int __hot mdbx_e2k_strncmp_bug_workaround(const char *s1, const char *s2, + size_t n) { + while (n > 0) { + int diff = *(uint8_t *)s1 - *(uint8_t *)s2; + if (likely(diff != 0) || *s1 == '\0') + return diff; + s1 += 1; + s2 += 1; + n -= 1; + } + return 0; +} + +size_t __hot mdbx_e2k_strlen_bug_workaround(const char *s) { + size_t n = 0; + while (*s) { + s += 1; + n += 1; + } + return n; +} + +size_t __hot mdbx_e2k_strnlen_bug_workaround(const char *s, size_t maxlen) { + size_t n = 0; + while (maxlen > n && *s) { + s += 1; + n += 1; + } + return n; +} +#endif /* Elbrus's memcmp() bug. */ + /*----------------------------------------------------------------------------*/ /* rthc (tls keys and destructors) */ @@ -2507,6 +2618,12 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) { return MDBX_PANIC; } + STATIC_ASSERT(sizeof(MDBX_reader) == MDBX_CACHELINE_SIZE); + STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_numreaders) % MDBX_CACHELINE_SIZE == + 0); + STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_readers) % MDBX_CACHELINE_SIZE == + 0); + pgno_t upper_pgno = 0; if (flags & MDBX_TXN_RDONLY) { txn->mt_flags = MDBX_TXN_RDONLY; @@ -2562,9 +2679,6 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) { } } - STATIC_ASSERT(sizeof(MDBX_reader) == MDBX_CACHELINE_SIZE); - STATIC_ASSERT( - offsetof(MDBX_lockinfo, mti_readers) % MDBX_CACHELINE_SIZE == 0); r = &env->me_lck->mti_readers[slot]; /* Claim the reader slot, carefully since other code * uses the reader table un-mutexed: First reset the @@ -2876,6 +2990,13 @@ uint64_t mdbx_txn_id(MDBX_txn *txn) { return txn->mt_txnid; } +int mdbx_txn_flags(MDBX_txn *txn) { + if (unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE)) + return -1; + + return txn->mt_flags; +} + /* Export or close DBI handles opened in this txn. */ static void mdbx_dbis_update(MDBX_txn *txn, int keep) { MDBX_dbi n = txn->mt_numdbs; @@ -4042,7 +4163,7 @@ static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *meta) { STATIC_ASSERT(MIN_MAPSIZE < MAX_MAPSIZE); if (mapsize_max > MAX_MAPSIZE || MAX_PAGENO < mdbx_roundup2((size_t)mapsize_max, env->me_os_psize) / - (uint64_t)page.mp_meta.mm_psize) { + (size_t)page.mp_meta.mm_psize) { const uint64_t used_bytes = page.mp_meta.mm_geo.next * (uint64_t)page.mp_meta.mm_psize; if (page.mp_meta.mm_geo.next - 1 > MAX_PAGENO || @@ -4644,13 +4765,13 @@ LIBMDBX_API int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, if (pagesize < 0) { pagesize = env->me_os_psize; - if (pagesize > MAX_PAGESIZE) + if ((uintptr_t)pagesize > MAX_PAGESIZE) pagesize = MAX_PAGESIZE; - mdbx_assert(env, pagesize >= MIN_PAGESIZE); + mdbx_assert(env, (uintptr_t)pagesize >= MIN_PAGESIZE); } } - if (pagesize < MIN_PAGESIZE || pagesize > MAX_PAGESIZE || + if (pagesize < (intptr_t)MIN_PAGESIZE || pagesize > (intptr_t)MAX_PAGESIZE || !mdbx_is_power2(pagesize)) { rc = MDBX_EINVAL; goto bailout; @@ -4684,7 +4805,7 @@ LIBMDBX_API int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, size_upper = pagesize * MAX_PAGENO; } - if (unlikely(size_lower < MIN_MAPSIZE || size_lower > size_upper)) { + if (unlikely(size_lower < (intptr_t)MIN_MAPSIZE || size_lower > size_upper)) { rc = MDBX_EINVAL; goto bailout; } @@ -4991,7 +5112,7 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) { filesize_before_mmap, bytes2pgno(env, (size_t)filesize_before_mmap)); } else { - mdbx_notice("filesize mismatch (expect %" PRIuPTR "/%" PRIaPGNO + mdbx_notice("filesize mismatch (expect %" PRIuSIZE "/%" PRIaPGNO ", have %" PRIu64 "/%" PRIaPGNO ")", expected_bytes, bytes2pgno(env, expected_bytes), filesize_before_mmap, @@ -5007,11 +5128,11 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) { if (env->me_flags & MDBX_RDONLY) { mdbx_notice("ignore filesize mismatch in readonly-mode"); } else { - mdbx_info("resize datafile to %" PRIu64 " bytes, %" PRIaPGNO " pages", + mdbx_info("resize datafile to %" PRIuSIZE " bytes, %" PRIaPGNO " pages", expected_bytes, bytes2pgno(env, expected_bytes)); err = mdbx_ftruncate(env->me_fd, expected_bytes); if (unlikely(err != MDBX_SUCCESS)) { - mdbx_error("error %d, while resize datafile to %" PRIu64 + mdbx_error("error %d, while resize datafile to %" PRIuSIZE " bytes, %" PRIaPGNO " pages", rc, expected_bytes, bytes2pgno(env, expected_bytes)); return err; @@ -5048,15 +5169,30 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) { return MDBX_WANNA_RECOVERY /* LY: could not recovery/rollback */; } + const MDBX_meta *const meta0 = METAPAGE(env, 0); + const MDBX_meta *const meta1 = METAPAGE(env, 1); + const MDBX_meta *const meta2 = METAPAGE(env, 2); + txnid_t undo_txnid = 0; + while ( + (head != meta0 && mdbx_meta_txnid_fluid(env, meta0) == undo_txnid) || + (head != meta1 && mdbx_meta_txnid_fluid(env, meta1) == undo_txnid) || + (head != meta2 && mdbx_meta_txnid_fluid(env, meta2) == undo_txnid)) + undo_txnid += 1; + if (unlikely(undo_txnid >= meta.mm_txnid_a)) { + mdbx_fatal("rollback failed: no suitable txnid (0,1,2) < %" PRIaTXN, + meta.mm_txnid_a); + return MDBX_PANIC /* LY: could not recovery/rollback */; + } + /* LY: rollback weak checkpoint */ - mdbx_trace("rollback: from %" PRIaTXN ", to %" PRIaTXN, head_txnid, - meta.mm_txnid_a); + mdbx_trace("rollback: from %" PRIaTXN ", to %" PRIaTXN " as %" PRIaTXN, + head_txnid, meta.mm_txnid_a, undo_txnid); mdbx_ensure(env, head_txnid == mdbx_meta_txnid_stable(env, head)); if (env->me_flags & MDBX_WRITEMAP) { - head->mm_txnid_a = 0; + head->mm_txnid_a = undo_txnid; head->mm_datasync_sign = MDBX_DATASIGN_WEAK; - head->mm_txnid_b = 0; + head->mm_txnid_b = undo_txnid; const size_t offset = ((uint8_t *)container_of(head, MDBX_page, mp_meta)) - env->me_dxb_mmap.dxb; @@ -5066,7 +5202,7 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) { err = mdbx_msync(&env->me_dxb_mmap, paged_offset, paged_length, false); } else { MDBX_meta rollback = *head; - mdbx_meta_set_txnid(env, &rollback, 0); + mdbx_meta_set_txnid(env, &rollback, undo_txnid); rollback.mm_datasync_sign = MDBX_DATASIGN_WEAK; err = mdbx_pwrite(env->me_fd, &rollback, sizeof(MDBX_meta), (uint8_t *)head - (uint8_t *)env->me_map); @@ -5075,7 +5211,7 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) { return err; mdbx_invalidate_cache(env->me_map, pgno2bytes(env, NUM_METAS)); - mdbx_ensure(env, 0 == mdbx_meta_txnid_fluid(env, head)); + mdbx_ensure(env, undo_txnid == mdbx_meta_txnid_fluid(env, head)); mdbx_ensure(env, 0 == mdbx_meta_eq_mask(env)); continue; } @@ -7059,7 +7195,8 @@ int mdbx_cursor_put(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, } else { rc = mdbx_cursor_set(mc, key, &d2, MDBX_SET, &exact); } - if ((flags & MDBX_NOOVERWRITE) && rc == 0) { + if ((flags & MDBX_NOOVERWRITE) && + (rc == MDBX_SUCCESS || rc == MDBX_EKEYMISMATCH)) { mdbx_debug("duplicate key [%s]", DKEY(key)); *data = d2; return MDBX_KEYEXIST; @@ -7273,9 +7410,11 @@ int mdbx_cursor_put(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, memcpy((char *)mp + mp->mp_upper + PAGEHDRSZ, (char *)fp + fp->mp_upper + PAGEHDRSZ, olddata.iov_len - fp->mp_upper - PAGEHDRSZ); + memcpy((char *)(&mp->mp_ptrs), (char *)(&fp->mp_ptrs), + NUMKEYS(fp) * sizeof(mp->mp_ptrs[0])); for (i = 0; i < NUMKEYS(fp); i++) { - mdbx_cassert(mc, fp->mp_ptrs[i] + offset <= UINT16_MAX); - mp->mp_ptrs[i] = (indx_t)(fp->mp_ptrs[i] + offset); + mdbx_cassert(mc, mp->mp_ptrs[i] + offset <= UINT16_MAX); + mp->mp_ptrs[i] += (indx_t)offset; } } } @@ -8796,27 +8935,22 @@ static int mdbx_rebalance(MDBX_cursor *mc) { if (unlikely(rc)) return rc; /* Adjust cursors pointing to mp */ + const MDBX_dbi dbi = mc->mc_dbi; + for (MDBX_cursor *m2 = mc->mc_txn->mt_cursors[dbi]; m2; + m2 = m2->mc_next) { + MDBX_cursor *m3 = + (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; + if (!(m3->mc_flags & C_INITIALIZED) || (m3->mc_snum < mc->mc_snum)) + continue; + if (m3->mc_pg[0] == mp) { + m3->mc_snum = 0; + m3->mc_top = 0; + m3->mc_flags &= ~C_INITIALIZED; + } + } mc->mc_snum = 0; mc->mc_top = 0; mc->mc_flags &= ~C_INITIALIZED; - { - MDBX_cursor *m2, *m3; - MDBX_dbi dbi = mc->mc_dbi; - - for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { - if (mc->mc_flags & C_SUB) - m3 = &m2->mc_xcursor->mx_cursor; - else - m3 = m2; - if (!(m3->mc_flags & C_INITIALIZED) || (m3->mc_snum < mc->mc_snum)) - continue; - if (m3->mc_pg[0] == mp) { - m3->mc_snum = 0; - m3->mc_top = 0; - m3->mc_flags &= ~C_INITIALIZED; - } - } - } } else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) { int i; mdbx_debug("collapsing root page!"); @@ -10349,13 +10483,13 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags, !strncmp(table_name, txn->mt_dbxs[scan].md_name.iov_base, len)) { *dbi = scan; rc = mdbx_dbi_bind(txn, scan, user_flags, keycmp, datacmp); - goto unlock_return_rc; + goto bailout; } } if (unlikely(slot >= env->me_maxdbs)) { rc = MDBX_DBS_FULL; - goto unlock_return_rc; + goto bailout; } unsigned dbflag = DB_FRESH | DB_VALID | DB_USRVALID; @@ -10405,7 +10539,6 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags, *dbi = slot; } -unlock_return_rc: mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS); return rc; } diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/osal.h b/plugins/Dbx_mdbx/src/libmdbx/src/osal.h index 54559388c9..e01311cb01 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/src/osal.h +++ b/plugins/Dbx_mdbx/src/libmdbx/src/osal.h @@ -103,24 +103,47 @@ typedef struct { typedef pthread_mutex_t mdbx_fastmutex_t; #endif /* Platform */ -#ifndef SSIZE_MAX -#define SSIZE_MAX INTPTR_MAX -#endif - -#ifdef HAVE_SYS_STAT_H +/* *INDENT-OFF* */ +/* clang-format off */ +#if defined(HAVE_SYS_STAT_H) || __has_include(<sys/stat.h>) #include <sys/stat.h> #endif -#ifdef HAVE_SYS_TYPES_H +#if defined(HAVE_SYS_TYPES_H) || __has_include(<sys/types.h>) #include <sys/types.h> #endif -#ifdef HAVE_SYS_FILE_H +#if defined(HAVE_SYS_FILE_H) || __has_include(<sys/file.h>) #include <sys/file.h> #endif +/* *INDENT-ON* */ +/* clang-format on */ + +#ifndef SSIZE_MAX +#define SSIZE_MAX INTPTR_MAX +#endif + +#if defined(i386) || defined(__386) || defined(__i386) || defined(__i386__) || \ + defined(i486) || defined(__i486) || defined(__i486__) || \ + defined(i586) | defined(__i586) || defined(__i586__) || defined(i686) || \ + defined(__i686) || defined(__i686__) || defined(_M_IX86) || \ + defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || \ + defined(__INTEL__) || defined(__x86_64) || defined(__x86_64__) || \ + defined(__amd64__) || defined(__amd64) || defined(_M_X64) || \ + defined(_M_AMD64) || defined(__IA32__) || defined(__INTEL__) +#ifndef __ia32__ +/* LY: define neutral __ia32__ for x86 and x86-64 archs */ +#define __ia32__ 1 +#endif /* __ia32__ */ +#if !defined(__amd64__) && (defined(__x86_64) || defined(__x86_64__) || \ + defined(__amd64) || defined(_M_X64)) +/* LY: define trusty __amd64__ for all AMD64/x86-64 arch */ +#define __amd64__ 1 +#endif /* __amd64__ */ +#endif /* all x86 */ #if !defined(UNALIGNED_OK) -#if defined(__i386) || defined(__x86_64__) || defined(_M_IX86) || \ - defined(_M_X64) || defined(i386) || defined(_X86_) || defined(__i386__) || \ - defined(_X86_64_) +#if (defined(__ia32__) || defined(__e2k__) || \ + defined(__ARM_FEATURE_UNALIGNED)) && \ + !defined(__ALIGNED__) #define UNALIGNED_OK 1 #else #define UNALIGNED_OK 0 @@ -135,26 +158,15 @@ typedef pthread_mutex_t mdbx_fastmutex_t; /*----------------------------------------------------------------------------*/ /* Compiler's includes for builtins/intrinsics */ -#ifdef _MSC_VER - -#if _MSC_FULL_VER < 190024215 -#if _MSC_FULL_VER < 180040629 && defined(_M_IX86) -#error Please use Visual Studio 2015 (MSC 19.0) or newer for 32-bit target. -#else -#pragma message( \ - "It is recommended to use Visual Studio 2015 (MSC 19.0) or newer.") -#endif -#endif - +#if defined(_MSC_VER) || defined(__INTEL_COMPILER) #include <intrin.h> - #elif __GNUC_PREREQ(4, 4) || defined(__clang__) -#if defined(__i386__) || defined(__x86_64__) -#include <cpuid.h> +#if defined(__ia32__) || defined(__e2k__) #include <x86intrin.h> -#endif -#elif defined(__INTEL_COMPILER) -#include <intrin.h> +#endif /* __ia32__ */ +#if defined(__ia32__) +#include <cpuid.h> +#endif /* __ia32__ */ #elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) #include <mbarrier.h> #elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \ @@ -173,8 +185,10 @@ typedef pthread_mutex_t mdbx_fastmutex_t; #pragma gcc_extensions #elif defined(__SNC__) /* Sony PS3 - troubles ? */ +#elif defined(__hppa__) || defined(__hppa) +#include <machine/inline.h> #else -#error Unknown C compiler, please use GNU C 5.x or newer +#error Unsupported C compiler, please use GNU C 4.4 or newer #endif /* Compiler */ /*----------------------------------------------------------------------------*/ @@ -183,44 +197,69 @@ typedef pthread_mutex_t mdbx_fastmutex_t; #if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \ !defined(__ORDER_BIG_ENDIAN__) -#if defined(HAVE_ENDIAN_H) +/* *INDENT-OFF* */ +/* clang-format off */ +#if defined(__GLIBC__) || defined(__GNU_LIBRARY__) || defined(__ANDROID__) || \ + defined(HAVE_ENDIAN_H) || __has_include(<endian.h>) #include <endian.h> -#elif defined(HAVE_SYS_PARAM_H) -#include <sys/param.h> /* for endianness */ -#elif defined(HAVE_NETINET_IN_H) && defined(HAVE_RESOLV_H) -#include <netinet/in.h> -#include <resolv.h> /* defines BYTE_ORDER on HPUX and Solaris */ -#endif +#elif defined(__APPLE__) || defined(__MACH__) || defined(__OpenBSD__) || \ + defined(HAVE_MACHINE_ENDIAN_H) || __has_include(<machine/endian.h>) +#include <machine/endian.h> +#elif defined(HAVE_SYS_ISA_DEFS_H) || __has_include(<sys/isa_defs.h>) +#include <sys/isa_defs.h> +#elif (defined(HAVE_SYS_TYPES_H) && defined(HAVE_SYS_ENDIAN_H)) || \ + (__has_include(<sys/types.h>) && __has_include(<sys/endian.h>)) +#include <sys/endian.h> +#include <sys/types.h> +#elif defined(__bsdi__) || defined(__DragonFly__) || defined(__FreeBSD__) || \ + defined(__NETBSD__) || defined(__NetBSD__) || \ + defined(HAVE_SYS_PARAM_H) || __has_include(<sys/param.h>) +#include <sys/param.h> +#endif /* OS */ +/* *INDENT-ON* */ +/* clang-format on */ #if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN) #define __ORDER_LITTLE_ENDIAN__ __LITTLE_ENDIAN #define __ORDER_BIG_ENDIAN__ __BIG_ENDIAN #define __BYTE_ORDER__ __BYTE_ORDER +#elif defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) +#define __ORDER_LITTLE_ENDIAN__ _LITTLE_ENDIAN +#define __ORDER_BIG_ENDIAN__ _BIG_ENDIAN +#define __BYTE_ORDER__ _BYTE_ORDER #else #define __ORDER_LITTLE_ENDIAN__ 1234 #define __ORDER_BIG_ENDIAN__ 4321 -#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN) || \ + +#if defined(__LITTLE_ENDIAN__) || \ + (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \ defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ defined(__MIPSEL__) || defined(_MIPSEL) || defined(__MIPSEL) || \ - defined(__i386) || defined(__x86_64__) || defined(_M_IX86) || \ - defined(_M_X64) || defined(i386) || defined(_X86_) || defined(__i386__) || \ - defined(_X86_64_) || defined(_M_ARM) || defined(_M_ARM64) || \ - defined(__e2k__) + defined(_M_ARM) || defined(_M_ARM64) || defined(__e2k__) || \ + defined(__elbrus_4c__) || defined(__elbrus_8c__) || defined(__bfin__) || \ + defined(__BFIN__) || defined(__ia64__) || defined(_IA64) || \ + defined(__IA64__) || defined(__ia64) || defined(_M_IA64) || \ + defined(__itanium__) || defined(__ia32__) || defined(__CYGWIN__) || \ + defined(_WIN64) || defined(_WIN32) || defined(__TOS_WIN__) || \ + defined(__WINDOWS__) #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -#elif defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) || defined(__ARMEB__) || \ - defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(__MIPSEB__) || \ - defined(_MIPSEB) || defined(__MIPSEB) || defined(_M_IA64) + +#elif defined(__BIG_ENDIAN__) || \ + (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || \ + defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ + defined(__MIPSEB__) || defined(_MIPSEB) || defined(__MIPSEB) || \ + defined(__m68k__) || defined(M68000) || defined(__hppa__) || \ + defined(__hppa) || defined(__HPPA__) || defined(__sparc__) || \ + defined(__sparc) || defined(__370__) || defined(__THW_370__) || \ + defined(__s390__) || defined(__s390x__) || defined(__SYSC_ZARCH__) #define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__ + #else #error __BYTE_ORDER__ should be defined. -#endif -#endif -#endif /* __BYTE_ORDER__ || __ORDER_LITTLE_ENDIAN__ || __ORDER_BIG_ENDIAN__ */ +#endif /* Arch */ -#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ && \ - __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ -#error Unsupported byte order. #endif +#endif /* __BYTE_ORDER__ || __ORDER_LITTLE_ENDIAN__ || __ORDER_BIG_ENDIAN__ */ /*----------------------------------------------------------------------------*/ /* Memory/Compiler barriers, cache coherence */ @@ -286,17 +325,14 @@ static __inline void mdbx_memory_barrier(void) { /*----------------------------------------------------------------------------*/ /* Cache coherence and invalidation */ -#if defined(__i386__) || defined(__x86_64__) || defined(_M_AMD64) || \ - defined(_M_IX86) || defined(__i386) || defined(__amd64) || \ - defined(i386) || defined(__x86_64) || defined(_AMD64_) || defined(_M_X64) -#define MDBX_CACHE_IS_COHERENT 1 -#elif defined(__hppa) || defined(__hppa__) -#define MDBX_CACHE_IS_COHERENT 1 -#endif - #ifndef MDBX_CACHE_IS_COHERENT +#if defined(__ia32__) || defined(__e2k__) || defined(__hppa) || \ + defined(__hppa__) +#define MDBX_CACHE_IS_COHERENT 1 +#else #define MDBX_CACHE_IS_COHERENT 0 #endif +#endif /* MDBX_CACHE_IS_COHERENT */ #ifndef MDBX_CACHELINE_SIZE #if defined(SYSTEM_CACHE_ALIGNMENT_SIZE) @@ -308,29 +344,29 @@ static __inline void mdbx_memory_barrier(void) { #endif #endif /* MDBX_CACHELINE_SIZE */ -#ifndef __cache_aligned -#define __cache_aligned __aligned(MDBX_CACHELINE_SIZE) -#endif - #if MDBX_CACHE_IS_COHERENT #define mdbx_coherent_barrier() mdbx_compiler_barrier() #else #define mdbx_coherent_barrier() mdbx_memory_barrier() #endif -#if defined(__mips) && defined(__linux) +#if defined(__mips) || defined(__mips__) || defined(__mips64) || \ + defined(__mips64) || defined(_M_MRX000) || defined(_MIPS_) /* Only MIPS has explicit cache control */ -#include <asm/cachectl.h> +#include <sys/cachectl.h> #endif static __inline void mdbx_invalidate_cache(void *addr, size_t nbytes) { mdbx_coherent_barrier(); -#if defined(__mips) && defined(__linux) +#if defined(__mips) || defined(__mips__) || defined(__mips64) || \ + defined(__mips64) || defined(_M_MRX000) || defined(_MIPS_) +#if defined(DCACHE) /* MIPS has cache coherency issues. * Note: for any nbytes >= on-chip cache size, entire is flushed. */ cacheflush(addr, nbytes, DCACHE); -#elif defined(_M_MRX000) || defined(_MIPS_) +#else #error "Sorry, cacheflush() for MIPS not implemented" +#endif /* __mips__ */ #else /* LY: assume no relevant mmap/dcache issues. */ (void)addr; @@ -504,7 +540,13 @@ void mdbx_osal_jitter(bool tiny); #else #define MDBX_OSAL_LOCK pthread_mutex_t #define MDBX_OSAL_LOCK_SIGN UINT32_C(0x8017) -#endif +#endif /* MDBX_OSAL_LOCK */ + +#ifdef MDBX_OSAL_LOCK +#define MDBX_OSAL_LOCK_SIZE sizeof(MDBX_OSAL_LOCK) +#else +#define MDBX_OSAL_LOCK_SIZE 0 +#endif /* MDBX_OSAL_LOCK_SIZE */ int mdbx_lck_init(MDBX_env *env); @@ -516,8 +558,8 @@ void mdbx_lck_destroy(MDBX_env *env); int mdbx_rdt_lock(MDBX_env *env); void mdbx_rdt_unlock(MDBX_env *env); -int mdbx_txn_lock(MDBX_env *env, bool dontwait); -void mdbx_txn_unlock(MDBX_env *env); +LIBMDBX_API int mdbx_txn_lock(MDBX_env *env, bool dontwait); +LIBMDBX_API void mdbx_txn_unlock(MDBX_env *env); int mdbx_rpid_set(MDBX_env *env); int mdbx_rpid_clear(MDBX_env *env); diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c index 054e6e979e..681ee63d46 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c +++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c @@ -77,7 +77,7 @@ int exclusive = 2; int envflags = MDBX_RDONLY; MDBX_env *env; -MDBX_txn *txn, *locktxn; +MDBX_txn *txn; MDBX_envinfo envinfo; MDBX_stat envstat; size_t maxkeysize, userdb_count, skipped_subdb; @@ -763,6 +763,7 @@ int main(int argc, char *argv[]) { char *envname; int problems_maindb = 0, problems_freedb = 0, problems_meta = 0; int dont_traversal = 0; + bool locked = false; double elapsed; #if defined(_WIN32) || defined(_WIN64) @@ -836,8 +837,8 @@ int main(int argc, char *argv[]) { #endif /* !WINDOWS */ envname = argv[optind]; - print("Running mdbx_chk for '%s' in %s mode...\n", envname, - (envflags & MDBX_RDONLY) ? "read-only" : "write-lock"); + print("Running mdbx_chk for 'read-%s' in %s mode...\n", envname, + (envflags & MDBX_RDONLY) ? "read" : "write"); fflush(NULL); rc = mdbx_env_create(&env); @@ -862,13 +863,19 @@ int main(int argc, char *argv[]) { if (verbose) print(" - %s mode\n", exclusive ? "monopolistic" : "cooperative"); - if (!(envflags & MDBX_RDONLY)) { - rc = mdbx_txn_begin(env, NULL, 0, &locktxn); - if (rc) { - error("mdbx_txn_begin(lock-write) failed, error %d %s\n", rc, - mdbx_strerror(rc)); + if ((envflags & MDBX_RDONLY) == 0) { + rc = mdbx_txn_lock(env, false); + if (rc != MDBX_SUCCESS) { + error("mdbx_txn_lock failed, error %d %s\n", rc, mdbx_strerror(rc)); goto bailout; } + locked = true; + } + + rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn); + if (rc) { + error("mdbx_txn_begin() failed, error %d %s\n", rc, mdbx_strerror(rc)); + goto bailout; } rc = mdbx_env_get_maxkeysize(env); @@ -879,13 +886,6 @@ int main(int argc, char *argv[]) { } maxkeysize = rc; - rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn); - if (rc) { - error("mdbx_txn_begin(read-only) failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto bailout; - } - rc = mdbx_env_info(env, &envinfo, sizeof(envinfo)); if (rc) { error("mdbx_env_info failed, error %d %s\n", rc, mdbx_strerror(rc)); @@ -950,14 +950,14 @@ int main(int argc, char *argv[]) { if (verbose) print(" - performs full check recent-txn-id with meta-pages\n"); problems_meta += check_meta_head(true); - } else if (locktxn) { + } else if (locked) { if (verbose) print(" - performs lite check recent-txn-id with meta-pages (not a " "monopolistic mode)\n"); problems_meta += check_meta_head(false); } else if (verbose) { print(" - skip check recent-txn-id with meta-pages (monopolistic or " - "write-lock mode only)\n"); + "read-write mode only)\n"); } if (!dont_traversal) { @@ -1079,7 +1079,7 @@ int main(int argc, char *argv[]) { } if (problems_maindb == 0 && problems_freedb == 0) { - if (!dont_traversal && (exclusive || locktxn)) { + if (!dont_traversal && (exclusive || (envflags & MDBX_RDONLY) == 0)) { if (walk.pgcount != lastpgno - freedb_pages) { error("used pages mismatch (%" PRIu64 " != %" PRIu64 ")\n", walk.pgcount, lastpgno - freedb_pages); @@ -1090,7 +1090,7 @@ int main(int argc, char *argv[]) { } } else if (verbose) { print(" - skip check used and gc pages (btree-traversal with " - "monopolistic or write-lock mode only)\n"); + "monopolistic or read-write mode only)\n"); } if (!process_db(MAIN_DBI, NULL, handle_maindb, true)) { @@ -1102,8 +1102,8 @@ int main(int argc, char *argv[]) { bailout: if (txn) mdbx_txn_abort(txn); - if (locktxn) - mdbx_txn_abort(locktxn); + if (locked) + mdbx_txn_unlock(env); if (env) mdbx_env_close(env); fflush(NULL); diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/version.c b/plugins/Dbx_mdbx/src/libmdbx/src/version.c index 3b2ffdba76..c325be5878 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/src/version.c +++ b/plugins/Dbx_mdbx/src/libmdbx/src/version.c @@ -18,8 +18,8 @@ #error "API version mismatch!" #endif -#define MDBX_VERSION_RELEASE 0 -#define MDBX_VERSION_REVISION 0 +#define MDBX_VERSION_RELEASE 2 +#define MDBX_VERSION_REVISION 1 /*LIBMDBX_EXPORTS*/ const mdbx_version_info mdbx_version = { MDBX_VERSION_MAJOR, diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/base.h b/plugins/Dbx_mdbx/src/libmdbx/test/base.h index 63554e730d..f0c6043220 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/base.h +++ b/plugins/Dbx_mdbx/src/libmdbx/test/base.h @@ -76,14 +76,6 @@ #include <unordered_set> #include <vector> -#ifdef _MSC_VER -#include <intrin.h> -#endif - -#if defined(__i386__) || defined(__x86_64__) -#include <x86intrin.h> -#endif - #include "../mdbx.h" #include "../src/defs.h" #include "../src/osal.h" diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/config.cc b/plugins/Dbx_mdbx/src/libmdbx/test/config.cc index 2b9c6e5a0c..cbff68ce4e 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/config.cc +++ b/plugins/Dbx_mdbx/src/libmdbx/test/config.cc @@ -278,8 +278,6 @@ void dump(const char *title) { logging::local_suffix indent(title); for (auto i = global::actors.begin(); i != global::actors.end(); ++i) { - const std::string tableid = - i->space_id ? "MAINDB" : ("SUB#" + std::to_string(i->space_id)); log_info("#%u, testcase %s, space_id/table %u\n", i->actor_id, testcase2str(i->testcase), i->space_id); indent.push(); @@ -326,6 +324,11 @@ void dump(const char *title) { else log_info("no-delay\n"); + if (i->params.inject_writefaultn) + log_info("inject-writefault on %u ops\n", i->params.inject_writefaultn); + else + log_info("no-inject-writefault\n"); + log_info("limits: readers %u, tables %u\n", i->params.max_readers, i->params.max_tables); diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/config.h b/plugins/Dbx_mdbx/src/libmdbx/test/config.h index 5efd31100a..86f37fbed8 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/config.h +++ b/plugins/Dbx_mdbx/src/libmdbx/test/config.h @@ -218,6 +218,7 @@ struct actor_params_pod { unsigned delaystart; unsigned waitfor_nops; + unsigned inject_writefaultn; unsigned max_readers; unsigned max_tables; @@ -244,7 +245,7 @@ void dump(const char *title = "config-dump: "); struct actor_params : public config::actor_params_pod { std::string pathname_log; std::string pathname_db; - void set_defaults(void); + void set_defaults(const std::string &tmpdir); }; struct actor_config : public config::actor_config_pod { diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/log.cc b/plugins/Dbx_mdbx/src/libmdbx/test/log.cc index 8697effd8f..6ad33ced35 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/log.cc +++ b/plugins/Dbx_mdbx/src/libmdbx/test/log.cc @@ -285,3 +285,5 @@ void log_trouble(const char *where, const char *what, int errnum) { bool log_enabled(const logging::loglevel priority) { return (priority >= logging::level); } + +void log_flush(void) { fflushall(); } diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/log.h b/plugins/Dbx_mdbx/src/libmdbx/test/log.h index c321f3ce91..81eaf2ca91 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/log.h +++ b/plugins/Dbx_mdbx/src/libmdbx/test/log.h @@ -81,6 +81,7 @@ void __printf_args(1, 2) log_warning(const char *msg, ...); void __printf_args(1, 2) log_error(const char *msg, ...); void log_trouble(const char *where, const char *what, int errnum); +void log_flush(void); bool log_enabled(const logging::loglevel priority); #ifdef _DEBUG diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/main.cc b/plugins/Dbx_mdbx/src/libmdbx/test/main.cc index adf60aae62..98461a245d 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/main.cc +++ b/plugins/Dbx_mdbx/src/libmdbx/test/main.cc @@ -22,21 +22,16 @@ void __noreturn usage(void) { //----------------------------------------------------------------------------- -void actor_params::set_defaults(void) { +void actor_params::set_defaults(const std::string &tmpdir) { pathname_log = ""; loglevel = #ifdef NDEBUG - logging::notice; + logging::info; #else logging::trace; #endif - pathname_db = -#ifdef __linux__ - "/dev/shm/test_tmpdb.mdbx"; -#else - "test_tmpdb.mdbx"; -#endif + pathname_db = tmpdir + "mdbx-test.db"; mode_flags = MDBX_NOSUBDIR | MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NORDAHEAD | MDBX_NOMEMINIT | MDBX_COALESCE | MDBX_LIFORECLAIM; table_flags = MDBX_DUPSORT; @@ -65,6 +60,7 @@ void actor_params::set_defaults(void) { delaystart = 0; waitfor_nops = 0; + inject_writefaultn = 0; drop_table = false; @@ -135,7 +131,7 @@ int main(int argc, char *const argv[]) { : EXIT_FAILURE; actor_params params; - params.set_defaults(); + params.set_defaults(osal_tempdir()); global::config::dump_config = true; logging::setup((logging::loglevel)params.loglevel, "main"); unsigned last_space_id = 0; @@ -219,6 +215,9 @@ int main(int argc, char *const argv[]) { if (config::parse_option(argc, argv, narg, "wait4ops", params.waitfor_nops, config::decimal)) continue; + if (config::parse_option(argc, argv, narg, "inject-writefault", + params.inject_writefaultn, config::decimal)) + continue; if (config::parse_option(argc, argv, narg, "drop", params.drop_table)) continue; if (config::parse_option(argc, argv, narg, "dump-config", diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/osal-unix.cc b/plugins/Dbx_mdbx/src/libmdbx/test/osal-unix.cc index 7625e0f419..8132e267ef 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/osal-unix.cc +++ b/plugins/Dbx_mdbx/src/libmdbx/test/osal-unix.cc @@ -272,3 +272,22 @@ void osal_udelay(unsigned us) { } bool osal_istty(int fd) { return isatty(fd) == 1; } + +std::string osal_tempdir(void) { + const char *tempdir = getenv("TMPDIR"); + if (!tempdir) + tempdir = getenv("TMP"); + if (!tempdir) + tempdir = getenv("TEMPDIR"); + if (!tempdir) + tempdir = getenv("TEMP"); + if (tempdir) { + std::string dir(tempdir); + if (!dir.empty() && dir.at(dir.length() - 1) != '/') + dir.append("/"); + return dir; + } + if (access("/dev/shm/", R_OK | W_OK | X_OK) == 0) + return "/dev/shm/"; + return ""; +} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/osal-windows.cc b/plugins/Dbx_mdbx/src/libmdbx/test/osal-windows.cc index b1a8928cbb..5d2e51a66d 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/osal-windows.cc +++ b/plugins/Dbx_mdbx/src/libmdbx/test/osal-windows.cc @@ -305,3 +305,9 @@ void osal_udelay(unsigned us) { } bool osal_istty(int fd) { return _isatty(fd) != 0; } + +std::string osal_tempdir(void) { + char buf[MAX_PATH + 1]; + DWORD len = GetTempPathA(sizeof(buf), buf); + return std::string(buf, len); +} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/osal.h b/plugins/Dbx_mdbx/src/libmdbx/test/osal.h index f75aae3831..c27282a656 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/osal.h +++ b/plugins/Dbx_mdbx/src/libmdbx/test/osal.h @@ -31,6 +31,7 @@ int osal_delay(unsigned seconds); void osal_udelay(unsigned us); void osal_yield(void); bool osal_istty(int fd); +std::string osal_tempdir(void); #ifdef _MSC_VER #ifndef STDIN_FILENO diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/test.cc b/plugins/Dbx_mdbx/src/libmdbx/test/test.cc index 8700d74add..02986b3d1a 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/test.cc +++ b/plugins/Dbx_mdbx/src/libmdbx/test/test.cc @@ -123,7 +123,7 @@ void testcase::db_prepare() { if (config.params.loglevel <= logging::verbose) mdbx_dbg_opts |= MDBX_DBG_PRINT; int rc = mdbx_setup_debug(mdbx_dbg_opts, mdbx_logger); - log_info("set mdbx debug-opts: 0x%02x", rc); + log_trace("set mdbx debug-opts: 0x%02x", rc); MDBX_env *env = nullptr; rc = mdbx_env_create(&env); @@ -204,6 +204,7 @@ void testcase::txn_end(bool abort) { if (unlikely(rc != MDBX_SUCCESS)) failure_perror("mdbx_txn_abort()", rc); } else { + txn_inject_writefault(txn); int rc = mdbx_txn_commit(txn); if (unlikely(rc != MDBX_SUCCESS)) failure_perror("mdbx_txn_commit()", rc); @@ -218,6 +219,27 @@ void testcase::txn_restart(bool abort, bool readonly, unsigned flags) { txn_begin(readonly, flags); } +void testcase::txn_inject_writefault(void) { + if (txn_guard) + txn_inject_writefault(txn_guard.get()); +} + +void testcase::txn_inject_writefault(MDBX_txn *txn) { + if (config.params.inject_writefaultn && txn) { + if (config.params.inject_writefaultn <= nops_completed && + (mdbx_txn_flags(txn) & MDBX_RDONLY) == 0) { + log_info("== txn_inject_writefault(): got %u nops or more, inject FAULT", + config.params.inject_writefaultn); + log_flush(); +#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) + TerminateProcess(GetCurrentProcess(), 42); +#else + raise(SIGKILL); +#endif + } + } +} + bool testcase::wait4start() { if (config.wait4id) { log_trace(">> wait4start(%u)", config.wait4id); diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/test.h b/plugins/Dbx_mdbx/src/libmdbx/test/test.h index 4158aba457..ef1c4caa47 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/test.h +++ b/plugins/Dbx_mdbx/src/libmdbx/test/test.h @@ -107,6 +107,8 @@ protected: void txn_begin(bool readonly, unsigned flags = 0); void txn_end(bool abort); void txn_restart(bool abort, bool readonly, unsigned flags = 0); + void txn_inject_writefault(void); + void txn_inject_writefault(MDBX_txn *txn); void fetch_canary(); void update_canary(uint64_t increment); void kick_progress(bool active) const; diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/utils.cc b/plugins/Dbx_mdbx/src/libmdbx/test/utils.cc index 96866f61b7..0855c7eef3 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/utils.cc +++ b/plugins/Dbx_mdbx/src/libmdbx/test/utils.cc @@ -14,44 +14,10 @@ #include "test.h" #include <float.h> -#ifdef HAVE_IEEE754_H +#if defined(HAVE_IEEE754_H) || __has_include(<ieee754.h>) #include <ieee754.h> #endif -/* Compiler's includes for builtins/intrinsics */ -#if defined(_MSC_VER) || defined(__INTEL_COMPILER) -#include <intrin.h> -#elif __GNUC_PREREQ(4, 4) || defined(__clang__) -#if defined(__ia32__) || defined(__e2k__) -#include <x86intrin.h> -#endif /* __ia32__ */ -#if defined(__ia32__) -#include <cpuid.h> -#endif /* __ia32__ */ -#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) -#include <mbarrier.h> -#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \ - (defined(HP_IA64) || defined(__ia64)) -#include <machine/sys/inline.h> -#elif defined(__IBMC__) && defined(__powerpc) -#include <atomic.h> -#elif defined(_AIX) -#include <builtins.h> -#include <sys/atomic_op.h> -#elif (defined(__osf__) && defined(__DECC)) || defined(__alpha) -#include <c_asm.h> -#include <machine/builtins.h> -#elif defined(__MWERKS__) -/* CodeWarrior - troubles ? */ -#pragma gcc_extensions -#elif defined(__SNC__) -/* Sony PS3 - troubles ? */ -#elif defined(__hppa__) || defined(__hppa) -#include <machine/inline.h> -#else -#error Unsupported C compiler, please use GNU C 4.4 or newer -#endif /* Compiler */ - std::string format(const char *fmt, ...) { va_list ap, ones; va_start(ap, fmt); @@ -127,8 +93,22 @@ bool hex2data(const char *hex_begin, const char *hex_end, void *ptr, //----------------------------------------------------------------------------- +/* TODO: replace my 'libmera' fomr t1ha. */ uint64_t entropy_ticks(void) { +#if defined(EMSCRIPTEN) + return (uint64_t)emscripten_get_now(); +#endif /* EMSCRIPTEN */ + +#if defined(__APPLE__) || defined(__MACH__) + return mach_absolute_time(); +#endif /* defined(__APPLE__) || defined(__MACH__) */ + +#if defined(__sun__) || defined(__sun) + return gethrtime(); +#endif /* __sun__ */ + #if defined(__GNUC__) || defined(__clang__) + #if defined(__ia64__) uint64_t ticks; __asm __volatile("mov %0=ar.itc" : "=r"(ticks)); @@ -145,29 +125,81 @@ uint64_t entropy_ticks(void) { uint64_t ticks; __asm __volatile("rpcc %0" : "=r"(ticks)); return ticks; -#elif defined(__sparc_v9__) - uint64_t ticks; - __asm __volatile("rd %%tick, %0" : "=r"(ticks)); - return ticks; -#elif defined(__powerpc64__) || defined(__ppc64__) +#elif defined(__sparc__) || defined(__sparc) || defined(__sparc64__) || \ + defined(__sparc64) || defined(__sparc_v8plus__) || \ + defined(__sparc_v8plus) || defined(__sparc_v8plusa__) || \ + defined(__sparc_v8plusa) || defined(__sparc_v9__) || defined(__sparc_v9) + + union { + uint64_t u64; + struct { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + uint32_t h, l; +#else + uint32_t l, h; +#endif + } u32; + } cycles; + +#if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || \ + defined(__sparc_v9__) || defined(__sparc_v8plus) || \ + defined(__sparc_v8plusa) || defined(__sparc_v9) + +#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul || \ + defined(__sparc64__) || defined(__sparc64) + __asm __volatile("rd %%tick, %0" : "=r"(cycles.u64)); +#else + __asm __volatile("rd %%tick, %1; srlx %1, 32, %0" + : "=r"(cycles.u32.h), "=r"(cycles.u32.l)); +#endif /* __sparc64__ */ + +#else + __asm __volatile(".byte 0x83, 0x41, 0x00, 0x00; mov %%g1, %0" + : "=r"(cycles.u64) + : + : "%g1"); +#endif /* __sparc8plus__ || __sparc_v9__ */ + return cycles.u64; + +#elif (defined(__powerpc64__) || defined(__ppc64__) || defined(__ppc64) || \ + defined(__powerpc64)) uint64_t ticks; __asm __volatile("mfspr %0, 268" : "=r"(ticks)); return ticks; -#elif defined(__ppc__) || defined(__powerpc__) - unsigned tbl, tbu; - - /* LY: Here not a problem if a high-part (tbu) - * would been updated during reading. */ - __asm __volatile("mftb %0" : "=r"(tbl)); - __asm __volatile("mftbu %0" : "=r"(tbu)); - - return (((uin64_t)tbu0) << 32) | tbl; +#elif (defined(__powerpc__) || defined(__ppc__) || defined(__powerpc) || \ + defined(__ppc)) +#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul + uint64_t ticks; + __asm __volatile("mftb %0" : "=r"(ticks)); + *now = ticks; +#else + uint64_t ticks; + uint32_t low, high_before, high_after; + __asm __volatile("mftbu %0; mftb %1; mftbu %2" + : "=r"(high_before), "=r"(low), "=r"(high_after)); + ticks = (uint64_t)high_after << 32; + ticks |= low & /* zeroes if high part has changed */ + ~(high_before - high_after); +#endif +#elif defined(__aarch64__) || (defined(__ARM_ARCH) && __ARM_ARCH > 7) + uint64_t virtual_timer; + __asm __volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer)); + return virtual_timer; +#elif defined(__ARM_ARCH) && __ARM_ARCH > 5 && __ARM_ARCH < 8 + unsigned long pmccntr; + __asm __volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr)); + return pmccntr; +#elif defined(__mips__) || defined(__mips) || defined(_R4000) + unsigned count; + __asm __volatile("rdhwr %0, $2" : "=r"(count)); + return count; #endif /* arch selector */ #endif /* __GNUC__ || __clang__ */ -#if defined(__e2k__) || defined(__elbrus__) || defined(_M_IX86) || \ - defined(_M_X64) || defined(__x86_64__) || defined(__i386__) +#if defined(__e2k__) || defined(__ia32__) return __rdtsc(); +#elif defined(_M_ARM) + return __rdpmccntr64(); #elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) LARGE_INTEGER PerformanceCount; if (QueryPerformanceCounter(&PerformanceCount)) diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/utils.h b/plugins/Dbx_mdbx/src/libmdbx/test/utils.h index 176823c60b..5d62909fd5 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/test/utils.h +++ b/plugins/Dbx_mdbx/src/libmdbx/test/utils.h @@ -17,33 +17,8 @@ #if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \ !defined(__ORDER_BIG_ENDIAN__) -#ifndef _MSC_VER -#include <sys/param.h> /* for endianness */ -#endif -#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN) -#define __ORDER_LITTLE_ENDIAN__ __LITTLE_ENDIAN -#define __ORDER_BIG_ENDIAN__ __BIG_ENDIAN -#define __BYTE_ORDER__ __BYTE_ORDER -#else -#define __ORDER_LITTLE_ENDIAN__ 1234 -#define __ORDER_BIG_ENDIAN__ 4321 -#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN) || \ - defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ - defined(__MIPSEL__) || defined(_MIPSEL) || defined(__MIPSEL) || \ - defined(__i386) || defined(__x86_64__) || defined(_M_IX86) || \ - defined(_M_X64) || defined(i386) || defined(_X86_) || defined(__i386__) || \ - defined(_X86_64_) || defined(_M_ARM) || defined(_M_ARM64) || \ - defined(__e2k__) -#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -#elif defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) || defined(__ARMEB__) || \ - defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(__MIPSEB__) || \ - defined(_MIPSEB) || defined(__MIPSEB) || defined(_M_IA64) -#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__ -#else #error __BYTE_ORDER__ should be defined. #endif -#endif -#endif #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ && \ __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ @@ -274,7 +249,7 @@ static __inline void memory_barrier(void) { #elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */ #if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) __mf(); -#elif defined(__i386__) || defined(__x86_64__) +#elif defined(__ia32__) _mm_mfence(); #else #error "Unknown target for Intel Compiler, please report to us." @@ -293,8 +268,7 @@ static __inline void memory_barrier(void) { } static __inline void cpu_relax() { -#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || \ - defined(_M_X64) +#if defined(__ia32__) _mm_pause(); #elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || \ defined(YieldProcessor) |