mdbxmou 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +32 -0
- package/.github/workflows/publish.yml +27 -0
- package/.gitmodules +3 -0
- package/CMakeLists.txt +53 -0
- package/LICENSE +201 -0
- package/README.md +639 -0
- package/build.js +11 -0
- package/deps/libmdbx/.clang-format +3 -0
- package/deps/libmdbx/.cmake-format.yaml +3 -0
- package/deps/libmdbx/.le.ini +40 -0
- package/deps/libmdbx/CMakeLists.txt +1269 -0
- package/deps/libmdbx/COPYRIGHT +159 -0
- package/deps/libmdbx/ChangeLog.md +2786 -0
- package/deps/libmdbx/GNUmakefile +950 -0
- package/deps/libmdbx/LICENSE +177 -0
- package/deps/libmdbx/Makefile +16 -0
- package/deps/libmdbx/NOTICE +39 -0
- package/deps/libmdbx/README.md +863 -0
- package/deps/libmdbx/TODO.md +43 -0
- package/deps/libmdbx/cmake/compiler.cmake +1221 -0
- package/deps/libmdbx/cmake/profile.cmake +58 -0
- package/deps/libmdbx/cmake/utils.cmake +524 -0
- package/deps/libmdbx/conanfile.py +323 -0
- package/deps/libmdbx/docs/Doxyfile.in +2734 -0
- package/deps/libmdbx/docs/_preface.md +47 -0
- package/deps/libmdbx/docs/_restrictions.md +248 -0
- package/deps/libmdbx/docs/_starting.md +245 -0
- package/deps/libmdbx/docs/_toc.md +34 -0
- package/deps/libmdbx/docs/header.html +96 -0
- package/deps/libmdbx/example/CMakeLists.txt +6 -0
- package/deps/libmdbx/example/README.md +1 -0
- package/deps/libmdbx/example/example-mdbx.c +154 -0
- package/deps/libmdbx/example/sample-bdb.txt +77 -0
- package/deps/libmdbx/mdbx.h +6655 -0
- package/deps/libmdbx/mdbx.h++ +6428 -0
- package/deps/libmdbx/packages/buildroot/0001-package-libmdbx-new-package-library-database.patch +173 -0
- package/deps/libmdbx/src/alloy.c +54 -0
- package/deps/libmdbx/src/api-cold.c +543 -0
- package/deps/libmdbx/src/api-copy.c +912 -0
- package/deps/libmdbx/src/api-cursor.c +754 -0
- package/deps/libmdbx/src/api-dbi.c +315 -0
- package/deps/libmdbx/src/api-env.c +1434 -0
- package/deps/libmdbx/src/api-extra.c +165 -0
- package/deps/libmdbx/src/api-key-transform.c +197 -0
- package/deps/libmdbx/src/api-misc.c +286 -0
- package/deps/libmdbx/src/api-opts.c +575 -0
- package/deps/libmdbx/src/api-range-estimate.c +365 -0
- package/deps/libmdbx/src/api-txn-data.c +454 -0
- package/deps/libmdbx/src/api-txn.c +921 -0
- package/deps/libmdbx/src/atomics-ops.h +364 -0
- package/deps/libmdbx/src/atomics-types.h +97 -0
- package/deps/libmdbx/src/audit.c +109 -0
- package/deps/libmdbx/src/bits.md +34 -0
- package/deps/libmdbx/src/chk.c +1796 -0
- package/deps/libmdbx/src/cogs.c +309 -0
- package/deps/libmdbx/src/cogs.h +506 -0
- package/deps/libmdbx/src/coherency.c +170 -0
- package/deps/libmdbx/src/config.h.in +88 -0
- package/deps/libmdbx/src/cursor.c +2396 -0
- package/deps/libmdbx/src/cursor.h +391 -0
- package/deps/libmdbx/src/dbi.c +717 -0
- package/deps/libmdbx/src/dbi.h +142 -0
- package/deps/libmdbx/src/debug_begin.h +36 -0
- package/deps/libmdbx/src/debug_end.h +15 -0
- package/deps/libmdbx/src/dpl.c +486 -0
- package/deps/libmdbx/src/dpl.h +134 -0
- package/deps/libmdbx/src/dxb.c +1335 -0
- package/deps/libmdbx/src/env.c +607 -0
- package/deps/libmdbx/src/essentials.h +125 -0
- package/deps/libmdbx/src/gc-get.c +1345 -0
- package/deps/libmdbx/src/gc-put.c +970 -0
- package/deps/libmdbx/src/gc.h +40 -0
- package/deps/libmdbx/src/global.c +474 -0
- package/deps/libmdbx/src/internals.h +585 -0
- package/deps/libmdbx/src/layout-dxb.h +288 -0
- package/deps/libmdbx/src/layout-lck.h +289 -0
- package/deps/libmdbx/src/lck-posix.c +859 -0
- package/deps/libmdbx/src/lck-windows.c +607 -0
- package/deps/libmdbx/src/lck.c +174 -0
- package/deps/libmdbx/src/lck.h +110 -0
- package/deps/libmdbx/src/logging_and_debug.c +250 -0
- package/deps/libmdbx/src/logging_and_debug.h +159 -0
- package/deps/libmdbx/src/man1/mdbx_chk.1 +106 -0
- package/deps/libmdbx/src/man1/mdbx_copy.1 +95 -0
- package/deps/libmdbx/src/man1/mdbx_drop.1 +48 -0
- package/deps/libmdbx/src/man1/mdbx_dump.1 +101 -0
- package/deps/libmdbx/src/man1/mdbx_load.1 +105 -0
- package/deps/libmdbx/src/man1/mdbx_stat.1 +86 -0
- package/deps/libmdbx/src/mdbx.c++ +1837 -0
- package/deps/libmdbx/src/meta.c +656 -0
- package/deps/libmdbx/src/meta.h +168 -0
- package/deps/libmdbx/src/mvcc-readers.c +414 -0
- package/deps/libmdbx/src/node.c +365 -0
- package/deps/libmdbx/src/node.h +102 -0
- package/deps/libmdbx/src/ntdll.def +1246 -0
- package/deps/libmdbx/src/options.h +534 -0
- package/deps/libmdbx/src/osal.c +3485 -0
- package/deps/libmdbx/src/osal.h +587 -0
- package/deps/libmdbx/src/page-get.c +483 -0
- package/deps/libmdbx/src/page-iov.c +185 -0
- package/deps/libmdbx/src/page-iov.h +34 -0
- package/deps/libmdbx/src/page-ops.c +744 -0
- package/deps/libmdbx/src/page-ops.h +142 -0
- package/deps/libmdbx/src/pnl.c +236 -0
- package/deps/libmdbx/src/pnl.h +146 -0
- package/deps/libmdbx/src/preface.h +990 -0
- package/deps/libmdbx/src/proto.h +105 -0
- package/deps/libmdbx/src/refund.c +212 -0
- package/deps/libmdbx/src/sort.h +484 -0
- package/deps/libmdbx/src/spill.c +431 -0
- package/deps/libmdbx/src/spill.h +74 -0
- package/deps/libmdbx/src/table.c +107 -0
- package/deps/libmdbx/src/tls.c +551 -0
- package/deps/libmdbx/src/tls.h +43 -0
- package/deps/libmdbx/src/tools/chk.c +673 -0
- package/deps/libmdbx/src/tools/copy.c +166 -0
- package/deps/libmdbx/src/tools/drop.c +199 -0
- package/deps/libmdbx/src/tools/dump.c +515 -0
- package/deps/libmdbx/src/tools/load.c +831 -0
- package/deps/libmdbx/src/tools/stat.c +516 -0
- package/deps/libmdbx/src/tools/wingetopt.c +87 -0
- package/deps/libmdbx/src/tools/wingetopt.h +30 -0
- package/deps/libmdbx/src/tree-ops.c +1554 -0
- package/deps/libmdbx/src/tree-search.c +140 -0
- package/deps/libmdbx/src/txl.c +99 -0
- package/deps/libmdbx/src/txl.h +26 -0
- package/deps/libmdbx/src/txn.c +1083 -0
- package/deps/libmdbx/src/unaligned.h +205 -0
- package/deps/libmdbx/src/utils.c +32 -0
- package/deps/libmdbx/src/utils.h +76 -0
- package/deps/libmdbx/src/version.c.in +44 -0
- package/deps/libmdbx/src/walk.c +290 -0
- package/deps/libmdbx/src/walk.h +20 -0
- package/deps/libmdbx/src/windows-import.c +152 -0
- package/deps/libmdbx/src/windows-import.h +128 -0
- package/deps/libmdbx/test/CMakeLists.txt +317 -0
- package/deps/libmdbx/test/append.c++ +237 -0
- package/deps/libmdbx/test/base.h++ +92 -0
- package/deps/libmdbx/test/battery-tmux.sh +64 -0
- package/deps/libmdbx/test/cases.c++ +118 -0
- package/deps/libmdbx/test/chrono.c++ +134 -0
- package/deps/libmdbx/test/chrono.h++ +85 -0
- package/deps/libmdbx/test/config.c++ +643 -0
- package/deps/libmdbx/test/config.h++ +334 -0
- package/deps/libmdbx/test/copy.c++ +62 -0
- package/deps/libmdbx/test/dead.c++ +39 -0
- package/deps/libmdbx/test/dump-load.sh +40 -0
- package/deps/libmdbx/test/extra/crunched_delete.c++ +409 -0
- package/deps/libmdbx/test/extra/cursor_closing.c++ +410 -0
- package/deps/libmdbx/test/extra/dbi.c++ +229 -0
- package/deps/libmdbx/test/extra/doubtless_positioning.c++ +253 -0
- package/deps/libmdbx/test/extra/dupfix_addodd.c +94 -0
- package/deps/libmdbx/test/extra/dupfix_multiple.c++ +311 -0
- package/deps/libmdbx/test/extra/early_close_dbi.c++ +137 -0
- package/deps/libmdbx/test/extra/hex_base64_base58.c++ +118 -0
- package/deps/libmdbx/test/extra/maindb_ordinal.c++ +61 -0
- package/deps/libmdbx/test/extra/open.c++ +96 -0
- package/deps/libmdbx/test/extra/pcrf/README.md +2 -0
- package/deps/libmdbx/test/extra/pcrf/pcrf_test.c +380 -0
- package/deps/libmdbx/test/extra/probe.c++ +10 -0
- package/deps/libmdbx/test/extra/txn.c++ +407 -0
- package/deps/libmdbx/test/extra/upsert_alldups.c +193 -0
- package/deps/libmdbx/test/fork.c++ +263 -0
- package/deps/libmdbx/test/hill.c++ +447 -0
- package/deps/libmdbx/test/jitter.c++ +197 -0
- package/deps/libmdbx/test/keygen.c++ +393 -0
- package/deps/libmdbx/test/keygen.h++ +130 -0
- package/deps/libmdbx/test/log.c++ +358 -0
- package/deps/libmdbx/test/log.h++ +91 -0
- package/deps/libmdbx/test/main.c++ +706 -0
- package/deps/libmdbx/test/nested.c++ +318 -0
- package/deps/libmdbx/test/osal-unix.c++ +647 -0
- package/deps/libmdbx/test/osal-windows.c++ +440 -0
- package/deps/libmdbx/test/osal.h++ +41 -0
- package/deps/libmdbx/test/stochastic.sh +690 -0
- package/deps/libmdbx/test/stub/LICENSE +24 -0
- package/deps/libmdbx/test/stub/README.md +8 -0
- package/deps/libmdbx/test/stub/pthread_barrier.c +104 -0
- package/deps/libmdbx/test/stub/pthread_barrier.h +77 -0
- package/deps/libmdbx/test/test.c++ +1551 -0
- package/deps/libmdbx/test/test.h++ +298 -0
- package/deps/libmdbx/test/tmux.conf +3 -0
- package/deps/libmdbx/test/try.c++ +30 -0
- package/deps/libmdbx/test/ttl.c++ +240 -0
- package/deps/libmdbx/test/utils.c++ +203 -0
- package/deps/libmdbx/test/utils.h++ +326 -0
- package/deps/libmdbx/test/valgrind_suppress.txt +536 -0
- package/lib/mdbx_evn_async.js +211 -0
- package/lib/mdbx_worker.js +195 -0
- package/lib/nativemou.js +6 -0
- package/package.json +38 -0
- package/src/async/envmou_close.cpp +34 -0
- package/src/async/envmou_close.hpp +32 -0
- package/src/async/envmou_copy_to.cpp +29 -0
- package/src/async/envmou_copy_to.hpp +38 -0
- package/src/async/envmou_keys.cpp +201 -0
- package/src/async/envmou_keys.hpp +50 -0
- package/src/async/envmou_open.cpp +38 -0
- package/src/async/envmou_open.hpp +33 -0
- package/src/async/envmou_query.cpp +167 -0
- package/src/async/envmou_query.hpp +53 -0
- package/src/dbimou.cpp +522 -0
- package/src/dbimou.hpp +82 -0
- package/src/env_arg0.hpp +24 -0
- package/src/envmou.cpp +445 -0
- package/src/envmou.hpp +116 -0
- package/src/modulemou.cpp +113 -0
- package/src/querymou.cpp +177 -0
- package/src/querymou.hpp +93 -0
- package/src/txnmou.cpp +254 -0
- package/src/txnmou.hpp +122 -0
- package/src/typemou.hpp +239 -0
- package/src/valuemou.hpp +194 -0
- package/test/async.js +67 -0
- package/test/e3.js +38 -0
- package/test/e4.js +89 -0
- package/test/e5.js +162 -0
- package/test/test-batch-ops.js +243 -0
- package/test/test-cursor-mode.js +84 -0
- package/test/test-multi-mode.js +87 -0
|
@@ -0,0 +1,647 @@
|
|
|
1
|
+
/// \author Леонид Юрьев aka Leonid Yuriev <leo@yuriev.ru> \date 2015-2025
|
|
2
|
+
/// \copyright SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
#include "test.h++"
|
|
5
|
+
|
|
6
|
+
#if !(defined(_WIN32) || defined(_WIN64))
|
|
7
|
+
|
|
8
|
+
#include <atomic>
|
|
9
|
+
#include <pthread.h>
|
|
10
|
+
#include <signal.h>
|
|
11
|
+
#include <sys/mman.h>
|
|
12
|
+
#include <sys/types.h>
|
|
13
|
+
#include <sys/wait.h>
|
|
14
|
+
#include <unistd.h>
|
|
15
|
+
|
|
16
|
+
#include <atomic>
|
|
17
|
+
|
|
18
|
+
#ifndef MDBX_LOCKING
|
|
19
|
+
#error "Oops, MDBX_LOCKING is undefined!"
|
|
20
|
+
#endif
|
|
21
|
+
|
|
22
|
+
#if defined(__APPLE__) && (MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008)
|
|
23
|
+
#include "stub/pthread_barrier.c"
|
|
24
|
+
#endif /* __APPLE__ && MDBX_LOCKING >= MDBX_LOCKING_POSIX2001 */
|
|
25
|
+
|
|
26
|
+
#if defined(__ANDROID_API__) && __ANDROID_API__ < 24 && \
|
|
27
|
+
(MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008)
|
|
28
|
+
#include "stub/pthread_barrier.c"
|
|
29
|
+
#endif /* __ANDROID_API__ < 24 && MDBX_LOCKING >= MDBX_LOCKING_POSIX2001 */
|
|
30
|
+
|
|
31
|
+
#if MDBX_LOCKING == MDBX_LOCKING_SYSV
|
|
32
|
+
#include <sys/ipc.h>
|
|
33
|
+
#include <sys/sem.h>
|
|
34
|
+
#endif /* MDBX_LOCKING == MDBX_LOCKING_SYSV */
|
|
35
|
+
|
|
36
|
+
#if MDBX_LOCKING == MDBX_LOCKING_POSIX1988
|
|
37
|
+
#include <semaphore.h>
|
|
38
|
+
|
|
39
|
+
#if __cplusplus >= 201103L
|
|
40
|
+
#include <atomic>
|
|
41
|
+
MDBX_MAYBE_UNUSED static inline int atomic_decrement(std::atomic_int *p) { return std::atomic_fetch_sub(p, 1) - 1; }
|
|
42
|
+
#else
|
|
43
|
+
MDBX_MAYBE_UNUSED static inline int atomic_decrement(volatile int *p) {
|
|
44
|
+
#if defined(__GNUC__) || defined(__clang__)
|
|
45
|
+
return __sync_sub_and_fetch(p, 1);
|
|
46
|
+
#elif defined(_MSC_VER)
|
|
47
|
+
STATIC_ASSERT(sizeof(volatile long) == sizeof(volatile int));
|
|
48
|
+
return _InterlockedDecrement((volatile long *)p);
|
|
49
|
+
#elif defined(__APPLE__)
|
|
50
|
+
return OSAtomicDecrement32Barrier((volatile int *)p);
|
|
51
|
+
#else
|
|
52
|
+
#error FIXME: Unsupported compiler
|
|
53
|
+
#endif
|
|
54
|
+
}
|
|
55
|
+
#endif /* C++11 */
|
|
56
|
+
#endif /* MDBX_LOCKING == MDBX_LOCKING_POSIX1988 */
|
|
57
|
+
|
|
58
|
+
#if MDBX_LOCKING == MDBX_LOCKING_SYSV
|
|
59
|
+
static int ipc;
|
|
60
|
+
static pid_t ipc_overlord_pid;
|
|
61
|
+
static void ipc_remove(void) {
|
|
62
|
+
if (ipc_overlord_pid == getpid())
|
|
63
|
+
semctl(ipc, 0, IPC_RMID, nullptr);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#else
|
|
67
|
+
struct shared_t {
|
|
68
|
+
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008
|
|
69
|
+
pthread_barrier_t barrier;
|
|
70
|
+
pthread_mutex_t mutex;
|
|
71
|
+
size_t count;
|
|
72
|
+
pthread_cond_t events[1];
|
|
73
|
+
#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
|
|
74
|
+
struct {
|
|
75
|
+
#if __cplusplus >= 201103L
|
|
76
|
+
std::atomic_int countdown;
|
|
77
|
+
#else
|
|
78
|
+
volatile int countdown;
|
|
79
|
+
#endif /* C++11 */
|
|
80
|
+
sem_t sema;
|
|
81
|
+
} barrier;
|
|
82
|
+
size_t count;
|
|
83
|
+
sem_t events[1];
|
|
84
|
+
#else
|
|
85
|
+
#error "FIXME"
|
|
86
|
+
#endif /* MDBX_LOCKING */
|
|
87
|
+
};
|
|
88
|
+
static shared_t *shared;
|
|
89
|
+
#endif /* MDBX_LOCKING != MDBX_LOCKING_SYSV */
|
|
90
|
+
|
|
91
|
+
void osal_wait4barrier(void) {
|
|
92
|
+
#if MDBX_LOCKING == MDBX_LOCKING_SYSV
|
|
93
|
+
struct sembuf op;
|
|
94
|
+
op.sem_num = 0;
|
|
95
|
+
op.sem_op = -1;
|
|
96
|
+
op.sem_flg = IPC_NOWAIT;
|
|
97
|
+
if (semop(ipc, &op, 1))
|
|
98
|
+
failure_perror("semop(dec)", errno);
|
|
99
|
+
op.sem_op = 0;
|
|
100
|
+
op.sem_flg = 0;
|
|
101
|
+
if (semop(ipc, &op, 1))
|
|
102
|
+
failure_perror("semop(wait)", errno);
|
|
103
|
+
#elif MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008
|
|
104
|
+
assert(shared != nullptr && shared != MAP_FAILED);
|
|
105
|
+
int err = pthread_barrier_wait(&shared->barrier);
|
|
106
|
+
if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
|
|
107
|
+
failure_perror("pthread_barrier_wait(shared)", err);
|
|
108
|
+
#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
|
|
109
|
+
assert(shared != nullptr && shared != MAP_FAILED);
|
|
110
|
+
int err = (atomic_decrement(&shared->barrier.countdown) > 0 && sem_wait(&shared->barrier.sema)) ? errno : 0;
|
|
111
|
+
if (err != 0)
|
|
112
|
+
failure_perror("sem_wait(shared)", err);
|
|
113
|
+
if (sem_post(&shared->barrier.sema))
|
|
114
|
+
failure_perror("sem_post(shared)", errno);
|
|
115
|
+
#else
|
|
116
|
+
#error "FIXME"
|
|
117
|
+
#endif /* MDBX_LOCKING */
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
void osal_setup(const std::vector<actor_config> &actors) {
|
|
121
|
+
#if MDBX_LOCKING == MDBX_LOCKING_SYSV
|
|
122
|
+
if (ipc_overlord_pid)
|
|
123
|
+
failure("ipc already created by %ld pid", (long)ipc_overlord_pid);
|
|
124
|
+
ipc_overlord_pid = getpid();
|
|
125
|
+
#ifndef SEM_A
|
|
126
|
+
#define SEM_A S_IRUSR
|
|
127
|
+
#endif
|
|
128
|
+
#ifndef SEM_R
|
|
129
|
+
#define SEM_R S_IWUSR
|
|
130
|
+
#endif
|
|
131
|
+
ipc = semget(IPC_PRIVATE, actors.size() + 2, IPC_CREAT | SEM_A | SEM_R);
|
|
132
|
+
if (ipc < 0)
|
|
133
|
+
failure_perror("semget(IPC_PRIVATE, shared_sems)", errno);
|
|
134
|
+
if (atexit(ipc_remove))
|
|
135
|
+
failure_perror("atexit(ipc_remove)", errno);
|
|
136
|
+
if (semctl(ipc, 0, SETVAL, (int)(actors.size() + 1)))
|
|
137
|
+
failure_perror("semctl(SETVAL.0, shared_sems)", errno);
|
|
138
|
+
for (size_t i = 1; i < actors.size() + 2; ++i)
|
|
139
|
+
if (semctl(ipc, i, SETVAL, 1))
|
|
140
|
+
failure_perror("semctl(SETVAL.N, shared_sems)", errno);
|
|
141
|
+
#else
|
|
142
|
+
assert(shared == nullptr);
|
|
143
|
+
shared =
|
|
144
|
+
(shared_t *)mmap(nullptr, sizeof(shared_t) + actors.size() * sizeof(shared->events[0]), PROT_READ | PROT_WRITE,
|
|
145
|
+
MAP_SHARED | MAP_ANONYMOUS
|
|
146
|
+
#ifdef MAP_HASSEMAPHORE
|
|
147
|
+
| MAP_HASSEMAPHORE
|
|
148
|
+
#endif
|
|
149
|
+
,
|
|
150
|
+
-1, 0);
|
|
151
|
+
if (MAP_FAILED == (void *)shared)
|
|
152
|
+
failure_perror("mmap(shared)", errno);
|
|
153
|
+
|
|
154
|
+
shared->count = actors.size() + 1;
|
|
155
|
+
|
|
156
|
+
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008
|
|
157
|
+
pthread_barrierattr_t barrierattr;
|
|
158
|
+
int err = pthread_barrierattr_init(&barrierattr);
|
|
159
|
+
if (err)
|
|
160
|
+
failure_perror("pthread_barrierattr_init()", err);
|
|
161
|
+
err = pthread_barrierattr_setpshared(&barrierattr, PTHREAD_PROCESS_SHARED);
|
|
162
|
+
if (err)
|
|
163
|
+
failure_perror("pthread_barrierattr_setpshared()", err);
|
|
164
|
+
|
|
165
|
+
err = pthread_barrier_init(&shared->barrier, &barrierattr, unsigned(shared->count));
|
|
166
|
+
if (err)
|
|
167
|
+
failure_perror("pthread_barrier_init(shared)", err);
|
|
168
|
+
pthread_barrierattr_destroy(&barrierattr);
|
|
169
|
+
|
|
170
|
+
pthread_mutexattr_t mutexattr;
|
|
171
|
+
err = pthread_mutexattr_init(&mutexattr);
|
|
172
|
+
if (err)
|
|
173
|
+
failure_perror("pthread_mutexattr_init()", err);
|
|
174
|
+
err = pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
|
|
175
|
+
if (err)
|
|
176
|
+
failure_perror("pthread_mutexattr_setpshared()", err);
|
|
177
|
+
|
|
178
|
+
pthread_condattr_t condattr;
|
|
179
|
+
err = pthread_condattr_init(&condattr);
|
|
180
|
+
if (err)
|
|
181
|
+
failure_perror("pthread_condattr_init()", err);
|
|
182
|
+
err = pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED);
|
|
183
|
+
if (err)
|
|
184
|
+
failure_perror("pthread_condattr_setpshared()", err);
|
|
185
|
+
|
|
186
|
+
err = pthread_mutex_init(&shared->mutex, &mutexattr);
|
|
187
|
+
if (err)
|
|
188
|
+
failure_perror("pthread_mutex_init(shared)", err);
|
|
189
|
+
|
|
190
|
+
for (size_t i = 0; i < shared->count; ++i) {
|
|
191
|
+
pthread_cond_t *event = &shared->events[i];
|
|
192
|
+
err = pthread_cond_init(event, &condattr);
|
|
193
|
+
if (err)
|
|
194
|
+
failure_perror("pthread_cond_init(shared)", err);
|
|
195
|
+
log_trace("osal_setup: event(shared pthread_cond) %" PRIuPTR " -> %p", i, __Wpedantic_format_voidptr(event));
|
|
196
|
+
}
|
|
197
|
+
pthread_condattr_destroy(&condattr);
|
|
198
|
+
pthread_mutexattr_destroy(&mutexattr);
|
|
199
|
+
#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
|
|
200
|
+
shared->barrier.countdown = shared->count;
|
|
201
|
+
if (sem_init(&shared->barrier.sema, true, 1))
|
|
202
|
+
failure_perror("sem_init(shared.barrier)", errno);
|
|
203
|
+
for (size_t i = 0; i < shared->count; ++i) {
|
|
204
|
+
sem_t *event = &shared->events[i];
|
|
205
|
+
if (sem_init(event, true, 0))
|
|
206
|
+
failure_perror("sem_init(shared.event)", errno);
|
|
207
|
+
log_trace("osal_setup: event(shared sem_init) %" PRIuPTR " -> %p", i, __Wpedantic_format_voidptr(event));
|
|
208
|
+
}
|
|
209
|
+
#else
|
|
210
|
+
#error "FIXME"
|
|
211
|
+
#endif /* MDBX_LOCKING */
|
|
212
|
+
#endif /* MDBX_LOCKING != MDBX_LOCKING_SYSV */
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
void osal_broadcast(unsigned id) {
|
|
216
|
+
log_trace("osal_broadcast: event %u", id);
|
|
217
|
+
#if MDBX_LOCKING == MDBX_LOCKING_SYSV
|
|
218
|
+
if (semctl(ipc, id + 1, SETVAL, 0))
|
|
219
|
+
failure_perror("semctl(SETVAL)", errno);
|
|
220
|
+
#else
|
|
221
|
+
assert(shared != nullptr && shared != MAP_FAILED);
|
|
222
|
+
if (id >= shared->count)
|
|
223
|
+
failure("osal_broadcast: id > limit");
|
|
224
|
+
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008
|
|
225
|
+
int err = pthread_cond_broadcast(shared->events + id);
|
|
226
|
+
if (err)
|
|
227
|
+
failure_perror("pthread_cond_broadcast(shared)", err);
|
|
228
|
+
#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
|
|
229
|
+
if (sem_post(shared->events + id))
|
|
230
|
+
failure_perror("sem_post(shared)", errno);
|
|
231
|
+
#else
|
|
232
|
+
#error "FIXME"
|
|
233
|
+
#endif /* MDBX_LOCKING */
|
|
234
|
+
#endif /* MDBX_LOCKING != MDBX_LOCKING_SYSV */
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
int osal_waitfor(unsigned id) {
|
|
238
|
+
log_trace("osal_waitfor: event %u", id);
|
|
239
|
+
#if MDBX_LOCKING == MDBX_LOCKING_SYSV
|
|
240
|
+
struct sembuf op;
|
|
241
|
+
memset(&op, 0, sizeof(op));
|
|
242
|
+
op.sem_num = (short)(id + 1);
|
|
243
|
+
int rc = semop(ipc, &op, 1) ? errno : MDBX_SUCCESS;
|
|
244
|
+
#else
|
|
245
|
+
assert(shared != nullptr && shared != MAP_FAILED);
|
|
246
|
+
if (id >= shared->count)
|
|
247
|
+
failure("osal_waitfor: id > limit");
|
|
248
|
+
|
|
249
|
+
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008
|
|
250
|
+
int rc = pthread_mutex_lock(&shared->mutex);
|
|
251
|
+
if (rc != 0)
|
|
252
|
+
failure_perror("pthread_mutex_lock(shared)", rc);
|
|
253
|
+
|
|
254
|
+
rc = pthread_cond_wait(shared->events + id, &shared->mutex);
|
|
255
|
+
if (rc && rc != EINTR)
|
|
256
|
+
failure_perror("pthread_cond_wait(shared)", rc);
|
|
257
|
+
|
|
258
|
+
rc = pthread_mutex_unlock(&shared->mutex);
|
|
259
|
+
if (rc != 0)
|
|
260
|
+
failure_perror("pthread_mutex_unlock(shared)", rc);
|
|
261
|
+
#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
|
|
262
|
+
int rc = sem_wait(shared->events + id) ? errno : 0;
|
|
263
|
+
if (rc == 0 && sem_post(shared->events + id))
|
|
264
|
+
failure_perror("sem_post(shared)", errno);
|
|
265
|
+
#else
|
|
266
|
+
#error "FIXME"
|
|
267
|
+
#endif /* MDBX_LOCKING */
|
|
268
|
+
#endif /* MDBX_LOCKING != MDBX_LOCKING_SYSV */
|
|
269
|
+
|
|
270
|
+
return (rc == 0) ? true : false;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
//-----------------------------------------------------------------------------
|
|
274
|
+
|
|
275
|
+
const std::string actor_config::osal_serialize(simple_checksum &checksum) const {
|
|
276
|
+
(void)checksum;
|
|
277
|
+
/* not used in workload, but just for testing */
|
|
278
|
+
return "unix.fork";
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
bool actor_config::osal_deserialize(const char *str, const char *end, simple_checksum &checksum) {
|
|
282
|
+
(void)checksum;
|
|
283
|
+
/* not used in workload, but just for testing */
|
|
284
|
+
return strncmp(str, "unix.fork", 9) == 0 && str + 9 == end;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
//-----------------------------------------------------------------------------
|
|
288
|
+
|
|
289
|
+
static pid_t overlord_pid;
|
|
290
|
+
|
|
291
|
+
static std::atomic_int sigusr1_head, sigusr2_head;
|
|
292
|
+
static void handler_SIGUSR(int signum) {
|
|
293
|
+
switch (signum) {
|
|
294
|
+
case SIGUSR1:
|
|
295
|
+
++sigusr1_head;
|
|
296
|
+
return;
|
|
297
|
+
case SIGUSR2:
|
|
298
|
+
++sigusr2_head;
|
|
299
|
+
return;
|
|
300
|
+
default:
|
|
301
|
+
abort();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
bool osal_multiactor_mode(void) { return overlord_pid != 0; }
|
|
306
|
+
|
|
307
|
+
bool osal_progress_push(bool active) {
|
|
308
|
+
if (overlord_pid) {
|
|
309
|
+
if (kill(overlord_pid, active ? SIGUSR1 : SIGUSR2))
|
|
310
|
+
failure_perror("osal_progress_push: kill(overload)", errno);
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
//-----------------------------------------------------------------------------
|
|
318
|
+
|
|
319
|
+
static std::unordered_map<pid_t, actor_status> children;
|
|
320
|
+
|
|
321
|
+
static std::atomic_int sigalarm_head;
|
|
322
|
+
static void handler_SIGCHLD(int signum) {
|
|
323
|
+
if (signum == SIGALRM)
|
|
324
|
+
++sigalarm_head;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
static std::atomic_int sigbreak;
|
|
328
|
+
static void handler_SIGBREAK(int signum) {
|
|
329
|
+
(void)signum;
|
|
330
|
+
++sigbreak;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
int osal_delay(unsigned seconds) { return sleep(seconds) ? errno : 0; }
|
|
334
|
+
|
|
335
|
+
int osal_actor_start(const actor_config &config, mdbx_pid_t &pid) {
|
|
336
|
+
static sigset_t mask;
|
|
337
|
+
if (children.empty()) {
|
|
338
|
+
struct sigaction act;
|
|
339
|
+
memset(&act, 0, sizeof(act));
|
|
340
|
+
act.sa_handler = handler_SIGBREAK;
|
|
341
|
+
sigaction(SIGTERM, &act, nullptr);
|
|
342
|
+
sigaction(SIGHUP, &act, nullptr);
|
|
343
|
+
sigaction(SIGINT, &act, nullptr);
|
|
344
|
+
sigaction(SIGQUIT, &act, nullptr);
|
|
345
|
+
#ifdef SIGXCPU
|
|
346
|
+
sigaction(SIGXCPU, &act, nullptr);
|
|
347
|
+
#endif
|
|
348
|
+
#ifdef SIGXFSZ
|
|
349
|
+
sigaction(SIGXFSZ, &act, nullptr);
|
|
350
|
+
#endif
|
|
351
|
+
act.sa_handler = handler_SIGCHLD;
|
|
352
|
+
sigaction(SIGCHLD, &act, nullptr);
|
|
353
|
+
sigaction(SIGALRM, &act, nullptr);
|
|
354
|
+
act.sa_handler = handler_SIGUSR;
|
|
355
|
+
sigaction(SIGUSR1, &act, nullptr);
|
|
356
|
+
sigaction(SIGUSR2, &act, nullptr);
|
|
357
|
+
|
|
358
|
+
sigemptyset(&mask);
|
|
359
|
+
sigaddset(&mask, SIGCHLD);
|
|
360
|
+
sigaddset(&mask, SIGUSR1);
|
|
361
|
+
sigaddset(&mask, SIGUSR2);
|
|
362
|
+
sigprocmask(SIG_UNBLOCK, &mask, nullptr);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
pid = fork();
|
|
366
|
+
|
|
367
|
+
if (pid == 0) {
|
|
368
|
+
sigprocmask(SIG_BLOCK, &mask, nullptr);
|
|
369
|
+
overlord_pid = getppid();
|
|
370
|
+
const bool result = test_execute(config);
|
|
371
|
+
exit(result ? EXIT_SUCCESS : EXIT_FAILURE);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (pid < 0)
|
|
375
|
+
return errno;
|
|
376
|
+
|
|
377
|
+
log_trace("osal_actor_start: fork pid %ld for %u", (long)pid, config.actor_id);
|
|
378
|
+
children[pid] = as_running;
|
|
379
|
+
return 0;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
actor_status osal_actor_info(const mdbx_pid_t pid) { return children.at(pid); }
|
|
383
|
+
|
|
384
|
+
void osal_killall_actors(void) {
|
|
385
|
+
for (auto &pair : children) {
|
|
386
|
+
kill(pair.first, SIGKILL);
|
|
387
|
+
pair.second = as_killed;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const char *signal_name(const int sig) {
|
|
392
|
+
if (sig == SIGHUP)
|
|
393
|
+
return "HUP";
|
|
394
|
+
if (sig == SIGINT)
|
|
395
|
+
return "INT";
|
|
396
|
+
if (sig == SIGQUIT)
|
|
397
|
+
return "QUIT";
|
|
398
|
+
if (sig == SIGILL)
|
|
399
|
+
return "ILL";
|
|
400
|
+
if (sig == SIGTRAP)
|
|
401
|
+
return "TRAP";
|
|
402
|
+
if (sig == SIGABRT)
|
|
403
|
+
return "ABRT";
|
|
404
|
+
if (sig == SIGBUS)
|
|
405
|
+
return "BUS";
|
|
406
|
+
if (sig == SIGKILL)
|
|
407
|
+
return "KILL";
|
|
408
|
+
if (sig == SIGUSR1)
|
|
409
|
+
return "USR1";
|
|
410
|
+
if (sig == SIGSEGV)
|
|
411
|
+
return "SEGV";
|
|
412
|
+
if (sig == SIGUSR2)
|
|
413
|
+
return "USR2";
|
|
414
|
+
if (sig == SIGPIPE)
|
|
415
|
+
return "PIPE";
|
|
416
|
+
if (sig == SIGALRM)
|
|
417
|
+
return "ALRM";
|
|
418
|
+
if (sig == SIGTERM)
|
|
419
|
+
return "TERM";
|
|
420
|
+
if (sig == SIGCHLD)
|
|
421
|
+
return "CHLD";
|
|
422
|
+
if (sig == SIGCONT)
|
|
423
|
+
return "CONT";
|
|
424
|
+
if (sig == SIGSTOP)
|
|
425
|
+
return "STOP";
|
|
426
|
+
#ifdef SIGPOLL
|
|
427
|
+
if (sig == SIGPOLL)
|
|
428
|
+
return "POLL";
|
|
429
|
+
#endif
|
|
430
|
+
#ifdef SIGFPE
|
|
431
|
+
if (sig == SIGFPE)
|
|
432
|
+
return "FPE";
|
|
433
|
+
#endif
|
|
434
|
+
#ifdef SIGEMT
|
|
435
|
+
if (sig == SIGEMT)
|
|
436
|
+
return "EMT";
|
|
437
|
+
#endif
|
|
438
|
+
#ifdef SIGSTKFLT
|
|
439
|
+
if (sig == SIGSTKFLT)
|
|
440
|
+
return "STKFLT";
|
|
441
|
+
#endif
|
|
442
|
+
#ifdef SIGTSTP
|
|
443
|
+
if (sig == SIGTSTP)
|
|
444
|
+
return "TSTP";
|
|
445
|
+
#endif
|
|
446
|
+
#ifdef SIGTTIN
|
|
447
|
+
if (sig == SIGTTIN)
|
|
448
|
+
return "TTIN";
|
|
449
|
+
#endif
|
|
450
|
+
#ifdef SIGTTOU
|
|
451
|
+
if (sig == SIGTTOU)
|
|
452
|
+
return "TTOU";
|
|
453
|
+
#endif
|
|
454
|
+
#ifdef SIGURG
|
|
455
|
+
if (sig == SIGURG)
|
|
456
|
+
return "URG";
|
|
457
|
+
#endif
|
|
458
|
+
#ifdef SIGXCPU
|
|
459
|
+
if (sig == SIGXCPU)
|
|
460
|
+
return "XCPU";
|
|
461
|
+
#endif
|
|
462
|
+
#ifdef SIGXFSZ
|
|
463
|
+
if (sig == SIGXFSZ)
|
|
464
|
+
return "XFSZ";
|
|
465
|
+
#endif
|
|
466
|
+
#ifdef SIGVTALRM
|
|
467
|
+
if (sig == SIGVTALRM)
|
|
468
|
+
return "VTALRM";
|
|
469
|
+
#endif
|
|
470
|
+
#ifdef SIGPROF
|
|
471
|
+
if (sig == SIGPROF)
|
|
472
|
+
return "PROF";
|
|
473
|
+
#endif
|
|
474
|
+
#ifdef SIGWINCH
|
|
475
|
+
if (sig == SIGWINCH)
|
|
476
|
+
return "WINCH";
|
|
477
|
+
#endif
|
|
478
|
+
#ifdef SIGIO
|
|
479
|
+
if (sig == SIGIO)
|
|
480
|
+
return "IO";
|
|
481
|
+
#endif
|
|
482
|
+
#ifdef SIGPWR
|
|
483
|
+
if (sig == SIGPWR)
|
|
484
|
+
return "PWR";
|
|
485
|
+
#endif
|
|
486
|
+
#ifdef SIGSYS
|
|
487
|
+
if (sig == SIGSYS)
|
|
488
|
+
return "SYS";
|
|
489
|
+
#endif
|
|
490
|
+
static char buf[32];
|
|
491
|
+
snprintf(buf, sizeof(buf), "%u", sig);
|
|
492
|
+
return buf;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) {
|
|
496
|
+
static sig_atomic_t sigalarm_tail;
|
|
497
|
+
alarm(0) /* cancel prev timeout */;
|
|
498
|
+
sigalarm_tail = sigalarm_head /* reset timeout flag */;
|
|
499
|
+
|
|
500
|
+
int options = WNOHANG;
|
|
501
|
+
if (timeout && !sigbreak) {
|
|
502
|
+
alarm((timeout > INT_MAX) ? INT_MAX : timeout);
|
|
503
|
+
options = 0;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
#ifdef WUNTRACED
|
|
507
|
+
options |= WUNTRACED;
|
|
508
|
+
#endif
|
|
509
|
+
#ifdef WCONTINUED
|
|
510
|
+
options |= WCONTINUED;
|
|
511
|
+
#endif
|
|
512
|
+
|
|
513
|
+
pid = 0;
|
|
514
|
+
while (sigalarm_tail == sigalarm_head) {
|
|
515
|
+
int status;
|
|
516
|
+
pid = waitpid(0, &status, options);
|
|
517
|
+
const int err = errno;
|
|
518
|
+
|
|
519
|
+
if (pid > 0) {
|
|
520
|
+
if (WIFEXITED(status))
|
|
521
|
+
children[pid] = (WEXITSTATUS(status) == EXIT_SUCCESS) ? as_successful : as_failed;
|
|
522
|
+
else if (WIFSIGNALED(status)) {
|
|
523
|
+
int sig = WTERMSIG(status);
|
|
524
|
+
#ifdef WCOREDUMP
|
|
525
|
+
if (WCOREDUMP(status))
|
|
526
|
+
children[pid] = as_coredump;
|
|
527
|
+
else
|
|
528
|
+
#endif /* WCOREDUMP */
|
|
529
|
+
switch (sig) {
|
|
530
|
+
case SIGABRT:
|
|
531
|
+
case SIGBUS:
|
|
532
|
+
case SIGFPE:
|
|
533
|
+
case SIGILL:
|
|
534
|
+
case SIGSEGV:
|
|
535
|
+
log_notice("child pid %lu %s by SIG%s", (long)pid, "terminated", signal_name(sig));
|
|
536
|
+
children[pid] = as_coredump;
|
|
537
|
+
break;
|
|
538
|
+
default:
|
|
539
|
+
log_notice("child pid %lu %s by SIG%s", (long)pid, "killed", signal_name(sig));
|
|
540
|
+
children[pid] = as_killed;
|
|
541
|
+
}
|
|
542
|
+
} else if (WIFSTOPPED(status))
|
|
543
|
+
children[pid] = as_debugging;
|
|
544
|
+
else if (WIFCONTINUED(status))
|
|
545
|
+
children[pid] = as_running;
|
|
546
|
+
else {
|
|
547
|
+
assert(false);
|
|
548
|
+
}
|
|
549
|
+
return 0;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
static sig_atomic_t sigusr1_tail, sigusr2_tail;
|
|
553
|
+
if (sigusr1_tail != sigusr1_head) {
|
|
554
|
+
sigusr1_tail = sigusr1_head;
|
|
555
|
+
logging::progress_canary(true);
|
|
556
|
+
if (pid < 0 && err == EINTR)
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
if (sigusr2_tail != sigusr2_head) {
|
|
560
|
+
sigusr2_tail = sigusr2_head;
|
|
561
|
+
logging::progress_canary(false);
|
|
562
|
+
if (pid < 0 && err == EINTR)
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
if (pid == 0 || sigbreak)
|
|
567
|
+
break;
|
|
568
|
+
|
|
569
|
+
if (err != EINTR)
|
|
570
|
+
return err;
|
|
571
|
+
}
|
|
572
|
+
return sigbreak ? EINTR : 0 /* timeout */;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
void osal_yield(void) {
|
|
576
|
+
if (sched_yield())
|
|
577
|
+
failure_perror("sched_yield()", errno);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
void osal_udelay(size_t us) {
|
|
581
|
+
chrono::time until, now = chrono::now_monotonic();
|
|
582
|
+
until.fixedpoint = now.fixedpoint + chrono::from_us(us).fixedpoint;
|
|
583
|
+
struct timespec ts;
|
|
584
|
+
|
|
585
|
+
static size_t threshold_us;
|
|
586
|
+
if (threshold_us == 0) {
|
|
587
|
+
#if defined(_POSIX_CPUTIME) && _POSIX_CPUTIME > -1 && defined(CLOCK_PROCESS_CPUTIME_ID)
|
|
588
|
+
if (clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts)) {
|
|
589
|
+
int rc = errno;
|
|
590
|
+
log_warning("clock_getres(CLOCK_PROCESS_CPUTIME_ID), failed errno %d", rc);
|
|
591
|
+
}
|
|
592
|
+
#endif /* CLOCK_PROCESS_CPUTIME_ID */
|
|
593
|
+
if (threshold_us == 0 && clock_getres(CLOCK_MONOTONIC, &ts)) {
|
|
594
|
+
int rc = errno;
|
|
595
|
+
failure_perror("clock_getres(CLOCK_MONOTONIC)", rc);
|
|
596
|
+
}
|
|
597
|
+
chrono::time threshold = chrono::from_timespec(ts);
|
|
598
|
+
assert(threshold.seconds() == 0);
|
|
599
|
+
|
|
600
|
+
threshold_us = chrono::fractional2us(threshold.fractional);
|
|
601
|
+
if (threshold_us < 1000)
|
|
602
|
+
threshold_us = 1000;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
ts.tv_sec = ts.tv_nsec = 0;
|
|
606
|
+
if (us > threshold_us) {
|
|
607
|
+
ts.tv_sec = us / 1000000u;
|
|
608
|
+
ts.tv_nsec = (us % 1000000u) * 1000u;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
do {
|
|
612
|
+
if (us > threshold_us) {
|
|
613
|
+
if (nanosleep(&ts, &ts)) {
|
|
614
|
+
int rc = errno;
|
|
615
|
+
/* if (rc == EINTR) { ... } ? */
|
|
616
|
+
failure_perror("usleep()", rc);
|
|
617
|
+
}
|
|
618
|
+
us = ts.tv_sec * 1000000u + ts.tv_nsec / 1000u;
|
|
619
|
+
}
|
|
620
|
+
cpu_relax();
|
|
621
|
+
|
|
622
|
+
now = chrono::now_monotonic();
|
|
623
|
+
} while (until.fixedpoint > now.fixedpoint);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
bool osal_istty(int fd) { return isatty(fd) == 1; }
|
|
627
|
+
|
|
628
|
+
std::string osal_tempdir(void) {
|
|
629
|
+
const char *tempdir = getenv("TMPDIR");
|
|
630
|
+
if (!tempdir)
|
|
631
|
+
tempdir = getenv("TMP");
|
|
632
|
+
if (!tempdir)
|
|
633
|
+
tempdir = getenv("TEMPDIR");
|
|
634
|
+
if (!tempdir)
|
|
635
|
+
tempdir = getenv("TEMP");
|
|
636
|
+
if (tempdir && *tempdir) {
|
|
637
|
+
std::string dir(tempdir);
|
|
638
|
+
if (dir.back() != '/')
|
|
639
|
+
dir.append("/");
|
|
640
|
+
return dir;
|
|
641
|
+
}
|
|
642
|
+
if (access("/dev/shm/", R_OK | W_OK | X_OK) == 0)
|
|
643
|
+
return "/dev/shm/";
|
|
644
|
+
return "";
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
#endif /* !Windows */
|