mdbx: merge branch 'osx-try'.

This resolves https://github.com/leo-yuriev/libmdbx/issues/49.

Change-Id: Ib20c3898e99ca229f10e7d41cda3989b8b4a832c
This commit is contained in:
Leonid Yuriev 2019-08-20 03:18:31 +03:00
commit 6f0a11f155
18 changed files with 423 additions and 85 deletions

View File

@ -7,6 +7,7 @@ compiler:
os:
- linux
- osx
script: if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make all check; fi

View File

@ -23,6 +23,7 @@ suffix ?=
CC ?= gcc
CXX ?= g++
LD ?= ld
CFLAGS ?= -O2 -g3 -Wall -Werror -Wextra -ffunction-sections -fPIC -fvisibility=hidden
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
# 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
EXE_LDFLAGS ?= -pthread -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
# LY: just for benchmarking
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
UNAME := Windows
LCK_IMPL := windows
TEST_OSAL := windows
TEST_ITER := 42
else
UNAME := $(shell uname -s 2>/dev/null || echo Unknown)
define uname2lck
case "`uname -s 2>/dev/null`" in
case "$(UNAME)" in
Linux) echo linux;;
CYGWIN*|MINGW32*|MSYS*) echo windows;;
CYGWIN*|MINGW32*|MSYS*|Windows*) echo windows;;
*) echo posix;;
esac
endef
define uname2osal
case "`uname -s 2>/dev/null`" in
CYGWIN*|MINGW32*|MSYS*) echo windows;;
case "$(UNAME)" in
CYGWIN*|MINGW32*|MSYS*|Windows*) echo windows;;
*) echo unix;;
esac
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))
TEST_OSAL := $(shell $(uname2osal))
TEST_ITER := $(shell $(uname2titer))
SO_SUFFIX := $(shell $(uname2suffix))
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_INC := $(wildcard src/*.h)
CORE_OBJ := $(patsubst %.c,%.o,$(CORE_SRC))
@ -82,10 +101,10 @@ TEST_OBJ := $(patsubst %.cc,%.o,$(TEST_SRC))
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
$(CC) $(CFLAGS) -I. tutorial/sample-mdbx.c ./libmdbx.so -o example
example: mdbx.h tutorial/sample-mdbx.c libmdbx.$(SO_SUFFIX)
$(CC) $(CFLAGS) -I. tutorial/sample-mdbx.c ./libmdbx.$(SO_SUFFIX) -o example
tools: $(TOOLS)
@ -103,7 +122,7 @@ clean:
rm -rf $(TOOLS) mdbx_test @* *.[ao] *.[ls]o *~ tmp.db/* *.gcov *.log *.err src/*.o test/*.o
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
check-singleprocess: all
@ -134,13 +153,13 @@ $(foreach file,$(TEST_SRC),$(eval $(call test-rule,$(file))))
libmdbx.a: $(CORE_OBJ)
$(AR) rs $@ $?
libmdbx.so: $(CORE_OBJ)
libmdbx.$(SO_SUFFIX): $(CORE_OBJ)
$(CC) $(CFLAGS) -save-temps $^ -pthread -shared $(LDFLAGS) -o $@
mdbx_%: src/tools/mdbx_%.c libmdbx.a
$(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 $@
###############################################################################
@ -166,7 +185,7 @@ bench-$(1)_$(2).txt: $(3) $(IOARENA) Makefile
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,leveldb,$(NN)))

View File

@ -23,6 +23,12 @@
# undef NDEBUG
#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 */
@ -30,6 +36,10 @@
# define _FILE_OFFSET_BITS 64
#endif
#ifdef __APPLE__
#define _DARWIN_C_SOURCE
#endif
#ifdef _MSC_VER
# if _MSC_VER < 1400
# error "Microsoft Visual C++ 8.0 (Visual Studio 2005) or later version is required"

View File

@ -18,7 +18,7 @@
* even though they don't support Robust Mutexes.
* Compile with -DMDBX_USE_ROBUST=0. */
#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
#else
#define MDBX_USE_ROBUST 0

View File

@ -292,6 +292,16 @@ static CRITICAL_SECTION rthc_critical_section;
#else
int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj, void *dso_symbol)
__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_cond_t mdbx_rthc_cond = PTHREAD_COND_INITIALIZER;
static mdbx_thread_key_t mdbx_rthc_key;
@ -515,9 +525,9 @@ __cold void mdbx_rthc_global_dtor(void) {
mdbx_thread_key_delete(key);
for (MDBX_reader *rthc = rthc_table[i].begin; rthc < rthc_table[i].end;
++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",
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);
if (rthc->mr_pid == self_pid) {
rthc->mr_pid = 0;
@ -553,8 +563,8 @@ __cold int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin,
return rc;
mdbx_rthc_lock();
mdbx_trace(">> key 0x%x, rthc_count %u, rthc_limit %u", *key, rthc_count,
rthc_limit);
mdbx_trace(">> key %zu, rthc_count %u, rthc_limit %u", (size_t)*key,
rthc_count, rthc_limit);
if (rthc_count == rthc_limit) {
rthc_entry_t *new_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_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].begin = begin;
rthc_table[rthc_count].end = end;
++rthc_count;
mdbx_trace("<< key 0x%x, rthc_count %u, rthc_limit %u", *key, rthc_count,
rthc_limit);
mdbx_trace("<< key %zu, rthc_count %u, rthc_limit %u", (size_t)*key,
rthc_count, rthc_limit);
mdbx_rthc_unlock();
return MDBX_SUCCESS;
@ -587,8 +598,8 @@ bailout:
__cold void mdbx_rthc_remove(const mdbx_thread_key_t key) {
mdbx_thread_key_delete(key);
mdbx_rthc_lock();
mdbx_trace(">> key 0x%x, rthc_count %u, rthc_limit %u", key, rthc_count,
rthc_limit);
mdbx_trace(">> key %zu, rthc_count %u, rthc_limit %u", (size_t)key,
rthc_count, rthc_limit);
for (unsigned i = 0; i < rthc_count; ++i) {
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,
rthc_limit);
mdbx_trace("<< key %zu, rthc_count %u, rthc_limit %u", (size_t)key,
rthc_count, rthc_limit);
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)
? mdbx_msync(&env->me_dxb_mmap, 0, usedbytes,
flags & MDBX_MAPASYNC)
: mdbx_filesync(env->me_fd, false);
: mdbx_filesync(env->me_fd, MDBX_SYNC_DATA);
if (unlikely(rc != MDBX_SUCCESS))
return rc;
@ -5411,14 +5422,16 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags,
goto fail;
if ((flags & MDBX_MAPASYNC) == 0) {
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))
goto fail;
}
env->me_sync_pending = 0;
}
} 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))
goto fail;
env->me_sync_pending = 0;
@ -5566,7 +5579,7 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags,
if (unlikely(rc != MDBX_SUCCESS))
goto fail;
} else {
rc = mdbx_filesync(env->me_fd, false);
rc = mdbx_filesync(env->me_fd, MDBX_SYNC_DATA | MDBX_SYNC_IODQ);
if (rc != MDBX_SUCCESS)
goto undo;
}
@ -11814,12 +11827,15 @@ int __cold mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd,
mdbx_txn_abort(read_txn);
if (likely(rc == MDBX_SUCCESS))
rc = mdbx_filesync(fd, true);
rc = mdbx_filesync(fd, MDBX_SYNC_DATA | MDBX_SYNC_SIZE);
/* Write actual meta */
if (likely(rc == MDBX_SUCCESS))
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);
return rc;
}
@ -12860,7 +12876,7 @@ int __cold mdbx_setup_debug(int flags, MDBX_debug_func *logger) {
unsigned ret = mdbx_runtime_flags;
mdbx_runtime_flags = flags;
#ifdef __linux__
#if defined(__linux__) || defined(__gnu_linux__)
if (flags & MDBX_DBG_DUMP) {
int core_filter_fd = open("/proc/self/coredump_filter", O_TRUNC | O_RDWR);
if (core_filter_fd >= 0) {
@ -12883,7 +12899,7 @@ int __cold mdbx_setup_debug(int flags, MDBX_debug_func *logger) {
close(core_filter_fd);
}
}
#endif /* __linux__ */
#endif /* Linux */
mdbx_debug_logger = logger;
return ret;

View File

@ -159,9 +159,14 @@ typedef struct _FILE_PROVIDER_EXTERNAL_INFO_V1 {
/* Prototype should match libc runtime. ISO POSIX (2003) & LSB 1.x-3.x */
__nothrow __noreturn void __assert_fail(const char *assertion, const char *file,
unsigned line, const char *function);
#elif (defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \
defined(__DragonFly__))
#elif defined(__APPLE__) || defined(__MACH__)
__nothrow __noreturn void __assert_rtn(const char *function, const char *file,
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,
int line, const char *assertion);
#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)
(void)fcntl(*fd, F_SETFL, fd_flags | O_DIRECT);
#endif /* O_DIRECT */
#if defined(F_NOCACHE)
(void)fcntl(*fd, F_NOCACHE, 1);
#endif /* F_NOCACHE */
}
#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,
uint64_t offset, size_t expected_written) {
#if defined(_WIN32) || defined(_WIN64)
#if defined(_WIN32) || defined(_WIN64) || defined(__APPLE__)
size_t written = 0;
for (int i = 0; i < iovcnt; ++i) {
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
}
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)
(void)filesize_changed;
return FlushFileBuffers(fd) ? MDBX_SUCCESS : GetLastError();
return ((mode_bits & (MDBX_SYNC_DATA | MDBX_SYNC_IODQ)) == 0 ||
FlushFileBuffers(fd))
? MDBX_SUCCESS
: GetLastError();
#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;
do {
#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
* see http://www.spinics.net/lists/linux-ext4/msg33714.html */
if (!filesize_changed) {
if ((mode_bits & MDBX_SYNC_SIZE) == 0) {
if (fdatasync(fd) == 0)
return MDBX_SUCCESS;
} else
#else
(void)filesize_changed;
(void)mode_bits;
#endif
if (fsync(fd) == 0)
return MDBX_SUCCESS;
@ -680,22 +700,6 @@ int mdbx_filesync(mdbx_filehandle_t fd, bool filesize_changed) {
#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) {
#if defined(_WIN32) || defined(_WIN64)
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;
#endif /* Linux */
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
}
@ -1165,7 +1175,10 @@ retry_mapview:;
return rc;
#else
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,
/* LY: in case changing the mapping size calling code
must guarantees the absence of competing threads, and

View File

@ -55,7 +55,7 @@
#include <time.h>
#if !(defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \
defined(__DragonFly__))
defined(__DragonFly__) || defined(__APPLE__) || defined(__MACH__))
#include <malloc.h>
#endif /* xBSD */
@ -522,7 +522,13 @@ int mdbx_thread_create(mdbx_thread_t *thread,
void *arg);
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_ftruncate(mdbx_filehandle_t fd, uint64_t length);
int mdbx_fseek(mdbx_filehandle_t fd, uint64_t pos);

View File

@ -39,6 +39,10 @@
#include <SDKDDKVer.h>
#endif /* WINDOWS */
#ifdef __APPLE__
#define _DARWIN_C_SOURCE
#endif
#include <errno.h>
#include <limits.h>
#include <stdio.h>

View File

@ -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,
int32_t &value, const int32_t minval, const int32_t maxval,
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)

24
test/darwin/LICENSE Normal file
View 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
View 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.

View 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__ */

View 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 */

View File

@ -182,17 +182,19 @@ int main(int argc, char *const argv[]) {
params.datalen_max = datalen_max;
continue;
}
if (config::parse_option(argc, argv, narg, "size-lower", params.size_lower,
mdbx_limits_dbsize_min(params.pagesize),
mdbx_limits_dbsize_max(params.pagesize)))
if (config::parse_option_intptr(argc, argv, narg, "size-lower",
params.size_lower,
mdbx_limits_dbsize_min(params.pagesize),
mdbx_limits_dbsize_max(params.pagesize)))
continue;
if (config::parse_option(argc, argv, narg, "size-upper", params.size_upper,
mdbx_limits_dbsize_min(params.pagesize),
mdbx_limits_dbsize_max(params.pagesize)))
if (config::parse_option_intptr(argc, argv, narg, "size-upper",
params.size_upper,
mdbx_limits_dbsize_min(params.pagesize),
mdbx_limits_dbsize_max(params.pagesize)))
continue;
if (config::parse_option(argc, argv, narg, "size", params.size_now,
mdbx_limits_dbsize_min(params.pagesize),
mdbx_limits_dbsize_max(params.pagesize)))
if (config::parse_option_intptr(argc, argv, narg, "size", params.size_now,
mdbx_limits_dbsize_min(params.pagesize),
mdbx_limits_dbsize_max(params.pagesize)))
continue;
if (config::parse_option(
argc, argv, narg, "shrink-threshold", params.shrink_threshold, 0,

View File

@ -21,6 +21,10 @@
#include <sys/wait.h>
#include <unistd.h>
#ifdef __APPLE__
#include "darwin/pthread_barrier.c"
#endif
struct shared_t {
pthread_barrier_t barrier;
pthread_mutex_t mutex;

View File

@ -53,11 +53,26 @@ bool testcase_ttl::run() {
*/
/* LY: для параметризации используем подходящие параметры, которые не имеют
* здесь смысла в первоначальном значении */
const unsigned window_max =
(config.params.batch_read > 999) ? config.params.batch_read : 1000;
const unsigned count_max =
(config.params.batch_write > 999) ? config.params.batch_write : 1000;
* здесь смысла в первоначальном значении. */
const unsigned window_max_lower =
#ifdef __APPLE__
333;
#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_write` value %u for count_max", count_max);

View File

@ -17,6 +17,9 @@
#if defined(HAVE_IEEE754_H) || __has_include(<ieee754.h>)
#include <ieee754.h>
#endif
#if defined(__APPLE__) || defined(__MACH__)
#include <mach/mach_time.h>
#endif /* defined(__APPLE__) || defined(__MACH__) */
std::string format(const char *fmt, ...) {
va_list ap, ones;

View File

@ -247,18 +247,20 @@ struct simple_checksum {
simple_checksum() : value(0) {}
void push(uint32_t data) {
void push(const uint32_t &data) {
value += data * UINT64_C(9386433910765580089) + 1;
value ^= value >> 41;
value *= UINT64_C(0xBD9CACC22C6E9571);
}
void push(uint64_t data) {
void push(const uint64_t &data) {
push((uint32_t)data);
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) {
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(unsigned salt, const MDBX_val &val) {
push(val.iov_len);
push(unsigned(val.iov_len));
push(salt);
push(val.iov_base, val.iov_len);
}