2024-05-19 22:07:58 +03:00
|
|
|
/// \copyright SPDX-License-Identifier: Apache-2.0
|
|
|
|
/// \author Леонид Юрьев aka Leonid Yuriev <leo@yuriev.ru> \date 2015-2024
|
|
|
|
///
|
|
|
|
/// https://en.wikipedia.org/wiki/Operating_system_abstraction_layer
|
2017-03-16 18:09:27 +03:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
#include "essentials.h"
|
2017-05-24 13:59:50 +03:00
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
2022-06-02 18:59:58 +03:00
|
|
|
/* Memory/Compiler barriers, cache coherence */
|
|
|
|
|
|
|
|
#if __has_include(<sys/cachectl.h>)
|
|
|
|
#include <sys/cachectl.h>
|
|
|
|
#elif defined(__mips) || defined(__mips__) || defined(__mips64) || \
|
|
|
|
defined(__mips64__) || defined(_M_MRX000) || defined(_MIPS_) || \
|
|
|
|
defined(__MWERKS__) || defined(__sgi)
|
|
|
|
/* MIPS should have explicit cache control */
|
|
|
|
#include <sys/cachectl.h>
|
2022-01-31 23:29:03 +03:00
|
|
|
#endif
|
2022-06-02 18:59:58 +03:00
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_MAYBE_UNUSED static inline void osal_compiler_barrier(void) {
|
2022-06-02 18:59:58 +03:00
|
|
|
#if defined(__clang__) || defined(__GNUC__)
|
|
|
|
__asm__ __volatile__("" ::: "memory");
|
2019-08-23 03:36:56 +03:00
|
|
|
#elif defined(_MSC_VER)
|
2022-06-02 18:59:58 +03:00
|
|
|
_ReadWriteBarrier();
|
|
|
|
#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */
|
|
|
|
__memory_barrier();
|
|
|
|
#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun)
|
|
|
|
__compiler_barrier();
|
|
|
|
#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \
|
|
|
|
(defined(HP_IA64) || defined(__ia64))
|
|
|
|
_Asm_sched_fence(/* LY: no-arg meaning 'all expect ALU', e.g. 0x3D3D */);
|
|
|
|
#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) || \
|
|
|
|
defined(__ppc64__) || defined(__powerpc64__)
|
|
|
|
__fence();
|
2019-08-23 03:36:56 +03:00
|
|
|
#else
|
2022-06-02 18:59:58 +03:00
|
|
|
#error "Could not guess the kind of compiler, please report to us."
|
|
|
|
#endif
|
|
|
|
}
|
2019-08-23 03:36:56 +03:00
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_MAYBE_UNUSED static inline void osal_memory_barrier(void) {
|
2022-06-02 18:59:58 +03:00
|
|
|
#ifdef MDBX_HAVE_C11ATOMICS
|
|
|
|
atomic_thread_fence(memory_order_seq_cst);
|
|
|
|
#elif defined(__ATOMIC_SEQ_CST)
|
|
|
|
#ifdef __clang__
|
|
|
|
__c11_atomic_thread_fence(__ATOMIC_SEQ_CST);
|
2019-11-01 21:25:17 +03:00
|
|
|
#else
|
2022-06-02 18:59:58 +03:00
|
|
|
__atomic_thread_fence(__ATOMIC_SEQ_CST);
|
2020-04-10 11:40:58 -07:00
|
|
|
#endif
|
2022-06-02 18:59:58 +03:00
|
|
|
#elif defined(__clang__) || defined(__GNUC__)
|
|
|
|
__sync_synchronize();
|
|
|
|
#elif defined(_WIN32) || defined(_WIN64)
|
|
|
|
MemoryBarrier();
|
|
|
|
#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */
|
|
|
|
#if defined(__ia32__)
|
|
|
|
_mm_mfence();
|
2019-08-25 11:49:33 +00:00
|
|
|
#else
|
2022-06-02 18:59:58 +03:00
|
|
|
__mf();
|
2017-03-16 18:09:27 +03:00
|
|
|
#endif
|
2022-06-02 18:59:58 +03:00
|
|
|
#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun)
|
|
|
|
__machine_rw_barrier();
|
|
|
|
#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \
|
|
|
|
(defined(HP_IA64) || defined(__ia64))
|
|
|
|
_Asm_mf();
|
|
|
|
#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) || \
|
|
|
|
defined(__ppc64__) || defined(__powerpc64__)
|
|
|
|
__lwsync();
|
2019-11-01 21:25:17 +03:00
|
|
|
#else
|
2022-06-02 18:59:58 +03:00
|
|
|
#error "Could not guess the kind of compiler, please report to us."
|
|
|
|
#endif
|
|
|
|
}
|
2019-11-01 21:25:17 +03:00
|
|
|
|
2022-06-02 18:59:58 +03:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
/* system-depended definitions */
|
2019-11-01 21:25:17 +03:00
|
|
|
|
2017-03-16 18:09:27 +03:00
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
#define HAVE_SYS_STAT_H
|
|
|
|
#define HAVE_SYS_TYPES_H
|
2022-08-11 01:03:15 +03:00
|
|
|
typedef HANDLE osal_thread_t;
|
|
|
|
typedef unsigned osal_thread_key_t;
|
2024-05-19 22:07:58 +03:00
|
|
|
#define MAP_FAILED nullptr
|
2017-03-16 18:09:27 +03:00
|
|
|
#define HIGH_DWORD(v) ((DWORD)((sizeof(v) > 4) ? ((uint64_t)(v) >> 32) : 0))
|
|
|
|
#define THREAD_CALL WINAPI
|
|
|
|
#define THREAD_RESULT DWORD
|
2017-05-23 18:40:21 +03:00
|
|
|
typedef struct {
|
|
|
|
HANDLE mutex;
|
2020-05-21 22:15:30 +03:00
|
|
|
HANDLE event[2];
|
2022-08-11 01:03:15 +03:00
|
|
|
} osal_condpair_t;
|
|
|
|
typedef CRITICAL_SECTION osal_fastmutex_t;
|
2018-10-14 18:44:22 +03:00
|
|
|
|
2021-05-08 10:59:15 +03:00
|
|
|
#if !defined(_MSC_VER) && !defined(__try)
|
|
|
|
/* *INDENT-OFF* */
|
|
|
|
/* clang-format off */
|
|
|
|
#define __try
|
2022-06-02 18:59:58 +03:00
|
|
|
#define __except(COND) if (false)
|
2021-05-08 10:59:15 +03:00
|
|
|
/* *INDENT-ON* */
|
|
|
|
/* clang-format on */
|
|
|
|
#endif /* stub for MSVC's __try/__except */
|
|
|
|
|
2021-04-29 20:09:16 +03:00
|
|
|
#if MDBX_WITHOUT_MSVC_CRT
|
2021-04-30 02:24:36 +03:00
|
|
|
|
2022-08-11 01:03:15 +03:00
|
|
|
#ifndef osal_malloc
|
|
|
|
static inline void *osal_malloc(size_t bytes) {
|
2021-04-30 02:24:36 +03:00
|
|
|
return HeapAlloc(GetProcessHeap(), 0, bytes);
|
2018-10-13 11:32:46 +03:00
|
|
|
}
|
2022-08-11 01:03:15 +03:00
|
|
|
#endif /* osal_malloc */
|
2018-10-14 18:44:22 +03:00
|
|
|
|
2022-08-11 01:03:15 +03:00
|
|
|
#ifndef osal_calloc
|
|
|
|
static inline void *osal_calloc(size_t nelem, size_t size) {
|
2021-04-30 02:24:36 +03:00
|
|
|
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nelem * size);
|
2018-10-13 11:32:46 +03:00
|
|
|
}
|
2022-08-11 01:03:15 +03:00
|
|
|
#endif /* osal_calloc */
|
2018-10-14 18:44:22 +03:00
|
|
|
|
2022-08-11 01:03:15 +03:00
|
|
|
#ifndef osal_realloc
|
|
|
|
static inline void *osal_realloc(void *ptr, size_t bytes) {
|
2021-04-30 02:24:36 +03:00
|
|
|
return ptr ? HeapReAlloc(GetProcessHeap(), 0, ptr, bytes)
|
|
|
|
: HeapAlloc(GetProcessHeap(), 0, bytes);
|
2018-10-13 11:32:46 +03:00
|
|
|
}
|
2022-08-11 01:03:15 +03:00
|
|
|
#endif /* osal_realloc */
|
2018-10-14 18:44:22 +03:00
|
|
|
|
2022-08-11 01:03:15 +03:00
|
|
|
#ifndef osal_free
|
|
|
|
static inline void osal_free(void *ptr) { HeapFree(GetProcessHeap(), 0, ptr); }
|
|
|
|
#endif /* osal_free */
|
2021-04-30 02:24:36 +03:00
|
|
|
|
|
|
|
#else /* MDBX_WITHOUT_MSVC_CRT */
|
|
|
|
|
2022-08-11 01:03:15 +03:00
|
|
|
#define osal_malloc malloc
|
|
|
|
#define osal_calloc calloc
|
|
|
|
#define osal_realloc realloc
|
|
|
|
#define osal_free free
|
|
|
|
#define osal_strdup _strdup
|
2021-04-30 02:24:36 +03:00
|
|
|
|
2021-04-29 20:09:16 +03:00
|
|
|
#endif /* MDBX_WITHOUT_MSVC_CRT */
|
2018-10-14 18:44:22 +03:00
|
|
|
|
|
|
|
#ifndef snprintf
|
|
|
|
#define snprintf _snprintf /* ntdll */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef vsnprintf
|
2018-10-14 01:13:36 +03:00
|
|
|
#define vsnprintf _vsnprintf /* ntdll */
|
2018-10-14 18:44:22 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#else /*----------------------------------------------------------------------*/
|
|
|
|
|
2022-08-11 01:03:15 +03:00
|
|
|
typedef pthread_t osal_thread_t;
|
|
|
|
typedef pthread_key_t osal_thread_key_t;
|
2017-03-16 18:09:27 +03:00
|
|
|
#define INVALID_HANDLE_VALUE (-1)
|
|
|
|
#define THREAD_CALL
|
|
|
|
#define THREAD_RESULT void *
|
2017-05-23 18:40:21 +03:00
|
|
|
typedef struct {
|
|
|
|
pthread_mutex_t mutex;
|
2020-05-21 22:15:30 +03:00
|
|
|
pthread_cond_t cond[2];
|
2022-08-11 01:03:15 +03:00
|
|
|
} osal_condpair_t;
|
|
|
|
typedef pthread_mutex_t osal_fastmutex_t;
|
|
|
|
#define osal_malloc malloc
|
|
|
|
#define osal_calloc calloc
|
|
|
|
#define osal_realloc realloc
|
|
|
|
#define osal_free free
|
|
|
|
#define osal_strdup strdup
|
2018-10-13 11:32:46 +03:00
|
|
|
#endif /* Platform */
|
2018-10-12 22:01:36 +03:00
|
|
|
|
2019-10-10 14:36:57 +03:00
|
|
|
#if __GLIBC_PREREQ(2, 12) || defined(__FreeBSD__) || defined(malloc_usable_size)
|
|
|
|
/* malloc_usable_size() already provided */
|
|
|
|
#elif defined(__APPLE__)
|
|
|
|
#define malloc_usable_size(ptr) malloc_size(ptr)
|
2021-04-29 20:09:16 +03:00
|
|
|
#elif defined(_MSC_VER) && !MDBX_WITHOUT_MSVC_CRT
|
2019-10-10 14:36:57 +03:00
|
|
|
#define malloc_usable_size(ptr) _msize(ptr)
|
|
|
|
#endif /* malloc_usable_size */
|
|
|
|
|
2017-03-16 18:09:27 +03:00
|
|
|
/*----------------------------------------------------------------------------*/
|
2022-06-02 18:59:58 +03:00
|
|
|
/* OS abstraction layer stuff */
|
2017-03-16 18:09:27 +03:00
|
|
|
|
2022-08-09 18:27:43 +03:00
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
typedef wchar_t pathchar_t;
|
2023-01-05 22:33:56 +03:00
|
|
|
#define MDBX_PRIsPATH "ls"
|
2022-08-09 18:27:43 +03:00
|
|
|
#else
|
|
|
|
typedef char pathchar_t;
|
2023-01-05 22:33:56 +03:00
|
|
|
#define MDBX_PRIsPATH "s"
|
2022-08-09 18:27:43 +03:00
|
|
|
#endif
|
|
|
|
|
2022-11-29 01:10:44 +03:00
|
|
|
typedef struct osal_mmap {
|
2020-09-13 18:06:14 +03:00
|
|
|
union {
|
2022-11-29 01:10:44 +03:00
|
|
|
void *base;
|
2024-05-19 22:07:58 +03:00
|
|
|
struct shared_lck *lck;
|
2020-09-13 18:06:14 +03:00
|
|
|
};
|
|
|
|
mdbx_filehandle_t fd;
|
|
|
|
size_t limit; /* mapping length, but NOT a size of file nor DB */
|
|
|
|
size_t current; /* mapped region size, i.e. the size of file and DB */
|
2021-04-29 19:50:25 +03:00
|
|
|
uint64_t filesize /* in-process cache of a file size */;
|
2021-07-08 13:18:51 +03:00
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
2021-04-29 19:50:25 +03:00
|
|
|
HANDLE section; /* memory-mapped section handle */
|
2020-09-13 18:06:14 +03:00
|
|
|
#endif
|
2022-08-11 01:03:15 +03:00
|
|
|
} osal_mmap_t;
|
2020-09-13 18:06:14 +03:00
|
|
|
|
2022-09-25 12:47:31 +03:00
|
|
|
#ifndef MDBX_HAVE_PWRITEV
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
|
|
|
|
#define MDBX_HAVE_PWRITEV 0
|
|
|
|
|
|
|
|
#elif defined(__ANDROID_API__)
|
|
|
|
|
|
|
|
#if __ANDROID_API__ < 24
|
|
|
|
#define MDBX_HAVE_PWRITEV 0
|
|
|
|
#else
|
|
|
|
#define MDBX_HAVE_PWRITEV 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#elif defined(__APPLE__) || defined(__MACH__) || defined(_DARWIN_C_SOURCE)
|
|
|
|
|
|
|
|
#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && defined(MAC_OS_VERSION_11_0) && \
|
|
|
|
MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
|
|
|
|
/* FIXME: add checks for IOS versions, etc */
|
|
|
|
#define MDBX_HAVE_PWRITEV 1
|
|
|
|
#else
|
|
|
|
#define MDBX_HAVE_PWRITEV 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#elif defined(_SC_IOV_MAX) || (defined(IOV_MAX) && IOV_MAX > 1)
|
|
|
|
#define MDBX_HAVE_PWRITEV 1
|
|
|
|
#else
|
|
|
|
#define MDBX_HAVE_PWRITEV 0
|
|
|
|
#endif
|
|
|
|
#endif /* MDBX_HAVE_PWRITEV */
|
|
|
|
|
|
|
|
typedef struct ior_item {
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
OVERLAPPED ov;
|
|
|
|
#define ior_svg_gap4terminator 1
|
|
|
|
#define ior_sgv_element FILE_SEGMENT_ELEMENT
|
|
|
|
#else
|
|
|
|
size_t offset;
|
|
|
|
#if MDBX_HAVE_PWRITEV
|
|
|
|
size_t sgvcnt;
|
|
|
|
#define ior_svg_gap4terminator 0
|
|
|
|
#define ior_sgv_element struct iovec
|
|
|
|
#endif /* MDBX_HAVE_PWRITEV */
|
|
|
|
#endif /* !Windows */
|
|
|
|
union {
|
|
|
|
MDBX_val single;
|
|
|
|
#if defined(ior_sgv_element)
|
|
|
|
ior_sgv_element sgv[1 + ior_svg_gap4terminator];
|
|
|
|
#endif /* ior_sgv_element */
|
|
|
|
};
|
|
|
|
} ior_item_t;
|
|
|
|
|
|
|
|
typedef struct osal_ioring {
|
|
|
|
unsigned slots_left;
|
|
|
|
unsigned allocated;
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
#define IOR_STATE_LOCKED 1
|
2022-12-03 14:55:38 +03:00
|
|
|
HANDLE overlapped_fd;
|
2022-09-25 12:47:31 +03:00
|
|
|
unsigned pagesize;
|
|
|
|
unsigned last_sgvcnt;
|
|
|
|
size_t last_bytes;
|
2022-12-03 14:55:38 +03:00
|
|
|
uint8_t direct, state, pagesize_ln2;
|
2022-09-25 12:47:31 +03:00
|
|
|
unsigned event_stack;
|
|
|
|
HANDLE *event_pool;
|
|
|
|
volatile LONG async_waiting;
|
|
|
|
volatile LONG async_completed;
|
|
|
|
HANDLE async_done;
|
|
|
|
|
|
|
|
#define ior_last_sgvcnt(ior, item) (ior)->last_sgvcnt
|
|
|
|
#define ior_last_bytes(ior, item) (ior)->last_bytes
|
|
|
|
#elif MDBX_HAVE_PWRITEV
|
|
|
|
unsigned last_bytes;
|
|
|
|
#define ior_last_sgvcnt(ior, item) (item)->sgvcnt
|
|
|
|
#define ior_last_bytes(ior, item) (ior)->last_bytes
|
|
|
|
#else
|
|
|
|
#define ior_last_sgvcnt(ior, item) (1)
|
|
|
|
#define ior_last_bytes(ior, item) (item)->single.iov_len
|
|
|
|
#endif /* !Windows */
|
|
|
|
ior_item_t *last;
|
|
|
|
ior_item_t *pool;
|
|
|
|
char *boundary;
|
|
|
|
} osal_ioring_t;
|
|
|
|
|
|
|
|
/* Actually this is not ioring for now, but on the way. */
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int osal_ioring_create(osal_ioring_t *
|
2022-09-25 12:47:31 +03:00
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
2024-05-19 22:07:58 +03:00
|
|
|
,
|
|
|
|
bool enable_direct,
|
|
|
|
mdbx_filehandle_t overlapped_fd
|
2022-09-25 12:47:31 +03:00
|
|
|
#endif /* Windows */
|
2022-12-03 14:55:38 +03:00
|
|
|
);
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int osal_ioring_resize(osal_ioring_t *, size_t items);
|
|
|
|
MDBX_INTERNAL void osal_ioring_destroy(osal_ioring_t *);
|
|
|
|
MDBX_INTERNAL void osal_ioring_reset(osal_ioring_t *);
|
|
|
|
MDBX_INTERNAL int osal_ioring_add(osal_ioring_t *ctx, const size_t offset,
|
|
|
|
void *data, const size_t bytes);
|
2022-09-25 12:47:31 +03:00
|
|
|
typedef struct osal_ioring_write_result {
|
|
|
|
int err;
|
|
|
|
unsigned wops;
|
|
|
|
} osal_ioring_write_result_t;
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL osal_ioring_write_result_t
|
2022-12-03 14:55:38 +03:00
|
|
|
osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd);
|
2022-09-25 12:47:31 +03:00
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL void osal_ioring_walk(osal_ioring_t *ior, iov_ctx_t *ctx,
|
|
|
|
void (*callback)(iov_ctx_t *ctx,
|
|
|
|
size_t offset, void *data,
|
|
|
|
size_t bytes));
|
2022-09-25 12:47:31 +03:00
|
|
|
|
2022-10-09 20:55:53 +03:00
|
|
|
MDBX_MAYBE_UNUSED static inline unsigned
|
|
|
|
osal_ioring_left(const osal_ioring_t *ior) {
|
2022-09-25 12:47:31 +03:00
|
|
|
return ior->slots_left;
|
|
|
|
}
|
|
|
|
|
2022-10-09 20:55:53 +03:00
|
|
|
MDBX_MAYBE_UNUSED static inline unsigned
|
|
|
|
osal_ioring_used(const osal_ioring_t *ior) {
|
2022-09-25 12:47:31 +03:00
|
|
|
return ior->allocated - ior->slots_left;
|
|
|
|
}
|
|
|
|
|
2022-10-09 20:55:53 +03:00
|
|
|
MDBX_MAYBE_UNUSED static inline int
|
2022-12-03 14:55:38 +03:00
|
|
|
osal_ioring_prepare(osal_ioring_t *ior, size_t items, size_t bytes) {
|
2022-09-25 12:47:31 +03:00
|
|
|
items = (items > 32) ? items : 32;
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
2022-12-03 14:55:38 +03:00
|
|
|
if (ior->direct) {
|
|
|
|
const size_t npages = bytes >> ior->pagesize_ln2;
|
|
|
|
items = (items > npages) ? items : npages;
|
|
|
|
}
|
2022-09-25 12:47:31 +03:00
|
|
|
#else
|
|
|
|
(void)bytes;
|
|
|
|
#endif
|
|
|
|
items = (items < 65536) ? items : 65536;
|
|
|
|
if (likely(ior->allocated >= items))
|
|
|
|
return MDBX_SUCCESS;
|
|
|
|
return osal_ioring_resize(ior, items);
|
|
|
|
}
|
|
|
|
|
2017-03-16 18:09:27 +03:00
|
|
|
/*----------------------------------------------------------------------------*/
|
2017-05-24 13:59:50 +03:00
|
|
|
/* libc compatibility stuff */
|
2017-03-16 18:09:27 +03:00
|
|
|
|
2019-07-14 00:49:00 +03:00
|
|
|
#if (!defined(__GLIBC__) && __GLIBC_PREREQ(2, 1)) && \
|
|
|
|
(defined(_GNU_SOURCE) || defined(_BSD_SOURCE))
|
2022-08-11 01:03:15 +03:00
|
|
|
#define osal_asprintf asprintf
|
|
|
|
#define osal_vasprintf vasprintf
|
2017-05-15 12:08:04 +03:00
|
|
|
#else
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_MAYBE_UNUSED MDBX_INTERNAL
|
2022-08-11 01:03:15 +03:00
|
|
|
MDBX_PRINTF_ARGS(2, 3) int osal_asprintf(char **strp, const char *fmt, ...);
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int osal_vasprintf(char **strp, const char *fmt, va_list ap);
|
2017-05-15 12:08:04 +03:00
|
|
|
#endif
|
|
|
|
|
2022-06-02 18:59:58 +03:00
|
|
|
#if !defined(MADV_DODUMP) && defined(MADV_CORE)
|
|
|
|
#define MADV_DODUMP MADV_CORE
|
|
|
|
#endif /* MADV_CORE -> MADV_DODUMP */
|
|
|
|
|
|
|
|
#if !defined(MADV_DONTDUMP) && defined(MADV_NOCORE)
|
|
|
|
#define MADV_DONTDUMP MADV_NOCORE
|
|
|
|
#endif /* MADV_NOCORE -> MADV_DONTDUMP */
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_MAYBE_UNUSED MDBX_INTERNAL void osal_jitter(bool tiny);
|
2017-05-15 12:08:04 +03:00
|
|
|
|
2017-03-16 18:09:27 +03:00
|
|
|
/* max bytes to write in one call */
|
2022-09-25 12:47:31 +03:00
|
|
|
#if defined(_WIN64)
|
|
|
|
#define MAX_WRITE UINT32_C(0x10000000)
|
|
|
|
#elif defined(_WIN32)
|
|
|
|
#define MAX_WRITE UINT32_C(0x04000000)
|
2019-09-16 14:16:14 +03:00
|
|
|
#else
|
2022-09-25 12:47:31 +03:00
|
|
|
#define MAX_WRITE UINT32_C(0x3f000000)
|
2022-10-12 20:47:22 +03:00
|
|
|
|
|
|
|
#if defined(F_GETLK64) && defined(F_SETLK64) && defined(F_SETLKW64) && \
|
|
|
|
!defined(__ANDROID_API__)
|
|
|
|
#define MDBX_F_SETLK F_SETLK64
|
|
|
|
#define MDBX_F_SETLKW F_SETLKW64
|
|
|
|
#define MDBX_F_GETLK F_GETLK64
|
2022-10-13 17:30:43 +03:00
|
|
|
#if (__GLIBC_PREREQ(2, 28) && \
|
|
|
|
(defined(__USE_LARGEFILE64) || defined(__LARGEFILE64_SOURCE) || \
|
|
|
|
defined(_USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE))) || \
|
|
|
|
defined(fcntl64)
|
2022-10-12 20:47:22 +03:00
|
|
|
#define MDBX_FCNTL fcntl64
|
2022-10-13 17:30:43 +03:00
|
|
|
#else
|
|
|
|
#define MDBX_FCNTL fcntl
|
|
|
|
#endif
|
2022-10-12 20:47:22 +03:00
|
|
|
#define MDBX_STRUCT_FLOCK struct flock64
|
|
|
|
#ifndef OFF_T_MAX
|
|
|
|
#define OFF_T_MAX UINT64_C(0x7fffFFFFfff00000)
|
|
|
|
#endif /* OFF_T_MAX */
|
|
|
|
#else
|
|
|
|
#define MDBX_F_SETLK F_SETLK
|
|
|
|
#define MDBX_F_SETLKW F_SETLKW
|
|
|
|
#define MDBX_F_GETLK F_GETLK
|
|
|
|
#define MDBX_FCNTL fcntl
|
|
|
|
#define MDBX_STRUCT_FLOCK struct flock
|
|
|
|
#endif /* MDBX_F_SETLK, MDBX_F_SETLKW, MDBX_F_GETLK */
|
|
|
|
|
|
|
|
#if defined(F_OFD_SETLK64) && defined(F_OFD_SETLKW64) && \
|
|
|
|
defined(F_OFD_GETLK64) && !defined(__ANDROID_API__)
|
|
|
|
#define MDBX_F_OFD_SETLK F_OFD_SETLK64
|
|
|
|
#define MDBX_F_OFD_SETLKW F_OFD_SETLKW64
|
|
|
|
#define MDBX_F_OFD_GETLK F_OFD_GETLK64
|
|
|
|
#else
|
|
|
|
#define MDBX_F_OFD_SETLK F_OFD_SETLK
|
|
|
|
#define MDBX_F_OFD_SETLKW F_OFD_SETLKW
|
|
|
|
#define MDBX_F_OFD_GETLK F_OFD_GETLK
|
|
|
|
#ifndef OFF_T_MAX
|
|
|
|
#define OFF_T_MAX \
|
|
|
|
(((sizeof(off_t) > 4) ? INT64_MAX : INT32_MAX) & ~(size_t)0xFffff)
|
|
|
|
#endif /* OFF_T_MAX */
|
|
|
|
#endif /* MDBX_F_OFD_SETLK64, MDBX_F_OFD_SETLKW64, MDBX_F_OFD_GETLK64 */
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
#endif /* !Windows */
|
2019-07-22 00:19:15 +03:00
|
|
|
|
2022-08-11 01:03:15 +03:00
|
|
|
#ifndef osal_strdup
|
|
|
|
LIBMDBX_API char *osal_strdup(const char *str);
|
2017-03-16 18:09:27 +03:00
|
|
|
#endif
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_MAYBE_UNUSED static inline int osal_get_errno(void) {
|
2017-05-15 12:08:04 +03:00
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
DWORD rc = GetLastError();
|
|
|
|
#else
|
|
|
|
int rc = errno;
|
|
|
|
#endif
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2022-08-11 01:03:15 +03:00
|
|
|
#ifndef osal_memalign_alloc
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int osal_memalign_alloc(size_t alignment, size_t bytes,
|
|
|
|
void **result);
|
2018-10-14 11:14:14 +03:00
|
|
|
#endif
|
2022-08-11 01:03:15 +03:00
|
|
|
#ifndef osal_memalign_free
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL void osal_memalign_free(void *ptr);
|
2019-08-31 17:10:04 +03:00
|
|
|
#endif
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int osal_condpair_init(osal_condpair_t *condpair);
|
|
|
|
MDBX_INTERNAL int osal_condpair_lock(osal_condpair_t *condpair);
|
|
|
|
MDBX_INTERNAL int osal_condpair_unlock(osal_condpair_t *condpair);
|
|
|
|
MDBX_INTERNAL int osal_condpair_signal(osal_condpair_t *condpair, bool part);
|
|
|
|
MDBX_INTERNAL int osal_condpair_wait(osal_condpair_t *condpair, bool part);
|
|
|
|
MDBX_INTERNAL int osal_condpair_destroy(osal_condpair_t *condpair);
|
|
|
|
|
|
|
|
MDBX_INTERNAL int osal_fastmutex_init(osal_fastmutex_t *fastmutex);
|
|
|
|
MDBX_INTERNAL int osal_fastmutex_acquire(osal_fastmutex_t *fastmutex);
|
|
|
|
MDBX_INTERNAL int osal_fastmutex_release(osal_fastmutex_t *fastmutex);
|
|
|
|
MDBX_INTERNAL int osal_fastmutex_destroy(osal_fastmutex_t *fastmutex);
|
|
|
|
|
|
|
|
MDBX_INTERNAL int osal_pwritev(mdbx_filehandle_t fd, struct iovec *iov,
|
|
|
|
size_t sgvcnt, uint64_t offset);
|
|
|
|
MDBX_INTERNAL int osal_pread(mdbx_filehandle_t fd, void *buf, size_t count,
|
|
|
|
uint64_t offset);
|
|
|
|
MDBX_INTERNAL int osal_pwrite(mdbx_filehandle_t fd, const void *buf,
|
|
|
|
size_t count, uint64_t offset);
|
|
|
|
MDBX_INTERNAL int osal_write(mdbx_filehandle_t fd, const void *buf,
|
|
|
|
size_t count);
|
|
|
|
|
|
|
|
MDBX_INTERNAL int
|
2022-08-11 01:03:15 +03:00
|
|
|
osal_thread_create(osal_thread_t *thread,
|
2019-08-31 17:10:04 +03:00
|
|
|
THREAD_RESULT(THREAD_CALL *start_routine)(void *),
|
|
|
|
void *arg);
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int osal_thread_join(osal_thread_t thread);
|
2017-03-16 18:09:27 +03:00
|
|
|
|
2022-08-11 01:03:15 +03:00
|
|
|
enum osal_syncmode_bits {
|
2022-12-14 11:43:22 +03:00
|
|
|
MDBX_SYNC_NONE = 0,
|
|
|
|
MDBX_SYNC_KICK = 1,
|
|
|
|
MDBX_SYNC_DATA = 2,
|
|
|
|
MDBX_SYNC_SIZE = 4,
|
|
|
|
MDBX_SYNC_IODQ = 8
|
2019-08-20 00:17:28 +03:00
|
|
|
};
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int osal_fsync(mdbx_filehandle_t fd,
|
|
|
|
const enum osal_syncmode_bits mode_bits);
|
|
|
|
MDBX_INTERNAL int osal_ftruncate(mdbx_filehandle_t fd, uint64_t length);
|
|
|
|
MDBX_INTERNAL int osal_fseek(mdbx_filehandle_t fd, uint64_t pos);
|
|
|
|
MDBX_INTERNAL int osal_filesize(mdbx_filehandle_t fd, uint64_t *length);
|
2019-12-15 00:13:43 +03:00
|
|
|
|
2022-08-11 01:03:15 +03:00
|
|
|
enum osal_openfile_purpose {
|
2022-09-25 12:47:31 +03:00
|
|
|
MDBX_OPEN_DXB_READ,
|
|
|
|
MDBX_OPEN_DXB_LAZY,
|
|
|
|
MDBX_OPEN_DXB_DSYNC,
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
MDBX_OPEN_DXB_OVERLAPPED,
|
2022-09-27 02:37:28 +03:00
|
|
|
MDBX_OPEN_DXB_OVERLAPPED_DIRECT,
|
2022-09-25 12:47:31 +03:00
|
|
|
#endif /* Windows */
|
|
|
|
MDBX_OPEN_LCK,
|
|
|
|
MDBX_OPEN_COPY,
|
|
|
|
MDBX_OPEN_DELETE
|
2019-12-15 00:13:43 +03:00
|
|
|
};
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_MAYBE_UNUSED static inline bool osal_isdirsep(pathchar_t c) {
|
2023-01-05 01:34:52 +03:00
|
|
|
return
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
c == '\\' ||
|
|
|
|
#endif
|
|
|
|
c == '/';
|
|
|
|
}
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL bool osal_pathequal(const pathchar_t *l, const pathchar_t *r,
|
|
|
|
size_t len);
|
|
|
|
MDBX_INTERNAL pathchar_t *osal_fileext(const pathchar_t *pathname, size_t len);
|
|
|
|
MDBX_INTERNAL int osal_fileexists(const pathchar_t *pathname);
|
|
|
|
MDBX_INTERNAL int osal_openfile(const enum osal_openfile_purpose purpose,
|
|
|
|
const MDBX_env *env, const pathchar_t *pathname,
|
|
|
|
mdbx_filehandle_t *fd,
|
|
|
|
mdbx_mode_t unix_mode_bits);
|
|
|
|
MDBX_INTERNAL int osal_closefile(mdbx_filehandle_t fd);
|
|
|
|
MDBX_INTERNAL int osal_removefile(const pathchar_t *pathname);
|
|
|
|
MDBX_INTERNAL int osal_removedirectory(const pathchar_t *pathname);
|
|
|
|
MDBX_INTERNAL int osal_is_pipe(mdbx_filehandle_t fd);
|
|
|
|
MDBX_INTERNAL int osal_lockfile(mdbx_filehandle_t fd, bool wait);
|
2017-03-16 18:09:27 +03:00
|
|
|
|
2019-11-08 09:06:44 +03:00
|
|
|
#define MMAP_OPTION_TRUNCATE 1
|
|
|
|
#define MMAP_OPTION_SEMAPHORE 2
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int osal_mmap(const int flags, osal_mmap_t *map, size_t size,
|
|
|
|
const size_t limit, const unsigned options);
|
|
|
|
MDBX_INTERNAL int osal_munmap(osal_mmap_t *map);
|
2021-06-10 02:57:32 +03:00
|
|
|
#define MDBX_MRESIZE_MAY_MOVE 0x00000100
|
|
|
|
#define MDBX_MRESIZE_MAY_UNMAP 0x00000200
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int osal_mresize(const int flags, osal_mmap_t *map, size_t size,
|
|
|
|
size_t limit);
|
2018-01-07 14:37:38 +03:00
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
typedef struct {
|
|
|
|
unsigned limit, count;
|
|
|
|
HANDLE handles[31];
|
|
|
|
} mdbx_handle_array_t;
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int
|
2022-08-11 01:03:15 +03:00
|
|
|
osal_suspend_threads_before_remap(MDBX_env *env, mdbx_handle_array_t **array);
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int osal_resume_threads_after_remap(mdbx_handle_array_t *array);
|
2018-01-07 14:37:38 +03:00
|
|
|
#endif /* Windows */
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int osal_msync(const osal_mmap_t *map, size_t offset,
|
|
|
|
size_t length, enum osal_syncmode_bits mode_bits);
|
|
|
|
MDBX_INTERNAL int osal_check_fs_rdonly(mdbx_filehandle_t handle,
|
|
|
|
const pathchar_t *pathname, int err);
|
|
|
|
MDBX_INTERNAL int osal_check_fs_incore(mdbx_filehandle_t handle);
|
|
|
|
|
|
|
|
MDBX_MAYBE_UNUSED static inline uint32_t osal_getpid(void) {
|
2019-09-23 15:32:29 +03:00
|
|
|
STATIC_ASSERT(sizeof(mdbx_pid_t) <= sizeof(uint32_t));
|
2017-03-16 18:09:27 +03:00
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
return GetCurrentProcessId();
|
|
|
|
#else
|
2022-04-21 15:41:25 +03:00
|
|
|
STATIC_ASSERT(sizeof(pid_t) <= sizeof(uint32_t));
|
2017-03-16 18:09:27 +03:00
|
|
|
return getpid();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_MAYBE_UNUSED static inline uintptr_t osal_thread_self(void) {
|
2020-04-04 15:56:52 +03:00
|
|
|
mdbx_tid_t thunk;
|
2020-04-04 16:51:36 +03:00
|
|
|
STATIC_ASSERT(sizeof(uintptr_t) >= sizeof(thunk));
|
2017-06-06 17:05:30 +03:00
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
2020-04-04 15:56:52 +03:00
|
|
|
thunk = GetCurrentThreadId();
|
2017-06-06 17:05:30 +03:00
|
|
|
#else
|
2020-04-04 15:56:52 +03:00
|
|
|
thunk = pthread_self();
|
2017-06-06 17:05:30 +03:00
|
|
|
#endif
|
2020-04-04 16:51:36 +03:00
|
|
|
return (uintptr_t)thunk;
|
2017-06-06 17:05:30 +03:00
|
|
|
}
|
|
|
|
|
2022-04-21 15:41:25 +03:00
|
|
|
#if !defined(_WIN32) && !defined(_WIN64)
|
|
|
|
#if defined(__ANDROID_API__) || defined(ANDROID) || defined(BIONIC)
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL int osal_check_tid4bionic(void);
|
2022-04-21 15:41:25 +03:00
|
|
|
#else
|
2024-05-19 22:07:58 +03:00
|
|
|
static inline int osal_check_tid4bionic(void) { return 0; }
|
2022-04-21 15:41:25 +03:00
|
|
|
#endif /* __ANDROID_API__ || ANDROID) || BIONIC */
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_MAYBE_UNUSED static inline int
|
2022-08-11 01:03:15 +03:00
|
|
|
osal_pthread_mutex_lock(pthread_mutex_t *mutex) {
|
|
|
|
int err = osal_check_tid4bionic();
|
2022-04-21 15:41:25 +03:00
|
|
|
return unlikely(err) ? err : pthread_mutex_lock(mutex);
|
|
|
|
}
|
|
|
|
#endif /* !Windows */
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL uint64_t osal_monotime(void);
|
|
|
|
MDBX_INTERNAL uint64_t osal_cputime(size_t *optional_page_faults);
|
|
|
|
MDBX_INTERNAL uint64_t osal_16dot16_to_monotime(uint32_t seconds_16dot16);
|
|
|
|
MDBX_INTERNAL uint32_t osal_monotime_to_16dot16(uint64_t monotime);
|
2017-04-27 15:18:33 +03:00
|
|
|
|
2022-10-09 20:55:53 +03:00
|
|
|
MDBX_MAYBE_UNUSED static inline uint32_t
|
|
|
|
osal_monotime_to_16dot16_noUnderflow(uint64_t monotime) {
|
2022-10-07 14:53:35 +03:00
|
|
|
uint32_t seconds_16dot16 = osal_monotime_to_16dot16(monotime);
|
|
|
|
return seconds_16dot16 ? seconds_16dot16 : /* fix underflow */ (monotime > 0);
|
|
|
|
}
|
|
|
|
|
2017-03-16 18:09:27 +03:00
|
|
|
/*----------------------------------------------------------------------------*/
|
2020-02-18 20:29:35 +03:00
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_INTERNAL void osal_ctor(void);
|
|
|
|
MDBX_INTERNAL void osal_dtor(void);
|
2022-09-25 12:47:31 +03:00
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
MDBX_INTERNAL int osal_mb2w(const char *const src, wchar_t **const pdst);
|
2018-06-12 16:43:33 +03:00
|
|
|
#endif /* Windows */
|
|
|
|
|
2017-05-24 13:59:50 +03:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_MAYBE_UNUSED MDBX_NOTHROW_PURE_FUNCTION static inline uint64_t
|
2022-12-31 01:30:52 +03:00
|
|
|
osal_bswap64(uint64_t v) {
|
|
|
|
#if __GNUC_PREREQ(4, 4) || __CLANG_PREREQ(4, 0) || \
|
|
|
|
__has_builtin(__builtin_bswap64)
|
|
|
|
return __builtin_bswap64(v);
|
|
|
|
#elif defined(_MSC_VER) && !defined(__clang__)
|
|
|
|
return _byteswap_uint64(v);
|
|
|
|
#elif defined(__bswap_64)
|
|
|
|
return __bswap_64(v);
|
|
|
|
#elif defined(bswap_64)
|
|
|
|
return bswap_64(v);
|
|
|
|
#else
|
|
|
|
return v << 56 | v >> 56 | ((v << 40) & UINT64_C(0x00ff000000000000)) |
|
|
|
|
((v << 24) & UINT64_C(0x0000ff0000000000)) |
|
|
|
|
((v << 8) & UINT64_C(0x000000ff00000000)) |
|
|
|
|
((v >> 8) & UINT64_C(0x00000000ff000000)) |
|
|
|
|
((v >> 24) & UINT64_C(0x0000000000ff0000)) |
|
|
|
|
((v >> 40) & UINT64_C(0x000000000000ff00));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
MDBX_MAYBE_UNUSED MDBX_NOTHROW_PURE_FUNCTION static inline uint32_t
|
2022-12-31 01:30:52 +03:00
|
|
|
osal_bswap32(uint32_t v) {
|
|
|
|
#if __GNUC_PREREQ(4, 4) || __CLANG_PREREQ(4, 0) || \
|
|
|
|
__has_builtin(__builtin_bswap32)
|
|
|
|
return __builtin_bswap32(v);
|
|
|
|
#elif defined(_MSC_VER) && !defined(__clang__)
|
|
|
|
return _byteswap_ulong(v);
|
|
|
|
#elif defined(__bswap_32)
|
|
|
|
return __bswap_32(v);
|
|
|
|
#elif defined(bswap_32)
|
|
|
|
return bswap_32(v);
|
|
|
|
#else
|
|
|
|
return v << 24 | v >> 24 | ((v << 8) & UINT32_C(0x00ff0000)) |
|
|
|
|
((v >> 8) & UINT32_C(0x0000ff00));
|
|
|
|
#endif
|
|
|
|
}
|