summaryrefslogtreecommitdiff
path: root/libs/libmdbx/src/test/osal-unix.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libmdbx/src/test/osal-unix.cc')
-rw-r--r--libs/libmdbx/src/test/osal-unix.cc537
1 files changed, 0 insertions, 537 deletions
diff --git a/libs/libmdbx/src/test/osal-unix.cc b/libs/libmdbx/src/test/osal-unix.cc
deleted file mode 100644
index a85ce32a11..0000000000
--- a/libs/libmdbx/src/test/osal-unix.cc
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Copyright 2017-2020 Leonid Yuriev <leo@yuriev.ru>
- * and other libmdbx authors: please see AUTHORS file.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "test.h"
-
-#if !(defined(_WIN32) || defined(_WIN64))
-
-#include <pthread.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <atomic>
-
-#ifndef MDBX_LOCKING
-#error "Opps, MDBX_LOCKING is undefined!"
-#endif
-
-#if defined(__APPLE__) && (MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
- MDBX_LOCKING == MDBX_LOCKING_POSIX2008)
-#include "darwin/pthread_barrier.c"
-#endif /* __APPLE__ && MDBX_LOCKING >= MDBX_LOCKING_POSIX2001 */
-
-#if MDBX_LOCKING == MDBX_LOCKING_SYSV
-#include <sys/ipc.h>
-#include <sys/sem.h>
-#endif /* MDBX_LOCKING == MDBX_LOCKING_SYSV */
-
-#if MDBX_LOCKING == MDBX_LOCKING_POSIX1988
-#include <semaphore.h>
-
-#if __cplusplus >= 201103L
-#include <atomic>
-static __inline __maybe_unused int atomic_decrement(std::atomic_int *p) {
- return std::atomic_fetch_sub(p, 1) - 1;
-}
-#else
-static __inline __maybe_unused int atomic_decrement(volatile int *p) {
-#if defined(__GNUC__) || defined(__clang__)
- return __sync_sub_and_fetch(p, 1);
-#elif defined(_MSC_VER)
- STATIC_ASSERT(sizeof(volatile long) == sizeof(volatile int));
- return _InterlockedDecrement((volatile long *)p);
-#elif defined(__APPLE__)
- return OSAtomicDecrement32Barrier((volatile int *)p);
-#else
-#error FIXME: Unsupported compiler
-#endif
-}
-#endif /* C++11 */
-#endif /* MDBX_LOCKING == MDBX_LOCKING_POSIX1988 */
-
-#if MDBX_LOCKING == MDBX_LOCKING_SYSV
-static int ipc;
-static pid_t ipc_overlord_pid;
-static void ipc_remove(void) {
- if (ipc_overlord_pid == getpid())
- semctl(ipc, 0, IPC_RMID, nullptr);
-}
-
-#else
-struct shared_t {
-#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
- MDBX_LOCKING == MDBX_LOCKING_POSIX2008
- pthread_barrier_t barrier;
- pthread_mutex_t mutex;
- size_t count;
- pthread_cond_t events[1];
-#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
- struct {
-#if __cplusplus >= 201103L
- std::atomic_int countdown;
-#else
- volatile int countdown;
-#endif /* C++11 */
- sem_t sema;
- } barrier;
- size_t count;
- sem_t events[1];
-#else
-#error "FIXME"
-#endif /* MDBX_LOCKING */
-};
-static shared_t *shared;
-#endif /* MDBX_LOCKING != MDBX_LOCKING_SYSV */
-
-void osal_wait4barrier(void) {
-#if MDBX_LOCKING == MDBX_LOCKING_SYSV
- struct sembuf op;
- op.sem_num = 0;
- op.sem_op = -1;
- op.sem_flg = IPC_NOWAIT;
- if (semop(ipc, &op, 1))
- failure_perror("semop(dec)", errno);
- op.sem_op = 0;
- op.sem_flg = 0;
- if (semop(ipc, &op, 1))
- failure_perror("semop(wait)", errno);
-#elif MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
- MDBX_LOCKING == MDBX_LOCKING_POSIX2008
- assert(shared != nullptr && shared != MAP_FAILED);
- int err = pthread_barrier_wait(&shared->barrier);
- if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
- failure_perror("pthread_barrier_wait(shared)", err);
-#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
- assert(shared != nullptr && shared != MAP_FAILED);
- int err = (atomic_decrement(&shared->barrier.countdown) > 0 &&
- sem_wait(&shared->barrier.sema))
- ? errno
- : 0;
- if (err != 0)
- failure_perror("sem_wait(shared)", err);
- if (sem_post(&shared->barrier.sema))
- failure_perror("sem_post(shared)", errno);
-#else
-#error "FIXME"
-#endif /* MDBX_LOCKING */
-}
-
-void osal_setup(const std::vector<actor_config> &actors) {
-#if MDBX_LOCKING == MDBX_LOCKING_SYSV
- if (ipc_overlord_pid)
- failure("ipc already created by %ld pid", (long)ipc_overlord_pid);
- ipc_overlord_pid = getpid();
-#ifndef SEM_A
-#define SEM_A S_IRUSR
-#endif
-#ifndef SEM_R
-#define SEM_R S_IWUSR
-#endif
- ipc = semget(IPC_PRIVATE, actors.size() + 2, IPC_CREAT | SEM_A | SEM_R);
- if (ipc < 0)
- failure_perror("semget(IPC_PRIVATE, shared_sems)", errno);
- if (atexit(ipc_remove))
- failure_perror("atexit(ipc_remove)", errno);
- if (semctl(ipc, 0, SETVAL, (int)(actors.size() + 1)))
- failure_perror("semctl(SETVAL.0, shared_sems)", errno);
- for (size_t i = 1; i < actors.size() + 2; ++i)
- if (semctl(ipc, i, SETVAL, 1))
- failure_perror("semctl(SETVAL.N, shared_sems)", errno);
-#else
- assert(shared == nullptr);
- shared = (shared_t *)mmap(
- nullptr, sizeof(shared_t) + actors.size() * sizeof(shared->events[0]),
- PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_ANONYMOUS
-#ifdef MAP_HASSEMAPHORE
- | MAP_HASSEMAPHORE
-#endif
- ,
- -1, 0);
- if (MAP_FAILED == (void *)shared)
- failure_perror("mmap(shared_conds)", errno);
-
- shared->count = actors.size() + 1;
-
-#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
- MDBX_LOCKING == MDBX_LOCKING_POSIX2008
- pthread_barrierattr_t barrierattr;
- int err = pthread_barrierattr_init(&barrierattr);
- if (err)
- failure_perror("pthread_barrierattr_init()", err);
- err = pthread_barrierattr_setpshared(&barrierattr, PTHREAD_PROCESS_SHARED);
- if (err)
- failure_perror("pthread_barrierattr_setpshared()", err);
-
- err = pthread_barrier_init(&shared->barrier, &barrierattr, shared->count);
- if (err)
- failure_perror("pthread_barrier_init(shared)", err);
- pthread_barrierattr_destroy(&barrierattr);
-
- pthread_mutexattr_t mutexattr;
- err = pthread_mutexattr_init(&mutexattr);
- if (err)
- failure_perror("pthread_mutexattr_init()", err);
- err = pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
- if (err)
- failure_perror("pthread_mutexattr_setpshared()", err);
-
- pthread_condattr_t condattr;
- err = pthread_condattr_init(&condattr);
- if (err)
- failure_perror("pthread_condattr_init()", err);
- err = pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED);
- if (err)
- failure_perror("pthread_condattr_setpshared()", err);
-
- err = pthread_mutex_init(&shared->mutex, &mutexattr);
- if (err)
- failure_perror("pthread_mutex_init(shared)", err);
-
- for (size_t i = 0; i < shared->count; ++i) {
- pthread_cond_t *event = &shared->events[i];
- err = pthread_cond_init(event, &condattr);
- if (err)
- failure_perror("pthread_cond_init(shared)", err);
- log_trace("osal_setup: event(shared pthread_cond) %" PRIuPTR " -> %p", i,
- __Wpedantic_format_voidptr(event));
- }
- pthread_condattr_destroy(&condattr);
- pthread_mutexattr_destroy(&mutexattr);
-#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
- shared->barrier.countdown = shared->count;
- if (sem_init(&shared->barrier.sema, true, 1))
- failure_perror("sem_init(shared.barrier)", errno);
- for (size_t i = 0; i < shared->count; ++i) {
- sem_t *event = &shared->events[i];
- if (sem_init(event, true, 0))
- failure_perror("sem_init(shared.event)", errno);
- log_trace("osal_setup: event(shared sem_init) %" PRIuPTR " -> %p", i,
- __Wpedantic_format_voidptr(event));
- }
-#else
-#error "FIXME"
-#endif /* MDBX_LOCKING */
-#endif /* MDBX_LOCKING != MDBX_LOCKING_SYSV */
-}
-
-void osal_broadcast(unsigned id) {
- log_trace("osal_broadcast: event %u", id);
-#if MDBX_LOCKING == MDBX_LOCKING_SYSV
- if (semctl(ipc, id + 1, SETVAL, 0))
- failure_perror("semctl(SETVAL)", errno);
-#else
- assert(shared != nullptr && shared != MAP_FAILED);
- if (id >= shared->count)
- failure("osal_broadcast: id > limit");
-#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
- MDBX_LOCKING == MDBX_LOCKING_POSIX2008
- int err = pthread_cond_broadcast(shared->events + id);
- if (err)
- failure_perror("pthread_cond_broadcast(shared)", err);
-#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
- if (sem_post(shared->events + id))
- failure_perror("sem_post(shared)", errno);
-#else
-#error "FIXME"
-#endif /* MDBX_LOCKING */
-#endif /* MDBX_LOCKING != MDBX_LOCKING_SYSV */
-}
-
-int osal_waitfor(unsigned id) {
- log_trace("osal_waitfor: event %u", id);
-#if MDBX_LOCKING == MDBX_LOCKING_SYSV
- struct sembuf op;
- memset(&op, 0, sizeof(op));
- op.sem_num = (short)(id + 1);
- int rc = semop(ipc, &op, 1) ? errno : MDBX_SUCCESS;
-#else
- assert(shared != nullptr && shared != MAP_FAILED);
- if (id >= shared->count)
- failure("osal_waitfor: id > limit");
-
-#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
- MDBX_LOCKING == MDBX_LOCKING_POSIX2008
- int rc = pthread_mutex_lock(&shared->mutex);
- if (rc != 0)
- failure_perror("pthread_mutex_lock(shared)", rc);
-
- rc = pthread_cond_wait(shared->events + id, &shared->mutex);
- if (rc && rc != EINTR)
- failure_perror("pthread_cond_wait(shared)", rc);
-
- rc = pthread_mutex_unlock(&shared->mutex);
- if (rc != 0)
- failure_perror("pthread_mutex_unlock(shared)", rc);
-#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
- int rc = sem_wait(shared->events + id) ? errno : 0;
- if (rc == 0 && sem_post(shared->events + id))
- failure_perror("sem_post(shared)", errno);
-#else
-#error "FIXME"
-#endif /* MDBX_LOCKING */
-#endif /* MDBX_LOCKING != MDBX_LOCKING_SYSV */
-
- return (rc == 0) ? true : false;
-}
-
-//-----------------------------------------------------------------------------
-
-const std::string
-actor_config::osal_serialize(simple_checksum &checksum) const {
- (void)checksum;
- /* not used in workload, but just for testing */
- return "unix.fork";
-}
-
-bool actor_config::osal_deserialize(const char *str, const char *end,
- simple_checksum &checksum) {
- (void)checksum;
- /* not used in workload, but just for testing */
- return strncmp(str, "unix.fork", 9) == 0 && str + 9 == end;
-}
-
-//-----------------------------------------------------------------------------
-
-static pid_t overlord_pid;
-
-static std::atomic<int> sigusr1_head, sigusr2_head;
-static void handler_SIGUSR(int signum) {
- switch (signum) {
- case SIGUSR1:
- ++sigusr1_head;
- return;
- case SIGUSR2:
- ++sigusr2_head;
- return;
- default:
- abort();
- }
-}
-
-bool osal_progress_push(bool active) {
- if (overlord_pid) {
- if (kill(overlord_pid, active ? SIGUSR1 : SIGUSR2))
- failure_perror("osal_progress_push: kill(overload)", errno);
- return true;
- }
-
- return false;
-}
-
-//-----------------------------------------------------------------------------
-
-static std::unordered_map<pid_t, actor_status> childs;
-
-static std::atomic<int> sigalarm_head;
-static void handler_SIGCHLD(int signum) {
- if (signum == SIGALRM)
- ++sigalarm_head;
-}
-
-mdbx_pid_t osal_getpid(void) { return getpid(); }
-
-int osal_delay(unsigned seconds) { return sleep(seconds) ? errno : 0; }
-
-int osal_actor_start(const actor_config &config, mdbx_pid_t &pid) {
- if (childs.empty()) {
- struct sigaction act;
- memset(&act, 0, sizeof(act));
- act.sa_handler = handler_SIGCHLD;
- sigaction(SIGCHLD, &act, nullptr);
- sigaction(SIGALRM, &act, nullptr);
- act.sa_handler = handler_SIGUSR;
- sigaction(SIGUSR1, &act, nullptr);
- sigaction(SIGUSR2, &act, nullptr);
-
- sigset_t mask;
- sigemptyset(&mask);
- sigaddset(&mask, SIGCHLD);
- sigaddset(&mask, SIGUSR1);
- sigaddset(&mask, SIGUSR2);
- sigprocmask(SIG_UNBLOCK, &mask, nullptr);
- }
-
- pid = fork();
-
- if (pid == 0) {
- overlord_pid = getppid();
- const bool result = test_execute(config);
- exit(result ? EXIT_SUCCESS : EXIT_FAILURE);
- }
-
- if (pid < 0)
- return errno;
-
- log_trace("osal_actor_start: fork pid %ld for %u", (long)pid,
- config.actor_id);
- childs[pid] = as_running;
- return 0;
-}
-
-actor_status osal_actor_info(const mdbx_pid_t pid) { return childs.at(pid); }
-
-void osal_killall_actors(void) {
- for (auto &pair : childs) {
- kill(pair.first, SIGKILL);
- pair.second = as_killed;
- }
-}
-
-int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) {
- static sig_atomic_t sigalarm_tail;
- alarm(0) /* cancel prev timeout */;
- sigalarm_tail = sigalarm_head /* reset timeout flag */;
-
- int options = WNOHANG;
- if (timeout) {
- alarm((timeout > INT_MAX) ? INT_MAX : timeout);
- options = 0;
- }
-
-#ifdef WUNTRACED
- options |= WUNTRACED;
-#endif
-#ifdef WCONTINUED
- options |= WCONTINUED;
-#endif
-
- while (sigalarm_tail == sigalarm_head) {
- int status;
- pid = waitpid(0, &status, options);
-
- if (pid > 0) {
- if (WIFEXITED(status))
- childs[pid] =
- (WEXITSTATUS(status) == EXIT_SUCCESS) ? as_successful : as_failed;
- else if (WCOREDUMP(status))
- childs[pid] = as_coredump;
- else if (WIFSIGNALED(status))
- childs[pid] = as_killed;
- else if (WIFSTOPPED(status))
- childs[pid] = as_debugging;
- else if (WIFCONTINUED(status))
- childs[pid] = as_running;
- else {
- assert(false);
- }
- return 0;
- }
-
- static sig_atomic_t sigusr1_tail, sigusr2_tail;
- if (sigusr1_tail != sigusr1_head) {
- sigusr1_tail = sigusr1_head;
- logging::progress_canary(true);
- if (pid < 0 && errno == EINTR)
- continue;
- }
- if (sigusr2_tail != sigusr2_head) {
- sigusr2_tail = sigusr2_head;
- logging::progress_canary(false);
- if (pid < 0 && errno == EINTR)
- continue;
- }
-
- if (pid == 0)
- break;
-
- int err = errno;
- if (err != EINTR)
- return err;
- }
- return 0 /* timeout */;
-}
-
-void osal_yield(void) {
- if (sched_yield())
- failure_perror("sched_yield()", errno);
-}
-
-void osal_udelay(unsigned us) {
- chrono::time until, now = chrono::now_motonic();
- until.fixedpoint = now.fixedpoint + chrono::from_us(us).fixedpoint;
- struct timespec ts;
-
- static unsigned threshold_us;
- if (threshold_us == 0) {
-#if defined(_POSIX_CPUTIME) && _POSIX_CPUTIME > -1 && \
- defined(CLOCK_PROCESS_CPUTIME_ID)
- if (clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts)) {
- int rc = errno;
- log_warning("clock_getres(CLOCK_PROCESS_CPUTIME_ID), failed errno %d",
- rc);
- }
-#endif /* CLOCK_PROCESS_CPUTIME_ID */
- if (threshold_us == 0 && clock_getres(CLOCK_MONOTONIC, &ts)) {
- int rc = errno;
- failure_perror("clock_getres(CLOCK_MONOTONIC)", rc);
- }
- chrono::time threshold = chrono::from_timespec(ts);
- assert(threshold.seconds() == 0);
-
- threshold_us = chrono::fractional2us(threshold.fractional);
- if (threshold_us < 1000)
- threshold_us = 1000;
- }
-
- ts.tv_sec = ts.tv_nsec = 0;
- if (us > threshold_us) {
- ts.tv_sec = us / 1000000u;
- ts.tv_nsec = (us % 1000000u) * 1000u;
- }
-
- do {
- if (us > threshold_us) {
- if (nanosleep(&ts, &ts)) {
- int rc = errno;
- /* if (rc == EINTR) { ... } ? */
- failure_perror("usleep()", rc);
- }
- us = ts.tv_sec * 1000000u + ts.tv_nsec / 1000u;
- }
- cpu_relax();
-
- now = chrono::now_motonic();
- } while (until.fixedpoint > now.fixedpoint);
-}
-
-bool osal_istty(int fd) { return isatty(fd) == 1; }
-
-std::string osal_tempdir(void) {
- const char *tempdir = getenv("TMPDIR");
- if (!tempdir)
- tempdir = getenv("TMP");
- if (!tempdir)
- tempdir = getenv("TEMPDIR");
- if (!tempdir)
- tempdir = getenv("TEMP");
- if (tempdir && *tempdir) {
- std::string dir(tempdir);
- if (dir.back() != '/')
- dir.append("/");
- return dir;
- }
- if (access("/dev/shm/", R_OK | W_OK | X_OK) == 0)
- return "/dev/shm/";
- return "";
-}
-
-int osal_removefile(const std::string &pathname) {
- return unlink(pathname.c_str()) ? errno : MDBX_SUCCESS;
-}
-
-#endif /* !Windows */