mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-04 19:04:13 +08:00
mdbx: merge branch 'osx-try'.
This resolves https://github.com/leo-yuriev/libmdbx/issues/49. Change-Id: Ib20c3898e99ca229f10e7d41cda3989b8b4a832c
This commit is contained in:
commit
6f0a11f155
@ -7,6 +7,7 @@ compiler:
|
|||||||
|
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
script: if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make all check; fi
|
script: if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make all check; fi
|
||||||
|
|
||||||
|
57
Makefile
57
Makefile
@ -23,6 +23,7 @@ suffix ?=
|
|||||||
|
|
||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
CXX ?= g++
|
CXX ?= g++
|
||||||
|
LD ?= ld
|
||||||
CFLAGS ?= -O2 -g3 -Wall -Werror -Wextra -ffunction-sections -fPIC -fvisibility=hidden
|
CFLAGS ?= -O2 -g3 -Wall -Werror -Wextra -ffunction-sections -fPIC -fvisibility=hidden
|
||||||
|
|
||||||
XCFLAGS ?= -DNDEBUG=1 -DMDBX_DEBUG=0 -DLIBMDBX_EXPORTS=1
|
XCFLAGS ?= -DNDEBUG=1 -DMDBX_DEBUG=0 -DLIBMDBX_EXPORTS=1
|
||||||
@ -32,8 +33,8 @@ 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
|
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
|
# LY: '--no-as-needed,-lrt' for ability to built with modern glibc, but then run with the old
|
||||||
LDFLAGS ?= -Wl,--gc-sections,-z,relro,-O1,--no-as-needed,-lrt
|
LDFLAGS ?= $(shell $(LD) --help 2>/dev/null | grep -q -- --gc-sections && echo '-Wl,--gc-sections,-z,relro,-O1')$(shell $(LD) --help 2>/dev/null | grep -q -- -dead_strip && echo '-Wl,-dead_strip')
|
||||||
EXE_LDFLAGS ?= -pthread -lrt
|
EXE_LDFLAGS ?= -pthread
|
||||||
|
|
||||||
# LY: just for benchmarking
|
# LY: just for benchmarking
|
||||||
IOARENA ?= $(shell \
|
IOARENA ?= $(shell \
|
||||||
@ -44,33 +45,51 @@ NN ?= 25000000
|
|||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
HEADERS := mdbx.h
|
|
||||||
LIBRARIES := libmdbx.a libmdbx.so
|
|
||||||
TOOLS := mdbx_stat mdbx_copy mdbx_dump mdbx_load mdbx_chk
|
|
||||||
MANPAGES := mdbx_stat.1 mdbx_copy.1 mdbx_dump.1 mdbx_load.1
|
|
||||||
SHELL := /bin/bash
|
|
||||||
|
|
||||||
ifdef MSVC
|
ifdef MSVC
|
||||||
|
UNAME := Windows
|
||||||
LCK_IMPL := windows
|
LCK_IMPL := windows
|
||||||
TEST_OSAL := windows
|
TEST_OSAL := windows
|
||||||
|
TEST_ITER := 42
|
||||||
else
|
else
|
||||||
|
UNAME := $(shell uname -s 2>/dev/null || echo Unknown)
|
||||||
define uname2lck
|
define uname2lck
|
||||||
case "`uname -s 2>/dev/null`" in
|
case "$(UNAME)" in
|
||||||
Linux) echo linux;;
|
Linux) echo linux;;
|
||||||
CYGWIN*|MINGW32*|MSYS*) echo windows;;
|
CYGWIN*|MINGW32*|MSYS*|Windows*) echo windows;;
|
||||||
*) echo posix;;
|
*) echo posix;;
|
||||||
esac
|
esac
|
||||||
endef
|
endef
|
||||||
define uname2osal
|
define uname2osal
|
||||||
case "`uname -s 2>/dev/null`" in
|
case "$(UNAME)" in
|
||||||
CYGWIN*|MINGW32*|MSYS*) echo windows;;
|
CYGWIN*|MINGW32*|MSYS*|Windows*) echo windows;;
|
||||||
*) echo unix;;
|
*) echo unix;;
|
||||||
esac
|
esac
|
||||||
endef
|
endef
|
||||||
|
define uname2titer
|
||||||
|
case "$(UNAME)" in
|
||||||
|
Darwin*|Mach*) echo 3;;
|
||||||
|
*) echo 42;;
|
||||||
|
esac
|
||||||
|
endef
|
||||||
|
define uname2suffix
|
||||||
|
case "$(UNAME)" in
|
||||||
|
Darwin*|Mach*) echo dylib;;
|
||||||
|
CYGWIN*|MINGW32*|MSYS*|Windows*) echo dll;;
|
||||||
|
*) echo so;;
|
||||||
|
esac
|
||||||
|
endef
|
||||||
LCK_IMPL := $(shell $(uname2lck))
|
LCK_IMPL := $(shell $(uname2lck))
|
||||||
TEST_OSAL := $(shell $(uname2osal))
|
TEST_OSAL := $(shell $(uname2osal))
|
||||||
|
TEST_ITER := $(shell $(uname2titer))
|
||||||
|
SO_SUFFIX := $(shell $(uname2suffix))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
HEADERS := mdbx.h
|
||||||
|
LIBRARIES := libmdbx.a libmdbx.$(SO_SUFFIX)
|
||||||
|
TOOLS := mdbx_stat mdbx_copy mdbx_dump mdbx_load mdbx_chk
|
||||||
|
MANPAGES := mdbx_stat.1 mdbx_copy.1 mdbx_dump.1 mdbx_load.1
|
||||||
|
SHELL := /bin/bash
|
||||||
|
|
||||||
CORE_SRC := src/lck-$(LCK_IMPL).c $(filter-out $(wildcard src/lck-*.c), $(wildcard src/*.c))
|
CORE_SRC := src/lck-$(LCK_IMPL).c $(filter-out $(wildcard src/lck-*.c), $(wildcard src/*.c))
|
||||||
CORE_INC := $(wildcard src/*.h)
|
CORE_INC := $(wildcard src/*.h)
|
||||||
CORE_OBJ := $(patsubst %.c,%.o,$(CORE_SRC))
|
CORE_OBJ := $(patsubst %.c,%.o,$(CORE_SRC))
|
||||||
@ -82,10 +101,10 @@ TEST_OBJ := $(patsubst %.cc,%.o,$(TEST_SRC))
|
|||||||
|
|
||||||
all: $(LIBRARIES) $(TOOLS) mdbx_test example
|
all: $(LIBRARIES) $(TOOLS) mdbx_test example
|
||||||
|
|
||||||
mdbx: libmdbx.a libmdbx.so
|
mdbx: libmdbx.a libmdbx.$(SO_SUFFIX)
|
||||||
|
|
||||||
example: mdbx.h tutorial/sample-mdbx.c libmdbx.so
|
example: mdbx.h tutorial/sample-mdbx.c libmdbx.$(SO_SUFFIX)
|
||||||
$(CC) $(CFLAGS) -I. tutorial/sample-mdbx.c ./libmdbx.so -o example
|
$(CC) $(CFLAGS) -I. tutorial/sample-mdbx.c ./libmdbx.$(SO_SUFFIX) -o example
|
||||||
|
|
||||||
tools: $(TOOLS)
|
tools: $(TOOLS)
|
||||||
|
|
||||||
@ -103,7 +122,7 @@ clean:
|
|||||||
rm -rf $(TOOLS) mdbx_test @* *.[ao] *.[ls]o *~ tmp.db/* *.gcov *.log *.err src/*.o test/*.o
|
rm -rf $(TOOLS) mdbx_test @* *.[ao] *.[ls]o *~ tmp.db/* *.gcov *.log *.err src/*.o test/*.o
|
||||||
|
|
||||||
check: all
|
check: all
|
||||||
rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; ./mdbx_test --repeat=42 --pathname=$(TESTDB) --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) \
|
rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; ./mdbx_test --repeat=$(TEST_ITER) --pathname=$(TESTDB) --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) \
|
||||||
&& ./mdbx_chk -vvn $(TESTDB) && ./mdbx_chk -vvn $(TESTDB)-copy
|
&& ./mdbx_chk -vvn $(TESTDB) && ./mdbx_chk -vvn $(TESTDB)-copy
|
||||||
|
|
||||||
check-singleprocess: all
|
check-singleprocess: all
|
||||||
@ -134,13 +153,13 @@ $(foreach file,$(TEST_SRC),$(eval $(call test-rule,$(file))))
|
|||||||
libmdbx.a: $(CORE_OBJ)
|
libmdbx.a: $(CORE_OBJ)
|
||||||
$(AR) rs $@ $?
|
$(AR) rs $@ $?
|
||||||
|
|
||||||
libmdbx.so: $(CORE_OBJ)
|
libmdbx.$(SO_SUFFIX): $(CORE_OBJ)
|
||||||
$(CC) $(CFLAGS) -save-temps $^ -pthread -shared $(LDFLAGS) -o $@
|
$(CC) $(CFLAGS) -save-temps $^ -pthread -shared $(LDFLAGS) -o $@
|
||||||
|
|
||||||
mdbx_%: src/tools/mdbx_%.c libmdbx.a
|
mdbx_%: src/tools/mdbx_%.c libmdbx.a
|
||||||
$(CC) $(CFLAGS) $^ $(EXE_LDFLAGS) -o $@
|
$(CC) $(CFLAGS) $^ $(EXE_LDFLAGS) -o $@
|
||||||
|
|
||||||
mdbx_test: $(TEST_OBJ) libmdbx.so
|
mdbx_test: $(TEST_OBJ) libmdbx.$(SO_SUFFIX)
|
||||||
$(CXX) $(CXXFLAGS) $(TEST_OBJ) -Wl,-rpath . -L . -l mdbx $(EXE_LDFLAGS) -o $@
|
$(CXX) $(CXXFLAGS) $(TEST_OBJ) -Wl,-rpath . -L . -l mdbx $(EXE_LDFLAGS) -o $@
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@ -166,7 +185,7 @@ bench-$(1)_$(2).txt: $(3) $(IOARENA) Makefile
|
|||||||
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
$(eval $(call bench-rule,mdbx,$(NN),libmdbx.so))
|
$(eval $(call bench-rule,mdbx,$(NN),libmdbx.$(SO_SUFFIX)))
|
||||||
|
|
||||||
$(eval $(call bench-rule,sophia,$(NN)))
|
$(eval $(call bench-rule,sophia,$(NN)))
|
||||||
$(eval $(call bench-rule,leveldb,$(NN)))
|
$(eval $(call bench-rule,leveldb,$(NN)))
|
||||||
|
10
src/bits.h
10
src/bits.h
@ -23,6 +23,12 @@
|
|||||||
# undef NDEBUG
|
# undef NDEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MDBX_OSX_WANNA_DURABILITY 0 /* using fcntl(F_FULLFSYNC) with 5-10 times slowdown */
|
||||||
|
#define MDBX_OSX_WANNA_SPEED 1 /* using fsync() with chance of data lost on power failure */
|
||||||
|
#ifndef MDBX_OSX_SPEED_OR_DURABILITY
|
||||||
|
#define MDBX_OSX_SPEED_OR_DURABILITY MDBX_OSX_WANNA_DURABILITY
|
||||||
|
#endif
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* Should be defined before any includes */
|
/* Should be defined before any includes */
|
||||||
@ -30,6 +36,10 @@
|
|||||||
# define _FILE_OFFSET_BITS 64
|
# define _FILE_OFFSET_BITS 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#define _DARWIN_C_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# if _MSC_VER < 1400
|
# if _MSC_VER < 1400
|
||||||
# error "Microsoft Visual C++ 8.0 (Visual Studio 2005) or later version is required"
|
# error "Microsoft Visual C++ 8.0 (Visual Studio 2005) or later version is required"
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
* even though they don't support Robust Mutexes.
|
* even though they don't support Robust Mutexes.
|
||||||
* Compile with -DMDBX_USE_ROBUST=0. */
|
* Compile with -DMDBX_USE_ROBUST=0. */
|
||||||
#ifndef MDBX_USE_ROBUST
|
#ifndef MDBX_USE_ROBUST
|
||||||
#if defined(EOWNERDEAD) || _POSIX_C_SOURCE >= 200809L
|
#if (defined(EOWNERDEAD) || _POSIX_C_SOURCE >= 200809L) && !defined(__APPLE__)
|
||||||
#define MDBX_USE_ROBUST 1
|
#define MDBX_USE_ROBUST 1
|
||||||
#else
|
#else
|
||||||
#define MDBX_USE_ROBUST 0
|
#define MDBX_USE_ROBUST 0
|
||||||
|
52
src/mdbx.c
52
src/mdbx.c
@ -292,6 +292,16 @@ static CRITICAL_SECTION rthc_critical_section;
|
|||||||
#else
|
#else
|
||||||
int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj, void *dso_symbol)
|
int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj, void *dso_symbol)
|
||||||
__attribute__((weak));
|
__attribute__((weak));
|
||||||
|
#ifdef __APPLE__ /* FIXME: Thread-Local Storage destructors & DSO-unloading */
|
||||||
|
int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj,
|
||||||
|
void *dso_symbol) {
|
||||||
|
(void)dtor;
|
||||||
|
(void)obj;
|
||||||
|
(void)dso_symbol;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* __APPLE__ */
|
||||||
|
|
||||||
static pthread_mutex_t mdbx_rthc_mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t mdbx_rthc_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static pthread_cond_t mdbx_rthc_cond = PTHREAD_COND_INITIALIZER;
|
static pthread_cond_t mdbx_rthc_cond = PTHREAD_COND_INITIALIZER;
|
||||||
static mdbx_thread_key_t mdbx_rthc_key;
|
static mdbx_thread_key_t mdbx_rthc_key;
|
||||||
@ -515,9 +525,9 @@ __cold void mdbx_rthc_global_dtor(void) {
|
|||||||
mdbx_thread_key_delete(key);
|
mdbx_thread_key_delete(key);
|
||||||
for (MDBX_reader *rthc = rthc_table[i].begin; rthc < rthc_table[i].end;
|
for (MDBX_reader *rthc = rthc_table[i].begin; rthc < rthc_table[i].end;
|
||||||
++rthc) {
|
++rthc) {
|
||||||
mdbx_trace("== [%i] = key %u, %p ... %p, rthc %p (%+i), "
|
mdbx_trace("== [%i] = key %zu, %p ... %p, rthc %p (%+i), "
|
||||||
"rthc-pid %i, current-pid %i",
|
"rthc-pid %i, current-pid %i",
|
||||||
i, key, rthc_table[i].begin, rthc_table[i].end, rthc,
|
i, (size_t)key, rthc_table[i].begin, rthc_table[i].end, rthc,
|
||||||
(int)(rthc - rthc_table[i].begin), rthc->mr_pid, self_pid);
|
(int)(rthc - rthc_table[i].begin), rthc->mr_pid, self_pid);
|
||||||
if (rthc->mr_pid == self_pid) {
|
if (rthc->mr_pid == self_pid) {
|
||||||
rthc->mr_pid = 0;
|
rthc->mr_pid = 0;
|
||||||
@ -553,8 +563,8 @@ __cold int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin,
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
mdbx_rthc_lock();
|
mdbx_rthc_lock();
|
||||||
mdbx_trace(">> key 0x%x, rthc_count %u, rthc_limit %u", *key, rthc_count,
|
mdbx_trace(">> key %zu, rthc_count %u, rthc_limit %u", (size_t)*key,
|
||||||
rthc_limit);
|
rthc_count, rthc_limit);
|
||||||
if (rthc_count == rthc_limit) {
|
if (rthc_count == rthc_limit) {
|
||||||
rthc_entry_t *new_table =
|
rthc_entry_t *new_table =
|
||||||
mdbx_realloc((rthc_table == rthc_table_static) ? nullptr : rthc_table,
|
mdbx_realloc((rthc_table == rthc_table_static) ? nullptr : rthc_table,
|
||||||
@ -568,13 +578,14 @@ __cold int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin,
|
|||||||
rthc_table = new_table;
|
rthc_table = new_table;
|
||||||
rthc_limit *= 2;
|
rthc_limit *= 2;
|
||||||
}
|
}
|
||||||
mdbx_trace("== [%i] = key %u, %p ... %p", rthc_count, *key, begin, end);
|
mdbx_trace("== [%i] = key %zu, %p ... %p", rthc_count, (size_t)*key, begin,
|
||||||
|
end);
|
||||||
rthc_table[rthc_count].key = *key;
|
rthc_table[rthc_count].key = *key;
|
||||||
rthc_table[rthc_count].begin = begin;
|
rthc_table[rthc_count].begin = begin;
|
||||||
rthc_table[rthc_count].end = end;
|
rthc_table[rthc_count].end = end;
|
||||||
++rthc_count;
|
++rthc_count;
|
||||||
mdbx_trace("<< key 0x%x, rthc_count %u, rthc_limit %u", *key, rthc_count,
|
mdbx_trace("<< key %zu, rthc_count %u, rthc_limit %u", (size_t)*key,
|
||||||
rthc_limit);
|
rthc_count, rthc_limit);
|
||||||
mdbx_rthc_unlock();
|
mdbx_rthc_unlock();
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
|
|
||||||
@ -587,8 +598,8 @@ bailout:
|
|||||||
__cold void mdbx_rthc_remove(const mdbx_thread_key_t key) {
|
__cold void mdbx_rthc_remove(const mdbx_thread_key_t key) {
|
||||||
mdbx_thread_key_delete(key);
|
mdbx_thread_key_delete(key);
|
||||||
mdbx_rthc_lock();
|
mdbx_rthc_lock();
|
||||||
mdbx_trace(">> key 0x%x, rthc_count %u, rthc_limit %u", key, rthc_count,
|
mdbx_trace(">> key %zu, rthc_count %u, rthc_limit %u", (size_t)key,
|
||||||
rthc_limit);
|
rthc_count, rthc_limit);
|
||||||
|
|
||||||
for (unsigned i = 0; i < rthc_count; ++i) {
|
for (unsigned i = 0; i < rthc_count; ++i) {
|
||||||
if (key == rthc_table[i].key) {
|
if (key == rthc_table[i].key) {
|
||||||
@ -614,8 +625,8 @@ __cold void mdbx_rthc_remove(const mdbx_thread_key_t key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mdbx_trace("<< key 0x%x, rthc_count %u, rthc_limit %u", key, rthc_count,
|
mdbx_trace("<< key %zu, rthc_count %u, rthc_limit %u", (size_t)key,
|
||||||
rthc_limit);
|
rthc_count, rthc_limit);
|
||||||
mdbx_rthc_unlock();
|
mdbx_rthc_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3030,7 +3041,7 @@ __cold static int mdbx_env_sync_ex(MDBX_env *env, int force, int nonblock) {
|
|||||||
int rc = (flags & MDBX_WRITEMAP)
|
int rc = (flags & MDBX_WRITEMAP)
|
||||||
? mdbx_msync(&env->me_dxb_mmap, 0, usedbytes,
|
? mdbx_msync(&env->me_dxb_mmap, 0, usedbytes,
|
||||||
flags & MDBX_MAPASYNC)
|
flags & MDBX_MAPASYNC)
|
||||||
: mdbx_filesync(env->me_fd, false);
|
: mdbx_filesync(env->me_fd, MDBX_SYNC_DATA);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -5411,14 +5422,16 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags,
|
|||||||
goto fail;
|
goto fail;
|
||||||
if ((flags & MDBX_MAPASYNC) == 0) {
|
if ((flags & MDBX_MAPASYNC) == 0) {
|
||||||
if (unlikely(pending->mm_geo.next > steady->mm_geo.now)) {
|
if (unlikely(pending->mm_geo.next > steady->mm_geo.now)) {
|
||||||
rc = mdbx_filesize_sync(env->me_fd);
|
rc = mdbx_filesync(env->me_fd, MDBX_SYNC_SIZE);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
env->me_sync_pending = 0;
|
env->me_sync_pending = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = mdbx_filesync(env->me_fd, pending->mm_geo.next > steady->mm_geo.now);
|
rc = mdbx_filesync(env->me_fd, (pending->mm_geo.next > steady->mm_geo.now)
|
||||||
|
? MDBX_SYNC_DATA | MDBX_SYNC_SIZE
|
||||||
|
: MDBX_SYNC_DATA);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
goto fail;
|
goto fail;
|
||||||
env->me_sync_pending = 0;
|
env->me_sync_pending = 0;
|
||||||
@ -5566,7 +5579,7 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags,
|
|||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
goto fail;
|
goto fail;
|
||||||
} else {
|
} else {
|
||||||
rc = mdbx_filesync(env->me_fd, false);
|
rc = mdbx_filesync(env->me_fd, MDBX_SYNC_DATA | MDBX_SYNC_IODQ);
|
||||||
if (rc != MDBX_SUCCESS)
|
if (rc != MDBX_SUCCESS)
|
||||||
goto undo;
|
goto undo;
|
||||||
}
|
}
|
||||||
@ -11814,12 +11827,15 @@ int __cold mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd,
|
|||||||
mdbx_txn_abort(read_txn);
|
mdbx_txn_abort(read_txn);
|
||||||
|
|
||||||
if (likely(rc == MDBX_SUCCESS))
|
if (likely(rc == MDBX_SUCCESS))
|
||||||
rc = mdbx_filesync(fd, true);
|
rc = mdbx_filesync(fd, MDBX_SYNC_DATA | MDBX_SYNC_SIZE);
|
||||||
|
|
||||||
/* Write actual meta */
|
/* Write actual meta */
|
||||||
if (likely(rc == MDBX_SUCCESS))
|
if (likely(rc == MDBX_SUCCESS))
|
||||||
rc = mdbx_pwrite(fd, buffer, pgno2bytes(env, NUM_METAS), 0);
|
rc = mdbx_pwrite(fd, buffer, pgno2bytes(env, NUM_METAS), 0);
|
||||||
|
|
||||||
|
if (likely(rc == MDBX_SUCCESS))
|
||||||
|
rc = mdbx_filesync(fd, MDBX_SYNC_DATA | MDBX_SYNC_IODQ);
|
||||||
|
|
||||||
mdbx_memalign_free(buffer);
|
mdbx_memalign_free(buffer);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -12860,7 +12876,7 @@ int __cold mdbx_setup_debug(int flags, MDBX_debug_func *logger) {
|
|||||||
unsigned ret = mdbx_runtime_flags;
|
unsigned ret = mdbx_runtime_flags;
|
||||||
mdbx_runtime_flags = flags;
|
mdbx_runtime_flags = flags;
|
||||||
|
|
||||||
#ifdef __linux__
|
#if defined(__linux__) || defined(__gnu_linux__)
|
||||||
if (flags & MDBX_DBG_DUMP) {
|
if (flags & MDBX_DBG_DUMP) {
|
||||||
int core_filter_fd = open("/proc/self/coredump_filter", O_TRUNC | O_RDWR);
|
int core_filter_fd = open("/proc/self/coredump_filter", O_TRUNC | O_RDWR);
|
||||||
if (core_filter_fd >= 0) {
|
if (core_filter_fd >= 0) {
|
||||||
@ -12883,7 +12899,7 @@ int __cold mdbx_setup_debug(int flags, MDBX_debug_func *logger) {
|
|||||||
close(core_filter_fd);
|
close(core_filter_fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* __linux__ */
|
#endif /* Linux */
|
||||||
|
|
||||||
mdbx_debug_logger = logger;
|
mdbx_debug_logger = logger;
|
||||||
return ret;
|
return ret;
|
||||||
|
67
src/osal.c
67
src/osal.c
@ -159,9 +159,14 @@ typedef struct _FILE_PROVIDER_EXTERNAL_INFO_V1 {
|
|||||||
/* Prototype should match libc runtime. ISO POSIX (2003) & LSB 1.x-3.x */
|
/* Prototype should match libc runtime. ISO POSIX (2003) & LSB 1.x-3.x */
|
||||||
__nothrow __noreturn void __assert_fail(const char *assertion, const char *file,
|
__nothrow __noreturn void __assert_fail(const char *assertion, const char *file,
|
||||||
unsigned line, const char *function);
|
unsigned line, const char *function);
|
||||||
#elif (defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
|
#elif defined(__APPLE__) || defined(__MACH__)
|
||||||
defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \
|
__nothrow __noreturn void __assert_rtn(const char *function, const char *file,
|
||||||
defined(__DragonFly__))
|
int line, const char *assertion);
|
||||||
|
#define __assert_fail(assertion, file, line, function) \
|
||||||
|
__assert_rtn(function, file, line, assertion)
|
||||||
|
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||||
|
defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \
|
||||||
|
defined(__DragonFly__)
|
||||||
__nothrow __noreturn void __assert(const char *function, const char *file,
|
__nothrow __noreturn void __assert(const char *function, const char *file,
|
||||||
int line, const char *assertion);
|
int line, const char *assertion);
|
||||||
#define __assert_fail(assertion, file, line, function) \
|
#define __assert_fail(assertion, file, line, function) \
|
||||||
@ -548,6 +553,9 @@ int mdbx_openfile(const char *pathname, int flags, mode_t mode,
|
|||||||
if (fd_flags != -1)
|
if (fd_flags != -1)
|
||||||
(void)fcntl(*fd, F_SETFL, fd_flags | O_DIRECT);
|
(void)fcntl(*fd, F_SETFL, fd_flags | O_DIRECT);
|
||||||
#endif /* O_DIRECT */
|
#endif /* O_DIRECT */
|
||||||
|
#if defined(F_NOCACHE)
|
||||||
|
(void)fcntl(*fd, F_NOCACHE, 1);
|
||||||
|
#endif /* F_NOCACHE */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -626,7 +634,7 @@ int mdbx_pwrite(mdbx_filehandle_t fd, const void *buf, size_t bytes,
|
|||||||
|
|
||||||
int mdbx_pwritev(mdbx_filehandle_t fd, struct iovec *iov, int iovcnt,
|
int mdbx_pwritev(mdbx_filehandle_t fd, struct iovec *iov, int iovcnt,
|
||||||
uint64_t offset, size_t expected_written) {
|
uint64_t offset, size_t expected_written) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64) || defined(__APPLE__)
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
for (int i = 0; i < iovcnt; ++i) {
|
for (int i = 0; i < iovcnt; ++i) {
|
||||||
int rc = mdbx_pwrite(fd, iov[i].iov_base, iov[i].iov_len, offset);
|
int rc = mdbx_pwrite(fd, iov[i].iov_base, iov[i].iov_len, offset);
|
||||||
@ -652,11 +660,23 @@ int mdbx_pwritev(mdbx_filehandle_t fd, struct iovec *iov, int iovcnt,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_filesync(mdbx_filehandle_t fd, bool filesize_changed) {
|
int mdbx_filesync(mdbx_filehandle_t fd, enum mdbx_syncmode_bits mode_bits) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
(void)filesize_changed;
|
return ((mode_bits & (MDBX_SYNC_DATA | MDBX_SYNC_IODQ)) == 0 ||
|
||||||
return FlushFileBuffers(fd) ? MDBX_SUCCESS : GetLastError();
|
FlushFileBuffers(fd))
|
||||||
|
? MDBX_SUCCESS
|
||||||
|
: GetLastError();
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && \
|
||||||
|
MDBX_OSX_SPEED_OR_DURABILITY == MDBX_OSX_WANNA_DURABILITY
|
||||||
|
if (mode_bits & MDBX_SYNC_IODQ)
|
||||||
|
return likely(fcntl(fd, F_FULLFSYNC) != -1) ? MDBX_SUCCESS : errno;
|
||||||
|
#endif /* MacOS */
|
||||||
|
#if defined(__linux__) || defined(__gnu_linux__)
|
||||||
|
if (mode_bits == MDBX_SYNC_SIZE && linux_kernel_version >= 0x03060000)
|
||||||
|
return MDBX_SUCCESS;
|
||||||
|
#endif /* Linux */
|
||||||
int rc;
|
int rc;
|
||||||
do {
|
do {
|
||||||
#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
|
#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
|
||||||
@ -665,12 +685,12 @@ int mdbx_filesync(mdbx_filehandle_t fd, bool filesize_changed) {
|
|||||||
*
|
*
|
||||||
* For more info about of a corresponding fdatasync() bug
|
* For more info about of a corresponding fdatasync() bug
|
||||||
* see http://www.spinics.net/lists/linux-ext4/msg33714.html */
|
* see http://www.spinics.net/lists/linux-ext4/msg33714.html */
|
||||||
if (!filesize_changed) {
|
if ((mode_bits & MDBX_SYNC_SIZE) == 0) {
|
||||||
if (fdatasync(fd) == 0)
|
if (fdatasync(fd) == 0)
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
} else
|
} else
|
||||||
#else
|
#else
|
||||||
(void)filesize_changed;
|
(void)mode_bits;
|
||||||
#endif
|
#endif
|
||||||
if (fsync(fd) == 0)
|
if (fsync(fd) == 0)
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
@ -680,22 +700,6 @@ int mdbx_filesync(mdbx_filehandle_t fd, bool filesize_changed) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_filesize_sync(mdbx_filehandle_t fd) {
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
(void)fd;
|
|
||||||
/* Nothing on Windows (i.e. newer 100% steady) */
|
|
||||||
return MDBX_SUCCESS;
|
|
||||||
#else
|
|
||||||
for (;;) {
|
|
||||||
if (fsync(fd) == 0)
|
|
||||||
return MDBX_SUCCESS;
|
|
||||||
int rc = errno;
|
|
||||||
if (rc != EINTR)
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length) {
|
int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
BY_HANDLE_FILE_INFORMATION info;
|
BY_HANDLE_FILE_INFORMATION info;
|
||||||
@ -792,7 +796,13 @@ int mdbx_msync(mdbx_mmap_t *map, size_t offset, size_t length, int async) {
|
|||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
#endif /* Linux */
|
#endif /* Linux */
|
||||||
const int mode = async ? MS_ASYNC : MS_SYNC;
|
const int mode = async ? MS_ASYNC : MS_SYNC;
|
||||||
return (msync(ptr, length, mode) == 0) ? MDBX_SUCCESS : errno;
|
int rc = (msync(ptr, length, mode) == 0) ? MDBX_SUCCESS : errno;
|
||||||
|
#if defined(__APPLE__) && \
|
||||||
|
MDBX_OSX_SPEED_OR_DURABILITY == MDBX_OSX_WANNA_DURABILITY
|
||||||
|
if (rc == MDBX_SUCCESS && mode == MS_SYNC)
|
||||||
|
rc = likely(fcntl(map->fd, F_FULLFSYNC) != -1) ? MDBX_SUCCESS : errno;
|
||||||
|
#endif /* MacOS */
|
||||||
|
return rc;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1165,7 +1175,10 @@ retry_mapview:;
|
|||||||
return rc;
|
return rc;
|
||||||
#else
|
#else
|
||||||
if (limit != map->length) {
|
if (limit != map->length) {
|
||||||
#if defined(_GNU_SOURCE) && !defined(__FreeBSD__)
|
#if defined(_GNU_SOURCE) && \
|
||||||
|
!(defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||||
|
defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \
|
||||||
|
defined(__DragonFly__) || defined(__APPLE__) || defined(__MACH__))
|
||||||
void *ptr = mremap(map->address, map->length, limit,
|
void *ptr = mremap(map->address, map->length, limit,
|
||||||
/* LY: in case changing the mapping size calling code
|
/* LY: in case changing the mapping size calling code
|
||||||
must guarantees the absence of competing threads, and
|
must guarantees the absence of competing threads, and
|
||||||
|
10
src/osal.h
10
src/osal.h
@ -55,7 +55,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#if !(defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
|
#if !(defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||||
defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \
|
defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \
|
||||||
defined(__DragonFly__))
|
defined(__DragonFly__) || defined(__APPLE__) || defined(__MACH__))
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#endif /* xBSD */
|
#endif /* xBSD */
|
||||||
|
|
||||||
@ -522,7 +522,13 @@ int mdbx_thread_create(mdbx_thread_t *thread,
|
|||||||
void *arg);
|
void *arg);
|
||||||
int mdbx_thread_join(mdbx_thread_t thread);
|
int mdbx_thread_join(mdbx_thread_t thread);
|
||||||
|
|
||||||
int mdbx_filesync(mdbx_filehandle_t fd, bool fullsync);
|
enum mdbx_syncmode_bits {
|
||||||
|
MDBX_SYNC_DATA = 1,
|
||||||
|
MDBX_SYNC_SIZE = 2,
|
||||||
|
MDBX_SYNC_IODQ = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
int mdbx_filesync(mdbx_filehandle_t fd, enum mdbx_syncmode_bits mode_bits);
|
||||||
int mdbx_filesize_sync(mdbx_filehandle_t fd);
|
int mdbx_filesize_sync(mdbx_filehandle_t fd);
|
||||||
int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length);
|
int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length);
|
||||||
int mdbx_fseek(mdbx_filehandle_t fd, uint64_t pos);
|
int mdbx_fseek(mdbx_filehandle_t fd, uint64_t pos);
|
||||||
|
@ -39,6 +39,10 @@
|
|||||||
#include <SDKDDKVer.h>
|
#include <SDKDDKVer.h>
|
||||||
#endif /* WINDOWS */
|
#endif /* WINDOWS */
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#define _DARWIN_C_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -102,6 +102,22 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
|
|||||||
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
|
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
|
||||||
int32_t &value, const int32_t minval, const int32_t maxval,
|
int32_t &value, const int32_t minval, const int32_t maxval,
|
||||||
const int32_t default_value = -1);
|
const int32_t default_value = -1);
|
||||||
|
|
||||||
|
inline bool parse_option_intptr(int argc, char *const argv[], int &narg,
|
||||||
|
const char *option, intptr_t &value,
|
||||||
|
const intptr_t minval, const intptr_t maxval,
|
||||||
|
const intptr_t default_value = -1) {
|
||||||
|
static_assert(sizeof(intptr_t) == 4 || sizeof(intptr_t) == 8, "WTF?");
|
||||||
|
if (sizeof(intptr_t) == 8)
|
||||||
|
return parse_option(argc, argv, narg, option,
|
||||||
|
*reinterpret_cast<int64_t *>(&value), int64_t(minval),
|
||||||
|
int64_t(maxval), int64_t(default_value));
|
||||||
|
else
|
||||||
|
return parse_option(argc, argv, narg, option,
|
||||||
|
*reinterpret_cast<int32_t *>(&value), int32_t(minval),
|
||||||
|
int32_t(maxval), int32_t(default_value));
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
24
test/darwin/LICENSE
Normal file
24
test/darwin/LICENSE
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
Copyright (c) 2015, Aleksey Demakov
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
8
test/darwin/README.md
Normal file
8
test/darwin/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# DarwinPthreadBarrier
|
||||||
|
|
||||||
|
A pthread_barrier_t implementation for Mac OS/X
|
||||||
|
|
||||||
|
There is no pthread_barrier_t in Mac OS/X pthreads. This project fixes
|
||||||
|
this omission by providing a simple-minded barrier implementation based
|
||||||
|
on a pair of pthread_mutex_t and pthread_cond_t.
|
||||||
|
|
112
test/darwin/pthread_barrier.c
Normal file
112
test/darwin/pthread_barrier.c
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Aleksey Demakov
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pthread_barrier.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
|
||||||
|
#define __unused __attribute__((unused))
|
||||||
|
|
||||||
|
int pthread_barrierattr_init(pthread_barrierattr_t *attr) {
|
||||||
|
memset(attr, 0, sizeof(pthread_barrierattr_t));
|
||||||
|
int m = pthread_mutexattr_init(&attr->mattr);
|
||||||
|
int c = pthread_condattr_init(&attr->cattr);
|
||||||
|
return m ? m : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_barrierattr_destroy(pthread_barrierattr_t *attr) {
|
||||||
|
int c = pthread_condattr_destroy(&attr->cattr);
|
||||||
|
int m = pthread_mutexattr_destroy(&attr->mattr);
|
||||||
|
return m ? m : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr,
|
||||||
|
int *__restrict pshared) {
|
||||||
|
return pthread_condattr_getpshared(&attr->cattr, pshared);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) {
|
||||||
|
int m = pthread_mutexattr_setpshared(&attr->mattr, pshared);
|
||||||
|
int c = pthread_condattr_setpshared(&attr->cattr, pshared);
|
||||||
|
return m ? m : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_barrier_init(pthread_barrier_t *__restrict barrier,
|
||||||
|
const pthread_barrierattr_t *__restrict attr,
|
||||||
|
unsigned count) {
|
||||||
|
if (count == 0)
|
||||||
|
return errno = EINVAL;
|
||||||
|
|
||||||
|
int rc = pthread_mutex_init(&barrier->mutex, attr ? &attr->mattr : 0);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = pthread_cond_init(&barrier->cond, attr ? &attr->cattr : 0);
|
||||||
|
if (rc) {
|
||||||
|
int errno_save = errno;
|
||||||
|
pthread_mutex_destroy(&barrier->mutex);
|
||||||
|
errno = errno_save;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
barrier->limit = count;
|
||||||
|
barrier->count = 0;
|
||||||
|
barrier->phase = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_barrier_destroy(pthread_barrier_t *barrier) {
|
||||||
|
pthread_mutex_destroy(&barrier->mutex);
|
||||||
|
pthread_cond_destroy(&barrier->cond);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_barrier_wait(pthread_barrier_t *barrier) {
|
||||||
|
int rc = pthread_mutex_lock(&barrier->mutex);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
barrier->count++;
|
||||||
|
if (barrier->count >= barrier->limit) {
|
||||||
|
barrier->phase++;
|
||||||
|
barrier->count = 0;
|
||||||
|
pthread_cond_broadcast(&barrier->cond);
|
||||||
|
pthread_mutex_unlock(&barrier->mutex);
|
||||||
|
return PTHREAD_BARRIER_SERIAL_THREAD;
|
||||||
|
} else {
|
||||||
|
unsigned phase = barrier->phase;
|
||||||
|
do
|
||||||
|
pthread_cond_wait(&barrier->cond, &barrier->mutex);
|
||||||
|
while (phase == barrier->phase);
|
||||||
|
pthread_mutex_unlock(&barrier->mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __APPLE__ */
|
83
test/darwin/pthread_barrier.h
Normal file
83
test/darwin/pthread_barrier.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Aleksey Demakov
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PTHREAD_BARRIER_H
|
||||||
|
#define PTHREAD_BARRIER_H
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(PTHREAD_BARRIER_SERIAL_THREAD)
|
||||||
|
#define PTHREAD_BARRIER_SERIAL_THREAD (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(PTHREAD_PROCESS_PRIVATE)
|
||||||
|
#define PTHREAD_PROCESS_PRIVATE (42)
|
||||||
|
#endif
|
||||||
|
#if !defined(PTHREAD_PROCESS_SHARED)
|
||||||
|
#define PTHREAD_PROCESS_SHARED (43)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
pthread_mutexattr_t mattr;
|
||||||
|
pthread_condattr_t cattr;
|
||||||
|
} pthread_barrierattr_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
unsigned int limit;
|
||||||
|
unsigned int count;
|
||||||
|
unsigned int phase;
|
||||||
|
} pthread_barrier_t;
|
||||||
|
|
||||||
|
int pthread_barrierattr_init(pthread_barrierattr_t *attr);
|
||||||
|
int pthread_barrierattr_destroy(pthread_barrierattr_t *attr);
|
||||||
|
|
||||||
|
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr,
|
||||||
|
int *__restrict pshared);
|
||||||
|
int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared);
|
||||||
|
|
||||||
|
int pthread_barrier_init(pthread_barrier_t *__restrict barrier,
|
||||||
|
const pthread_barrierattr_t *__restrict attr,
|
||||||
|
unsigned int count);
|
||||||
|
int pthread_barrier_destroy(pthread_barrier_t *barrier);
|
||||||
|
|
||||||
|
int pthread_barrier_wait(pthread_barrier_t *barrier);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __APPLE__ */
|
||||||
|
|
||||||
|
#endif /* PTHREAD_BARRIER_H */
|
20
test/main.cc
20
test/main.cc
@ -182,17 +182,19 @@ int main(int argc, char *const argv[]) {
|
|||||||
params.datalen_max = datalen_max;
|
params.datalen_max = datalen_max;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (config::parse_option(argc, argv, narg, "size-lower", params.size_lower,
|
if (config::parse_option_intptr(argc, argv, narg, "size-lower",
|
||||||
mdbx_limits_dbsize_min(params.pagesize),
|
params.size_lower,
|
||||||
mdbx_limits_dbsize_max(params.pagesize)))
|
mdbx_limits_dbsize_min(params.pagesize),
|
||||||
|
mdbx_limits_dbsize_max(params.pagesize)))
|
||||||
continue;
|
continue;
|
||||||
if (config::parse_option(argc, argv, narg, "size-upper", params.size_upper,
|
if (config::parse_option_intptr(argc, argv, narg, "size-upper",
|
||||||
mdbx_limits_dbsize_min(params.pagesize),
|
params.size_upper,
|
||||||
mdbx_limits_dbsize_max(params.pagesize)))
|
mdbx_limits_dbsize_min(params.pagesize),
|
||||||
|
mdbx_limits_dbsize_max(params.pagesize)))
|
||||||
continue;
|
continue;
|
||||||
if (config::parse_option(argc, argv, narg, "size", params.size_now,
|
if (config::parse_option_intptr(argc, argv, narg, "size", params.size_now,
|
||||||
mdbx_limits_dbsize_min(params.pagesize),
|
mdbx_limits_dbsize_min(params.pagesize),
|
||||||
mdbx_limits_dbsize_max(params.pagesize)))
|
mdbx_limits_dbsize_max(params.pagesize)))
|
||||||
continue;
|
continue;
|
||||||
if (config::parse_option(
|
if (config::parse_option(
|
||||||
argc, argv, narg, "shrink-threshold", params.shrink_threshold, 0,
|
argc, argv, narg, "shrink-threshold", params.shrink_threshold, 0,
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include "darwin/pthread_barrier.c"
|
||||||
|
#endif
|
||||||
|
|
||||||
struct shared_t {
|
struct shared_t {
|
||||||
pthread_barrier_t barrier;
|
pthread_barrier_t barrier;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
25
test/ttl.cc
25
test/ttl.cc
@ -53,11 +53,26 @@ bool testcase_ttl::run() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* LY: для параметризации используем подходящие параметры, которые не имеют
|
/* LY: для параметризации используем подходящие параметры, которые не имеют
|
||||||
* здесь смысла в первоначальном значении */
|
* здесь смысла в первоначальном значении. */
|
||||||
const unsigned window_max =
|
const unsigned window_max_lower =
|
||||||
(config.params.batch_read > 999) ? config.params.batch_read : 1000;
|
#ifdef __APPLE__
|
||||||
const unsigned count_max =
|
333;
|
||||||
(config.params.batch_write > 999) ? config.params.batch_write : 1000;
|
#else
|
||||||
|
999;
|
||||||
|
#endif
|
||||||
|
const unsigned count_max_lower =
|
||||||
|
#ifdef __APPLE__
|
||||||
|
333;
|
||||||
|
#else
|
||||||
|
999;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const unsigned window_max = (config.params.batch_read > window_max_lower)
|
||||||
|
? config.params.batch_read
|
||||||
|
: window_max_lower;
|
||||||
|
const unsigned count_max = (config.params.batch_write > count_max_lower)
|
||||||
|
? config.params.batch_write
|
||||||
|
: count_max_lower;
|
||||||
log_info("ttl: using `batch_read` value %u for window_max", window_max);
|
log_info("ttl: using `batch_read` value %u for window_max", window_max);
|
||||||
log_info("ttl: using `batch_write` value %u for count_max", count_max);
|
log_info("ttl: using `batch_write` value %u for count_max", count_max);
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
#if defined(HAVE_IEEE754_H) || __has_include(<ieee754.h>)
|
#if defined(HAVE_IEEE754_H) || __has_include(<ieee754.h>)
|
||||||
#include <ieee754.h>
|
#include <ieee754.h>
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(__APPLE__) || defined(__MACH__)
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
#endif /* defined(__APPLE__) || defined(__MACH__) */
|
||||||
|
|
||||||
std::string format(const char *fmt, ...) {
|
std::string format(const char *fmt, ...) {
|
||||||
va_list ap, ones;
|
va_list ap, ones;
|
||||||
|
10
test/utils.h
10
test/utils.h
@ -247,18 +247,20 @@ struct simple_checksum {
|
|||||||
|
|
||||||
simple_checksum() : value(0) {}
|
simple_checksum() : value(0) {}
|
||||||
|
|
||||||
void push(uint32_t data) {
|
void push(const uint32_t &data) {
|
||||||
value += data * UINT64_C(9386433910765580089) + 1;
|
value += data * UINT64_C(9386433910765580089) + 1;
|
||||||
value ^= value >> 41;
|
value ^= value >> 41;
|
||||||
value *= UINT64_C(0xBD9CACC22C6E9571);
|
value *= UINT64_C(0xBD9CACC22C6E9571);
|
||||||
}
|
}
|
||||||
|
|
||||||
void push(uint64_t data) {
|
void push(const uint64_t &data) {
|
||||||
push((uint32_t)data);
|
push((uint32_t)data);
|
||||||
push((uint32_t)(data >> 32));
|
push((uint32_t)(data >> 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
void push(bool data) { push(data ? UINT32_C(0x780E) : UINT32_C(0xFA18E)); }
|
void push(const bool data) {
|
||||||
|
push(data ? UINT32_C(0x780E) : UINT32_C(0xFA18E));
|
||||||
|
}
|
||||||
|
|
||||||
void push(const void *ptr, size_t bytes) {
|
void push(const void *ptr, size_t bytes) {
|
||||||
const uint8_t *data = (const uint8_t *)ptr;
|
const uint8_t *data = (const uint8_t *)ptr;
|
||||||
@ -271,7 +273,7 @@ struct simple_checksum {
|
|||||||
void push(const std::string &str) { push(str.data(), str.size()); }
|
void push(const std::string &str) { push(str.data(), str.size()); }
|
||||||
|
|
||||||
void push(unsigned salt, const MDBX_val &val) {
|
void push(unsigned salt, const MDBX_val &val) {
|
||||||
push(val.iov_len);
|
push(unsigned(val.iov_len));
|
||||||
push(salt);
|
push(salt);
|
||||||
push(val.iov_base, val.iov_len);
|
push(val.iov_base, val.iov_len);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user