mirror of
https://github.com/isar/libmdbx.git
synced 2024-12-29 09:58:48 +08:00
776 lines
26 KiB
C++
776 lines
26 KiB
C++
/*
|
|
* Copyright 2015-2024 Leonid Yuriev <leo@yuriev.ru>
|
|
* and other libmdbx authors: please see AUTHORS file.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted only as authorized by the OpenLDAP
|
|
* Public License.
|
|
*
|
|
* A copy of this license is available in the file LICENSE in the
|
|
* top-level directory of the distribution or, alternatively, at
|
|
* <http://www.OpenLDAP.org/license.html>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/* Microsoft compiler generates a lot of warning for self includes... */
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(push, 1)
|
|
#pragma warning(disable : 4548) /* expression before comma has no effect; \
|
|
expected expression with side - effect */
|
|
#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \
|
|
* semantics are not enabled. Specify /EHsc */
|
|
#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \
|
|
* mode specified; termination on exception is \
|
|
* not guaranteed. Specify /EHsc */
|
|
#endif /* _MSC_VER (warnings) */
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
#if !defined(_CRT_SECURE_NO_WARNINGS)
|
|
#define _CRT_SECURE_NO_WARNINGS
|
|
#endif /* _CRT_SECURE_NO_WARNINGS */
|
|
#if !defined(_NO_CRT_STDIO_INLINE) && MDBX_BUILD_SHARED_LIBRARY && \
|
|
!defined(xMDBX_TOOLS) && MDBX_WITHOUT_MSVC_CRT
|
|
#define _NO_CRT_STDIO_INLINE
|
|
#endif
|
|
#elif !defined(_POSIX_C_SOURCE)
|
|
#define _POSIX_C_SOURCE 200809L
|
|
#endif /* Windows */
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/* basic C99 includes */
|
|
#include <inttypes.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <fcntl.h>
|
|
#include <limits.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
#if (-6 & 5) || CHAR_BIT != 8 || UINT_MAX < 0xffffffff || ULONG_MAX % 0xFFFF
|
|
#error \
|
|
"Sanity checking failed: Two's complement, reasonably sized integer types"
|
|
#endif
|
|
|
|
#ifndef SSIZE_MAX
|
|
#define SSIZE_MAX INTPTR_MAX
|
|
#endif
|
|
|
|
#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul || defined(_WIN64)
|
|
#define MDBX_WORDBITS 64
|
|
#else
|
|
#define MDBX_WORDBITS 32
|
|
#endif /* MDBX_WORDBITS */
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/* feature testing */
|
|
|
|
#ifndef __has_warning
|
|
#define __has_warning(x) (0)
|
|
#endif
|
|
|
|
#ifndef __has_include
|
|
#define __has_include(x) (0)
|
|
#endif
|
|
|
|
#ifndef __has_feature
|
|
#define __has_feature(x) (0)
|
|
#endif
|
|
|
|
#ifndef __has_extension
|
|
#define __has_extension(x) (0)
|
|
#endif
|
|
|
|
#if __has_feature(thread_sanitizer)
|
|
#define __SANITIZE_THREAD__ 1
|
|
#endif
|
|
|
|
#if __has_feature(address_sanitizer)
|
|
#define __SANITIZE_ADDRESS__ 1
|
|
#endif
|
|
|
|
#ifndef __GNUC_PREREQ
|
|
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
|
#define __GNUC_PREREQ(maj, min) \
|
|
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
|
#else
|
|
#define __GNUC_PREREQ(maj, min) (0)
|
|
#endif
|
|
#endif /* __GNUC_PREREQ */
|
|
|
|
#ifndef __CLANG_PREREQ
|
|
#ifdef __clang__
|
|
#define __CLANG_PREREQ(maj, min) \
|
|
((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min))
|
|
#else
|
|
#define __CLANG_PREREQ(maj, min) (0)
|
|
#endif
|
|
#endif /* __CLANG_PREREQ */
|
|
|
|
#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 */
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/* C11' alignas() */
|
|
|
|
#if __has_include(<stdalign.h>)
|
|
#include <stdalign.h>
|
|
#endif
|
|
#if defined(alignas) || defined(__cplusplus)
|
|
#define MDBX_ALIGNAS(N) alignas(N)
|
|
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
|
#define MDBX_ALIGNAS(N) _Alignas(N)
|
|
#elif defined(_MSC_VER)
|
|
#define MDBX_ALIGNAS(N) __declspec(align(N))
|
|
#elif __has_attribute(__aligned__) || defined(__GNUC__)
|
|
#define MDBX_ALIGNAS(N) __attribute__((__aligned__(N)))
|
|
#else
|
|
#error "FIXME: Required alignas() or equivalent."
|
|
#endif /* MDBX_ALIGNAS */
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/* Systems macros and includes */
|
|
|
|
#ifndef __extern_C
|
|
#ifdef __cplusplus
|
|
#define __extern_C extern "C"
|
|
#else
|
|
#define __extern_C
|
|
#endif
|
|
#endif /* __extern_C */
|
|
|
|
#if !defined(nullptr) && !defined(__cplusplus) || \
|
|
(__cplusplus < 201103L && !defined(_MSC_VER))
|
|
#define nullptr NULL
|
|
#endif
|
|
|
|
#if defined(__APPLE__) || defined(_DARWIN_C_SOURCE)
|
|
#include <AvailabilityMacros.h>
|
|
#include <TargetConditionals.h>
|
|
#ifndef MAC_OS_X_VERSION_MIN_REQUIRED
|
|
#define MAC_OS_X_VERSION_MIN_REQUIRED 1070 /* Mac OS X 10.7, 2011 */
|
|
#endif
|
|
#endif /* Apple OSX & iOS */
|
|
|
|
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
|
|
defined(__BSD__) || defined(__bsdi__) || defined(__DragonFly__) || \
|
|
defined(__APPLE__) || defined(__MACH__)
|
|
#include <sys/cdefs.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/sysctl.h>
|
|
#include <sys/types.h>
|
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
#include <vm/vm_param.h>
|
|
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
|
#include <uvm/uvm_param.h>
|
|
#else
|
|
#define SYSCTL_LEGACY_NONCONST_MIB
|
|
#endif
|
|
#ifndef __MACH__
|
|
#include <sys/vmmeter.h>
|
|
#endif
|
|
#else
|
|
#include <malloc.h>
|
|
#if !(defined(__sun) || defined(__SVR4) || defined(__svr4__) || \
|
|
defined(_WIN32) || defined(_WIN64))
|
|
#include <mntent.h>
|
|
#endif /* !Solaris */
|
|
#endif /* !xBSD */
|
|
|
|
#if defined(__FreeBSD__) || __has_include(<malloc_np.h>)
|
|
#include <malloc_np.h>
|
|
#endif
|
|
|
|
#if defined(__APPLE__) || defined(__MACH__) || __has_include(<malloc/malloc.h>)
|
|
#include <malloc/malloc.h>
|
|
#endif /* MacOS */
|
|
|
|
#if defined(__MACH__)
|
|
#include <mach/host_info.h>
|
|
#include <mach/mach_host.h>
|
|
#include <mach/mach_port.h>
|
|
#include <uuid/uuid.h>
|
|
#endif
|
|
|
|
#if defined(__linux__) || defined(__gnu_linux__)
|
|
#include <sched.h>
|
|
#include <sys/sendfile.h>
|
|
#include <sys/statfs.h>
|
|
#endif /* Linux */
|
|
|
|
#ifndef _XOPEN_SOURCE
|
|
#define _XOPEN_SOURCE 0
|
|
#endif
|
|
|
|
#ifndef _XOPEN_SOURCE_EXTENDED
|
|
#define _XOPEN_SOURCE_EXTENDED 0
|
|
#else
|
|
#include <utmpx.h>
|
|
#endif /* _XOPEN_SOURCE_EXTENDED */
|
|
|
|
#if defined(__sun) || defined(__SVR4) || defined(__svr4__)
|
|
#include <kstat.h>
|
|
#include <sys/mnttab.h>
|
|
/* On Solaris, it's easier to add a missing prototype rather than find a
|
|
* combination of #defines that break nothing. */
|
|
__extern_C key_t ftok(const char *, int);
|
|
#endif /* SunOS/Solaris */
|
|
|
|
#if defined(_WIN32) || defined(_WIN64) /*-------------------------------------*/
|
|
|
|
#ifndef _WIN32_WINNT
|
|
#define _WIN32_WINNT 0x0601 /* Windows 7 */
|
|
#elif _WIN32_WINNT < 0x0500
|
|
#error At least 'Windows 2000' API is required for libmdbx.
|
|
#endif /* _WIN32_WINNT */
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif /* WIN32_LEAN_AND_MEAN */
|
|
#include <excpt.h>
|
|
#include <tlhelp32.h>
|
|
#include <windows.h>
|
|
#include <winnt.h>
|
|
#include <winternl.h>
|
|
|
|
#else /*----------------------------------------------------------------------*/
|
|
|
|
#include <unistd.h>
|
|
#if !defined(_POSIX_MAPPED_FILES) || _POSIX_MAPPED_FILES < 1
|
|
#error "libmdbx requires the _POSIX_MAPPED_FILES feature"
|
|
#endif /* _POSIX_MAPPED_FILES */
|
|
|
|
#include <pthread.h>
|
|
#include <semaphore.h>
|
|
#include <signal.h>
|
|
#include <sys/file.h>
|
|
#include <sys/ipc.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/param.h>
|
|
#include <sys/resource.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/statvfs.h>
|
|
#include <sys/time.h>
|
|
#include <sys/uio.h>
|
|
|
|
#endif /*---------------------------------------------------------------------*/
|
|
|
|
#if defined(__ANDROID_API__) || defined(ANDROID)
|
|
#include <android/log.h>
|
|
#if __ANDROID_API__ >= 21
|
|
#include <sys/sendfile.h>
|
|
#endif
|
|
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS != MDBX_WORDBITS
|
|
#error "_FILE_OFFSET_BITS != MDBX_WORDBITS" (_FILE_OFFSET_BITS != MDBX_WORDBITS)
|
|
#elif defined(__FILE_OFFSET_BITS) && __FILE_OFFSET_BITS != MDBX_WORDBITS
|
|
#error "__FILE_OFFSET_BITS != MDBX_WORDBITS" (__FILE_OFFSET_BITS != MDBX_WORDBITS)
|
|
#endif
|
|
#endif /* Android */
|
|
|
|
#if defined(HAVE_SYS_STAT_H) || __has_include(<sys/stat.h>)
|
|
#include <sys/stat.h>
|
|
#endif
|
|
#if defined(HAVE_SYS_TYPES_H) || __has_include(<sys/types.h>)
|
|
#include <sys/types.h>
|
|
#endif
|
|
#if defined(HAVE_SYS_FILE_H) || __has_include(<sys/file.h>)
|
|
#include <sys/file.h>
|
|
#endif
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/* Byteorder */
|
|
|
|
#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 */
|
|
#define __ia32__ 1
|
|
#endif /* __ia32__ */
|
|
#if !defined(__amd64__) && \
|
|
(defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || \
|
|
defined(_M_X64) || defined(_M_AMD64))
|
|
/* LY: define trusty __amd64__ for all AMD64/x86-64 arch */
|
|
#define __amd64__ 1
|
|
#endif /* __amd64__ */
|
|
#endif /* all x86 */
|
|
|
|
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
|
|
!defined(__ORDER_BIG_ENDIAN__)
|
|
|
|
#if defined(__GLIBC__) || defined(__GNU_LIBRARY__) || \
|
|
defined(__ANDROID_API__) || defined(HAVE_ENDIAN_H) || __has_include(<endian.h>)
|
|
#include <endian.h>
|
|
#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(HAVE_SYS_PARAM_H) || __has_include(<sys/param.h>)
|
|
#include <sys/param.h>
|
|
#endif /* OS */
|
|
|
|
#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) && !defined(_BIG_ENDIAN)) || \
|
|
defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
|
|
defined(__MIPSEL__) || defined(_MIPSEL) || defined(__MIPSEL) || \
|
|
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(_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 /* Arch */
|
|
|
|
#endif
|
|
#endif /* __BYTE_ORDER__ || __ORDER_LITTLE_ENDIAN__ || __ORDER_BIG_ENDIAN__ */
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/* Availability of CMOV or equivalent */
|
|
|
|
#ifndef MDBX_HAVE_CMOV
|
|
#if defined(__e2k__)
|
|
#define MDBX_HAVE_CMOV 1
|
|
#elif defined(__thumb2__) || defined(__thumb2)
|
|
#define MDBX_HAVE_CMOV 1
|
|
#elif defined(__thumb__) || defined(__thumb) || defined(__TARGET_ARCH_THUMB)
|
|
#define MDBX_HAVE_CMOV 0
|
|
#elif defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || \
|
|
defined(__aarch64) || defined(__arm__) || defined(__arm) || \
|
|
defined(__CC_ARM)
|
|
#define MDBX_HAVE_CMOV 1
|
|
#elif (defined(__riscv__) || defined(__riscv64)) && \
|
|
(defined(__riscv_b) || defined(__riscv_bitmanip))
|
|
#define MDBX_HAVE_CMOV 1
|
|
#elif defined(i686) || defined(__i686) || defined(__i686__) || \
|
|
(defined(_M_IX86) && _M_IX86 > 600) || defined(__x86_64) || \
|
|
defined(__x86_64__) || defined(__amd64__) || defined(__amd64) || \
|
|
defined(_M_X64) || defined(_M_AMD64)
|
|
#define MDBX_HAVE_CMOV 1
|
|
#else
|
|
#define MDBX_HAVE_CMOV 0
|
|
#endif
|
|
#endif /* MDBX_HAVE_CMOV */
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/* 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(__e2k__)
|
|
#include <e2kintrin.h>
|
|
#include <x86intrin.h>
|
|
#endif /* __e2k__ */
|
|
#if defined(__ia32__)
|
|
#include <cpuid.h>
|
|
#include <x86intrin.h>
|
|
#endif /* __ia32__ */
|
|
#ifdef __ARM_NEON
|
|
#include <arm_neon.h>
|
|
#endif
|
|
#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 */
|
|
|
|
#if !defined(__noop) && !defined(_MSC_VER)
|
|
#define __noop \
|
|
do { \
|
|
} while (0)
|
|
#endif /* __noop */
|
|
|
|
#if defined(__fallthrough) && \
|
|
(defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__))
|
|
#undef __fallthrough
|
|
#endif /* __fallthrough workaround for MinGW */
|
|
|
|
#ifndef __fallthrough
|
|
#if defined(__cplusplus) && (__has_cpp_attribute(fallthrough) && \
|
|
(!defined(__clang__) || __clang__ > 4)) || \
|
|
__cplusplus >= 201703L
|
|
#define __fallthrough [[fallthrough]]
|
|
#elif __GNUC_PREREQ(8, 0) && defined(__cplusplus) && __cplusplus >= 201103L
|
|
#define __fallthrough [[fallthrough]]
|
|
#elif __GNUC_PREREQ(7, 0) && \
|
|
(!defined(__LCC__) || (__LCC__ == 124 && __LCC_MINOR__ >= 12) || \
|
|
(__LCC__ == 125 && __LCC_MINOR__ >= 5) || (__LCC__ >= 126))
|
|
#define __fallthrough __attribute__((__fallthrough__))
|
|
#elif defined(__clang__) && defined(__cplusplus) && __cplusplus >= 201103L && \
|
|
__has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
|
|
#define __fallthrough [[clang::fallthrough]]
|
|
#else
|
|
#define __fallthrough
|
|
#endif
|
|
#endif /* __fallthrough */
|
|
|
|
#ifndef __unreachable
|
|
#if __GNUC_PREREQ(4, 5) || __has_builtin(__builtin_unreachable)
|
|
#define __unreachable() __builtin_unreachable()
|
|
#elif defined(_MSC_VER)
|
|
#define __unreachable() __assume(0)
|
|
#else
|
|
#define __unreachable() \
|
|
do { \
|
|
} while (1)
|
|
#endif
|
|
#endif /* __unreachable */
|
|
|
|
#ifndef __prefetch
|
|
#if defined(__GNUC__) || defined(__clang__) || __has_builtin(__builtin_prefetch)
|
|
#define __prefetch(ptr) __builtin_prefetch(ptr)
|
|
#else
|
|
#define __prefetch(ptr) \
|
|
do { \
|
|
(void)(ptr); \
|
|
} while (0)
|
|
#endif
|
|
#endif /* __prefetch */
|
|
|
|
#ifndef offsetof
|
|
#define offsetof(type, member) __builtin_offsetof(type, member)
|
|
#endif /* offsetof */
|
|
|
|
#ifndef container_of
|
|
#define container_of(ptr, type, member) \
|
|
((type *)((char *)(ptr)-offsetof(type, member)))
|
|
#endif /* container_of */
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
#ifndef __always_inline
|
|
#if defined(__GNUC__) || __has_attribute(__always_inline__)
|
|
#define __always_inline __inline __attribute__((__always_inline__))
|
|
#elif defined(_MSC_VER)
|
|
#define __always_inline __forceinline
|
|
#else
|
|
#define __always_inline
|
|
#endif
|
|
#endif /* __always_inline */
|
|
|
|
#ifndef __noinline
|
|
#if defined(__GNUC__) || __has_attribute(__noinline__)
|
|
#define __noinline __attribute__((__noinline__))
|
|
#elif defined(_MSC_VER)
|
|
#define __noinline __declspec(noinline)
|
|
#else
|
|
#define __noinline
|
|
#endif
|
|
#endif /* __noinline */
|
|
|
|
#ifndef __must_check_result
|
|
#if defined(__GNUC__) || __has_attribute(__warn_unused_result__)
|
|
#define __must_check_result __attribute__((__warn_unused_result__))
|
|
#else
|
|
#define __must_check_result
|
|
#endif
|
|
#endif /* __must_check_result */
|
|
|
|
#ifndef __nothrow
|
|
#if defined(__cplusplus)
|
|
#if __cplusplus < 201703L
|
|
#define __nothrow throw()
|
|
#else
|
|
#define __nothrow noexcept(true)
|
|
#endif /* __cplusplus */
|
|
#elif defined(__GNUC__) || __has_attribute(__nothrow__)
|
|
#define __nothrow __attribute__((__nothrow__))
|
|
#elif defined(_MSC_VER) && defined(__cplusplus)
|
|
#define __nothrow __declspec(nothrow)
|
|
#else
|
|
#define __nothrow
|
|
#endif
|
|
#endif /* __nothrow */
|
|
|
|
#ifndef __hidden
|
|
#if defined(__GNUC__) || __has_attribute(__visibility__)
|
|
#define __hidden __attribute__((__visibility__("hidden")))
|
|
#else
|
|
#define __hidden
|
|
#endif
|
|
#endif /* __hidden */
|
|
|
|
#ifndef __optimize
|
|
#if defined(__OPTIMIZE__)
|
|
#if (defined(__GNUC__) && !defined(__clang__)) || __has_attribute(__optimize__)
|
|
#define __optimize(ops) __attribute__((__optimize__(ops)))
|
|
#else
|
|
#define __optimize(ops)
|
|
#endif
|
|
#else
|
|
#define __optimize(ops)
|
|
#endif
|
|
#endif /* __optimize */
|
|
|
|
#ifndef __hot
|
|
#if defined(__OPTIMIZE__)
|
|
#if defined(__clang__) && !__has_attribute(__hot__) && \
|
|
__has_attribute(__section__) && \
|
|
(defined(__linux__) || defined(__gnu_linux__))
|
|
/* just put frequently used functions in separate section */
|
|
#define __hot __attribute__((__section__("text.hot"))) __optimize("O3")
|
|
#elif defined(__GNUC__) || __has_attribute(__hot__)
|
|
#define __hot __attribute__((__hot__))
|
|
#else
|
|
#define __hot __optimize("O3")
|
|
#endif
|
|
#else
|
|
#define __hot
|
|
#endif
|
|
#endif /* __hot */
|
|
|
|
#ifndef __cold
|
|
#if defined(__OPTIMIZE__)
|
|
#if defined(__clang__) && !__has_attribute(__cold__) && \
|
|
__has_attribute(__section__) && \
|
|
(defined(__linux__) || defined(__gnu_linux__))
|
|
/* just put infrequently used functions in separate section */
|
|
#define __cold __attribute__((__section__("text.unlikely"))) __optimize("Os")
|
|
#elif defined(__GNUC__) || __has_attribute(__cold__)
|
|
#define __cold __attribute__((__cold__))
|
|
#else
|
|
#define __cold __optimize("Os")
|
|
#endif
|
|
#else
|
|
#define __cold
|
|
#endif
|
|
#endif /* __cold */
|
|
|
|
#ifndef __flatten
|
|
#if defined(__OPTIMIZE__) && (defined(__GNUC__) || __has_attribute(__flatten__))
|
|
#define __flatten __attribute__((__flatten__))
|
|
#else
|
|
#define __flatten
|
|
#endif
|
|
#endif /* __flatten */
|
|
|
|
#ifndef likely
|
|
#if (defined(__GNUC__) || __has_builtin(__builtin_expect)) && \
|
|
!defined(__COVERITY__)
|
|
#define likely(cond) __builtin_expect(!!(cond), 1)
|
|
#else
|
|
#define likely(x) (!!(x))
|
|
#endif
|
|
#endif /* likely */
|
|
|
|
#ifndef unlikely
|
|
#if (defined(__GNUC__) || __has_builtin(__builtin_expect)) && \
|
|
!defined(__COVERITY__)
|
|
#define unlikely(cond) __builtin_expect(!!(cond), 0)
|
|
#else
|
|
#define unlikely(x) (!!(x))
|
|
#endif
|
|
#endif /* unlikely */
|
|
|
|
#ifndef __anonymous_struct_extension__
|
|
#if defined(__GNUC__)
|
|
#define __anonymous_struct_extension__ __extension__
|
|
#else
|
|
#define __anonymous_struct_extension__
|
|
#endif
|
|
#endif /* __anonymous_struct_extension__ */
|
|
|
|
#ifndef expect_with_probability
|
|
#if defined(__builtin_expect_with_probability) || \
|
|
__has_builtin(__builtin_expect_with_probability) || __GNUC_PREREQ(9, 0)
|
|
#define expect_with_probability(expr, value, prob) \
|
|
__builtin_expect_with_probability(expr, value, prob)
|
|
#else
|
|
#define expect_with_probability(expr, value, prob) (expr)
|
|
#endif
|
|
#endif /* expect_with_probability */
|
|
|
|
#ifndef MDBX_WEAK_IMPORT_ATTRIBUTE
|
|
#ifdef WEAK_IMPORT_ATTRIBUTE
|
|
#define MDBX_WEAK_IMPORT_ATTRIBUTE WEAK_IMPORT_ATTRIBUTE
|
|
#elif __has_attribute(__weak__) && __has_attribute(__weak_import__)
|
|
#define MDBX_WEAK_IMPORT_ATTRIBUTE __attribute__((__weak__, __weak_import__))
|
|
#elif __has_attribute(__weak__) || \
|
|
(defined(__GNUC__) && __GNUC__ >= 4 && defined(__ELF__))
|
|
#define MDBX_WEAK_IMPORT_ATTRIBUTE __attribute__((__weak__))
|
|
#else
|
|
#define MDBX_WEAK_IMPORT_ATTRIBUTE
|
|
#endif
|
|
#endif /* MDBX_WEAK_IMPORT_ATTRIBUTE */
|
|
|
|
#ifndef MDBX_GOOFY_MSVC_STATIC_ANALYZER
|
|
#ifdef _PREFAST_
|
|
#define MDBX_GOOFY_MSVC_STATIC_ANALYZER 1
|
|
#else
|
|
#define MDBX_GOOFY_MSVC_STATIC_ANALYZER 0
|
|
#endif
|
|
#endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */
|
|
|
|
#if MDBX_GOOFY_MSVC_STATIC_ANALYZER || (defined(_MSC_VER) && _MSC_VER > 1919)
|
|
#define MDBX_ANALYSIS_ASSUME(expr) __analysis_assume(expr)
|
|
#ifdef _PREFAST_
|
|
#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \
|
|
__pragma(prefast(suppress : warn_id))
|
|
#else
|
|
#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \
|
|
__pragma(warning(suppress : warn_id))
|
|
#endif
|
|
#else
|
|
#define MDBX_ANALYSIS_ASSUME(expr) assert(expr)
|
|
#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id)
|
|
#endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
#if defined(ENABLE_MEMCHECK)
|
|
#include <valgrind/memcheck.h>
|
|
#ifndef VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE
|
|
/* LY: available since Valgrind 3.10 */
|
|
#define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a, s)
|
|
#define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a, s)
|
|
#endif
|
|
#elif !defined(RUNNING_ON_VALGRIND)
|
|
#define VALGRIND_CREATE_MEMPOOL(h, r, z)
|
|
#define VALGRIND_DESTROY_MEMPOOL(h)
|
|
#define VALGRIND_MEMPOOL_TRIM(h, a, s)
|
|
#define VALGRIND_MEMPOOL_ALLOC(h, a, s)
|
|
#define VALGRIND_MEMPOOL_FREE(h, a)
|
|
#define VALGRIND_MEMPOOL_CHANGE(h, a, b, s)
|
|
#define VALGRIND_MAKE_MEM_NOACCESS(a, s)
|
|
#define VALGRIND_MAKE_MEM_DEFINED(a, s)
|
|
#define VALGRIND_MAKE_MEM_UNDEFINED(a, s)
|
|
#define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a, s)
|
|
#define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a, s)
|
|
#define VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a, s) (0)
|
|
#define VALGRIND_CHECK_MEM_IS_DEFINED(a, s) (0)
|
|
#define RUNNING_ON_VALGRIND (0)
|
|
#endif /* ENABLE_MEMCHECK */
|
|
|
|
#ifdef __SANITIZE_ADDRESS__
|
|
#include <sanitizer/asan_interface.h>
|
|
#elif !defined(ASAN_POISON_MEMORY_REGION)
|
|
#define ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
|
|
#define ASAN_UNPOISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
|
|
#endif /* __SANITIZE_ADDRESS__ */
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
#ifndef ARRAY_LENGTH
|
|
#ifdef __cplusplus
|
|
template <typename T, size_t N> char (&__ArraySizeHelper(T (&array)[N]))[N];
|
|
#define ARRAY_LENGTH(array) (sizeof(::__ArraySizeHelper(array)))
|
|
#else
|
|
#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
|
|
#endif
|
|
#endif /* ARRAY_LENGTH */
|
|
|
|
#ifndef ARRAY_END
|
|
#define ARRAY_END(array) (&array[ARRAY_LENGTH(array)])
|
|
#endif /* ARRAY_END */
|
|
|
|
#define CONCAT(a, b) a##b
|
|
#define XCONCAT(a, b) CONCAT(a, b)
|
|
|
|
#define MDBX_TETRAD(a, b, c, d) \
|
|
((uint32_t)(a) << 24 | (uint32_t)(b) << 16 | (uint32_t)(c) << 8 | (d))
|
|
|
|
#define MDBX_STRING_TETRAD(str) MDBX_TETRAD(str[0], str[1], str[2], str[3])
|
|
|
|
#define FIXME "FIXME: " __FILE__ ", " MDBX_STRINGIFY(__LINE__)
|
|
|
|
#ifndef STATIC_ASSERT_MSG
|
|
#if defined(static_assert)
|
|
#define STATIC_ASSERT_MSG(expr, msg) static_assert(expr, msg)
|
|
#elif defined(_STATIC_ASSERT)
|
|
#define STATIC_ASSERT_MSG(expr, msg) _STATIC_ASSERT(expr)
|
|
#elif defined(_MSC_VER)
|
|
#include <crtdbg.h>
|
|
#define STATIC_ASSERT_MSG(expr, msg) _STATIC_ASSERT(expr)
|
|
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
|
|
__has_feature(c_static_assert)
|
|
#define STATIC_ASSERT_MSG(expr, msg) _Static_assert(expr, msg)
|
|
#else
|
|
#define STATIC_ASSERT_MSG(expr, msg) \
|
|
switch (0) { \
|
|
case 0: \
|
|
case (expr):; \
|
|
}
|
|
#endif
|
|
#endif /* STATIC_ASSERT */
|
|
|
|
#ifndef STATIC_ASSERT
|
|
#define STATIC_ASSERT(expr) STATIC_ASSERT_MSG(expr, #expr)
|
|
#endif
|
|
|
|
#ifndef __Wpedantic_format_voidptr
|
|
MDBX_MAYBE_UNUSED MDBX_PURE_FUNCTION static __inline const void *
|
|
__Wpedantic_format_voidptr(const void *ptr) {
|
|
return ptr;
|
|
}
|
|
#define __Wpedantic_format_voidptr(ARG) __Wpedantic_format_voidptr(ARG)
|
|
#endif /* __Wpedantic_format_voidptr */
|