mesh-rb 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/ext/mesh/extconf.rb +22 -4
- data/ext/mesh/mesh.tar.gz +0 -0
- data/lib/mesh/version.rb +1 -1
- data/mesh.gemspec +3 -2
- metadata +4 -120
- data/ext/mesh/mesh/.bazelrc +0 -20
- data/ext/mesh/mesh/.bazelversion +0 -1
- data/ext/mesh/mesh/.clang-format +0 -15
- data/ext/mesh/mesh/.dockerignore +0 -5
- data/ext/mesh/mesh/.editorconfig +0 -16
- data/ext/mesh/mesh/.gitattributes +0 -4
- data/ext/mesh/mesh/.github/workflows/main.yml +0 -144
- data/ext/mesh/mesh/.gitignore +0 -51
- data/ext/mesh/mesh/AUTHORS +0 -5
- data/ext/mesh/mesh/CMakeLists.txt +0 -270
- data/ext/mesh/mesh/CODE_OF_CONDUCT.md +0 -77
- data/ext/mesh/mesh/Dockerfile +0 -30
- data/ext/mesh/mesh/LICENSE +0 -201
- data/ext/mesh/mesh/Makefile +0 -81
- data/ext/mesh/mesh/README.md +0 -97
- data/ext/mesh/mesh/WORKSPACE +0 -50
- data/ext/mesh/mesh/bazel +0 -350
- data/ext/mesh/mesh/mesh-pldi19-powers.pdf +0 -0
- data/ext/mesh/mesh/src/BUILD +0 -222
- data/ext/mesh/mesh/src/CMakeLists.txt +0 -85
- data/ext/mesh/mesh/src/bitmap.h +0 -590
- data/ext/mesh/mesh/src/cheap_heap.h +0 -170
- data/ext/mesh/mesh/src/common.h +0 -377
- data/ext/mesh/mesh/src/copts.bzl +0 -31
- data/ext/mesh/mesh/src/d_assert.cc +0 -75
- data/ext/mesh/mesh/src/fixed_array.h +0 -124
- data/ext/mesh/mesh/src/global_heap.cc +0 -547
- data/ext/mesh/mesh/src/global_heap.h +0 -569
- data/ext/mesh/mesh/src/gnu_wrapper.cc +0 -75
- data/ext/mesh/mesh/src/internal.h +0 -356
- data/ext/mesh/mesh/src/libmesh.cc +0 -239
- data/ext/mesh/mesh/src/mac_wrapper.cc +0 -528
- data/ext/mesh/mesh/src/measure_rss.cc +0 -44
- data/ext/mesh/mesh/src/measure_rss.h +0 -20
- data/ext/mesh/mesh/src/meshable_arena.cc +0 -776
- data/ext/mesh/mesh/src/meshable_arena.h +0 -309
- data/ext/mesh/mesh/src/meshing.h +0 -60
- data/ext/mesh/mesh/src/mini_heap.h +0 -532
- data/ext/mesh/mesh/src/mmap_heap.h +0 -104
- data/ext/mesh/mesh/src/one_way_mmap_heap.h +0 -77
- data/ext/mesh/mesh/src/partitioned_heap.h +0 -111
- data/ext/mesh/mesh/src/plasma/mesh.h +0 -33
- data/ext/mesh/mesh/src/real.cc +0 -52
- data/ext/mesh/mesh/src/real.h +0 -36
- data/ext/mesh/mesh/src/rng/mwc.h +0 -296
- data/ext/mesh/mesh/src/rng/mwc64.h +0 -58
- data/ext/mesh/mesh/src/rpl_printf.c +0 -1991
- data/ext/mesh/mesh/src/runtime.cc +0 -393
- data/ext/mesh/mesh/src/runtime.h +0 -114
- data/ext/mesh/mesh/src/shuffle_vector.h +0 -287
- data/ext/mesh/mesh/src/size_classes.def +0 -251
- data/ext/mesh/mesh/src/static/if.h +0 -36
- data/ext/mesh/mesh/src/static/log.h +0 -43
- data/ext/mesh/mesh/src/testing/benchmark/local_refill.cc +0 -103
- data/ext/mesh/mesh/src/testing/big-alloc.c +0 -28
- data/ext/mesh/mesh/src/testing/fragmenter.cc +0 -128
- data/ext/mesh/mesh/src/testing/global-large-stress.cc +0 -25
- data/ext/mesh/mesh/src/testing/local-alloc.c +0 -16
- data/ext/mesh/mesh/src/testing/meshing_benchmark.cc +0 -189
- data/ext/mesh/mesh/src/testing/thread.cc +0 -35
- data/ext/mesh/mesh/src/testing/unit/alignment.cc +0 -56
- data/ext/mesh/mesh/src/testing/unit/bitmap_test.cc +0 -274
- data/ext/mesh/mesh/src/testing/unit/concurrent_mesh_test.cc +0 -185
- data/ext/mesh/mesh/src/testing/unit/mesh_test.cc +0 -143
- data/ext/mesh/mesh/src/testing/unit/rng_test.cc +0 -22
- data/ext/mesh/mesh/src/testing/unit/size_class_test.cc +0 -66
- data/ext/mesh/mesh/src/testing/unit/triple_mesh_test.cc +0 -285
- data/ext/mesh/mesh/src/testing/userfaultfd-kernel-copy.cc +0 -164
- data/ext/mesh/mesh/src/thread_local_heap.cc +0 -163
- data/ext/mesh/mesh/src/thread_local_heap.h +0 -268
- data/ext/mesh/mesh/src/wrapper.cc +0 -433
- data/ext/mesh/mesh/support/export_mesh.cmake +0 -28
- data/ext/mesh/mesh/support/gen-size-classes +0 -57
- data/ext/mesh/mesh/support/install_all_configs +0 -33
- data/ext/mesh/mesh/support/remove_export_mesh.cmake +0 -48
- data/ext/mesh/mesh/support/update-bazelisk +0 -8
- data/ext/mesh/mesh/theory/32m80.png +0 -0
- data/ext/mesh/mesh/theory/64m80ind.png +0 -0
- data/ext/mesh/mesh/theory/bound_comparison.py +0 -67
- data/ext/mesh/mesh/theory/bounds/impdeg+1 +0 -135
- data/ext/mesh/mesh/theory/choose.py +0 -43
- data/ext/mesh/mesh/theory/common.py +0 -42
- data/ext/mesh/mesh/theory/compute_exp_Y.py +0 -134
- data/ext/mesh/mesh/theory/createRandomString.py +0 -69
- data/ext/mesh/mesh/theory/deg_bound_check.py +0 -100
- data/ext/mesh/mesh/theory/degcheck.py +0 -47
- data/ext/mesh/mesh/theory/dumps/32,1,80,dumb.txt +0 -81
- data/ext/mesh/mesh/theory/dumps/32,2,80,dumb.txt +0 -81
- data/ext/mesh/mesh/theory/dumps/32,3,80,dumb.txt +0 -81
- data/ext/mesh/mesh/theory/dumps/32,4,80,dumb.txt +0 -81
- data/ext/mesh/mesh/theory/dumps/32,5,80,dumb.txt +0 -81
- data/ext/mesh/mesh/theory/dumps/32,6,80,dumb.txt +0 -81
- data/ext/mesh/mesh/theory/dumps/32,7,80,dumb.txt +0 -81
- data/ext/mesh/mesh/theory/dumps/32,8,80,dumb.txt +0 -81
- data/ext/mesh/mesh/theory/dumps/32,9,80,dumb.txt +0 -81
- data/ext/mesh/mesh/theory/experiment.py +0 -303
- data/ext/mesh/mesh/theory/experiment_raw_results/.gitignore +0 -0
- data/ext/mesh/mesh/theory/greedy_experiment.py +0 -66
- data/ext/mesh/mesh/theory/greedy_experiment_copy.py +0 -46
- data/ext/mesh/mesh/theory/greedy_experiment_q.py +0 -75
- data/ext/mesh/mesh/theory/makeGraph.py +0 -64
- data/ext/mesh/mesh/theory/manyreps.png +0 -0
- data/ext/mesh/mesh/theory/manystrings.png +0 -0
- data/ext/mesh/mesh/theory/match_vs_color_experiment.py +0 -94
- data/ext/mesh/mesh/theory/maxmatch_vs_E[Y].py +0 -162
- data/ext/mesh/mesh/theory/maxmatch_vs_greedymatch.py +0 -96
- data/ext/mesh/mesh/theory/maxvdeg+1imp++32,80.png +0 -0
- data/ext/mesh/mesh/theory/mesh_util.py +0 -322
- data/ext/mesh/mesh/theory/meshers.py +0 -452
- data/ext/mesh/mesh/theory/meshingBenchmark.py +0 -96
- data/ext/mesh/mesh/theory/occupancyComparison.py +0 -133
- data/ext/mesh/mesh/theory/randmatch_vs_greedymatch.py +0 -97
- data/ext/mesh/mesh/theory/randmatch_vs_greedymatch_q.py +0 -103
- data/ext/mesh/mesh/theory/randmatch_vs_greedymatch_time.py +0 -117
- data/ext/mesh/mesh/theory/read_mesh_dump.py +0 -82
- data/ext/mesh/mesh/theory/test.py +0 -70
- data/ext/mesh/mesh/tools/bazel +0 -1
@@ -1,393 +0,0 @@
|
|
1
|
-
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil -*-
|
2
|
-
// Copyright 2019 The Mesh Authors. All rights reserved.
|
3
|
-
// Use of this source code is governed by the Apache License,
|
4
|
-
// Version 2.0, that can be found in the LICENSE file.
|
5
|
-
|
6
|
-
#include <dirent.h>
|
7
|
-
#include <errno.h>
|
8
|
-
#include <pthread.h>
|
9
|
-
#include <sched.h>
|
10
|
-
#include <stdlib.h>
|
11
|
-
#include <sys/syscall.h>
|
12
|
-
#include <sys/types.h>
|
13
|
-
|
14
|
-
#ifdef __linux__
|
15
|
-
#include <sys/signalfd.h>
|
16
|
-
#endif
|
17
|
-
|
18
|
-
#include "runtime.h"
|
19
|
-
#include "thread_local_heap.h"
|
20
|
-
|
21
|
-
namespace mesh {
|
22
|
-
|
23
|
-
ATTRIBUTE_ALIGNED(CACHELINE_SIZE)
|
24
|
-
const unsigned char SizeMap::class_array_[kClassArraySize] = {
|
25
|
-
#include "size_classes.def"
|
26
|
-
};
|
27
|
-
|
28
|
-
ATTRIBUTE_ALIGNED(CACHELINE_SIZE)
|
29
|
-
const int32_t SizeMap::class_to_size_[kClassSizesMax] = {
|
30
|
-
16, 16, 32, 48, 64, 80, 96, 112, 128, 160, 192, 224, 256,
|
31
|
-
320, 384, 448, 512, 640, 768, 896, 1024, 2048, 4096, 8192, 16384,
|
32
|
-
};
|
33
|
-
|
34
|
-
// const internal::BinToken::Size internal::BinToken::Max = numeric_limits<uint32_t>::max();
|
35
|
-
// const internal::BinToken::Size internal::BinToken::MinFlags = numeric_limits<uint32_t>::max() - 4;
|
36
|
-
|
37
|
-
// const internal::BinToken::Size internal::BinToken::FlagFull = numeric_limits<uint32_t>::max() - 1;
|
38
|
-
// const internal::BinToken::Size internal::BinToken::FlagEmpty = numeric_limits<uint32_t>::max() - 2;
|
39
|
-
// const internal::BinToken::Size internal::BinToken::FlagNoOff = numeric_limits<uint32_t>::max();
|
40
|
-
|
41
|
-
STLAllocator<char, internal::Heap> internal::allocator{};
|
42
|
-
|
43
|
-
size_t internal::measurePssKiB() {
|
44
|
-
auto fd = open("/proc/self/smaps_rollup", O_RDONLY | O_CLOEXEC);
|
45
|
-
if (unlikely(fd < 0)) {
|
46
|
-
mesh::debug("measurePssKiB: no smaps_rollup");
|
47
|
-
return 0;
|
48
|
-
}
|
49
|
-
|
50
|
-
static constexpr size_t BUF_LEN = 1024;
|
51
|
-
char buf[BUF_LEN];
|
52
|
-
memset(buf, 0, BUF_LEN);
|
53
|
-
|
54
|
-
auto _ __attribute__((unused)) = read(fd, buf, BUF_LEN - 1);
|
55
|
-
close(fd);
|
56
|
-
|
57
|
-
auto start = strstr(buf, "\nPss: ");
|
58
|
-
if (unlikely(start == nullptr)) {
|
59
|
-
mesh::debug("measurePssKiB: no Pss");
|
60
|
-
return 0;
|
61
|
-
}
|
62
|
-
|
63
|
-
return atoi(&start[6]);
|
64
|
-
}
|
65
|
-
|
66
|
-
int internal::copyFile(int dstFd, int srcFd, off_t off, size_t sz) {
|
67
|
-
d_assert(off >= 0);
|
68
|
-
|
69
|
-
off_t newOff = lseek(dstFd, off, SEEK_SET);
|
70
|
-
d_assert(newOff == off);
|
71
|
-
|
72
|
-
#if defined(__APPLE__) || defined(__FreeBSD__)
|
73
|
-
#warning test that setting offset on dstFd works as intended
|
74
|
-
// fcopyfile works on FreeBSD and OS X 10.5+
|
75
|
-
int result = fcopyfile(srcFd, dstFd, 0, COPYFILE_ALL);
|
76
|
-
#else
|
77
|
-
errno = 0;
|
78
|
-
// sendfile will work with non-socket output (i.e. regular file) on Linux 2.6.33+
|
79
|
-
int result = sendfile(dstFd, srcFd, &off, sz);
|
80
|
-
#endif
|
81
|
-
|
82
|
-
return result;
|
83
|
-
}
|
84
|
-
|
85
|
-
Runtime::Runtime() {
|
86
|
-
updatePid();
|
87
|
-
}
|
88
|
-
|
89
|
-
void Runtime::initMaxMapCount() {
|
90
|
-
#ifndef __linux__
|
91
|
-
return;
|
92
|
-
#endif
|
93
|
-
|
94
|
-
auto fd = open("/proc/sys/vm/max_map_count", O_RDONLY | O_CLOEXEC);
|
95
|
-
if (unlikely(fd < 0)) {
|
96
|
-
mesh::debug("initMaxMapCount: no proc file");
|
97
|
-
return;
|
98
|
-
}
|
99
|
-
|
100
|
-
static constexpr size_t BUF_LEN = 128;
|
101
|
-
char buf[BUF_LEN];
|
102
|
-
memset(buf, 0, BUF_LEN);
|
103
|
-
|
104
|
-
auto _ __attribute__((unused)) = read(fd, buf, BUF_LEN - 1);
|
105
|
-
close(fd);
|
106
|
-
|
107
|
-
errno = 0;
|
108
|
-
int64_t mapCount = strtoll(buf, nullptr, 10);
|
109
|
-
if (errno != 0) {
|
110
|
-
mesh::debug("strtoll: %s (%s)", strerror(errno), buf);
|
111
|
-
return;
|
112
|
-
}
|
113
|
-
|
114
|
-
if (mapCount <= 0) {
|
115
|
-
mesh::debug("expected positive mapCount, not %ll", mapCount);
|
116
|
-
return;
|
117
|
-
}
|
118
|
-
|
119
|
-
const auto meshCount = static_cast<size_t>(kMeshesPerMap * mapCount);
|
120
|
-
|
121
|
-
_heap.setMaxMeshCount(meshCount);
|
122
|
-
}
|
123
|
-
|
124
|
-
int Runtime::createThread(pthread_t *thread, const pthread_attr_t *attr, PthreadFn startRoutine, void *arg) {
|
125
|
-
lock_guard<Runtime> lock(*this);
|
126
|
-
|
127
|
-
if (unlikely(mesh::real::pthread_create == nullptr)) {
|
128
|
-
mesh::real::init();
|
129
|
-
}
|
130
|
-
|
131
|
-
void *threadArgsBuf = mesh::internal::Heap().malloc(sizeof(StartThreadArgs));
|
132
|
-
d_assert(threadArgsBuf != nullptr);
|
133
|
-
StartThreadArgs *threadArgs = new (threadArgsBuf) StartThreadArgs(this, startRoutine, arg);
|
134
|
-
|
135
|
-
return mesh::real::pthread_create(thread, attr, reinterpret_cast<PthreadFn>(startThread), threadArgs);
|
136
|
-
}
|
137
|
-
|
138
|
-
void *Runtime::startThread(StartThreadArgs *threadArgs) {
|
139
|
-
d_assert(threadArgs != nullptr);
|
140
|
-
|
141
|
-
Runtime *runtime = threadArgs->runtime;
|
142
|
-
PthreadFn startRoutine = threadArgs->startRoutine;
|
143
|
-
void *arg = threadArgs->arg;
|
144
|
-
|
145
|
-
mesh::internal::Heap().free(threadArgs);
|
146
|
-
threadArgs = nullptr;
|
147
|
-
|
148
|
-
runtime->installSegfaultHandler();
|
149
|
-
|
150
|
-
return startRoutine(arg);
|
151
|
-
}
|
152
|
-
|
153
|
-
void Runtime::exitThread(void *retval) {
|
154
|
-
if (unlikely(mesh::real::pthread_exit == nullptr)) {
|
155
|
-
mesh::real::init();
|
156
|
-
}
|
157
|
-
|
158
|
-
auto heap = ThreadLocalHeap::GetHeapIfPresent();
|
159
|
-
if (heap != nullptr) {
|
160
|
-
heap->releaseAll();
|
161
|
-
}
|
162
|
-
|
163
|
-
mesh::real::pthread_exit(retval);
|
164
|
-
|
165
|
-
// pthread_exit doesn't return
|
166
|
-
__builtin_unreachable();
|
167
|
-
}
|
168
|
-
|
169
|
-
void Runtime::createSignalFd() {
|
170
|
-
mesh::real::init();
|
171
|
-
|
172
|
-
#ifdef __linux__
|
173
|
-
sigset_t mask;
|
174
|
-
sigemptyset(&mask);
|
175
|
-
sigaddset(&mask, SIGDUMP);
|
176
|
-
|
177
|
-
/* Block signals so that they aren't handled
|
178
|
-
according to their default dispositions */
|
179
|
-
|
180
|
-
auto result = mesh::real::sigprocmask(SIG_BLOCK, &mask, NULL);
|
181
|
-
hard_assert(result == 0);
|
182
|
-
|
183
|
-
_signalFd = signalfd(-1, &mask, 0);
|
184
|
-
hard_assert(_signalFd >= 0);
|
185
|
-
#endif
|
186
|
-
}
|
187
|
-
|
188
|
-
void Runtime::startBgThread() {
|
189
|
-
constexpr int MaxRetries = 20;
|
190
|
-
|
191
|
-
pthread_t bgPthread;
|
192
|
-
int retryCount = 0;
|
193
|
-
int ret = 0;
|
194
|
-
|
195
|
-
while ((ret = pthread_create(&bgPthread, nullptr, Runtime::bgThread, nullptr))) {
|
196
|
-
retryCount++;
|
197
|
-
sched_yield();
|
198
|
-
|
199
|
-
if (retryCount % 10)
|
200
|
-
debug("background thread creation failed, retrying.\n");
|
201
|
-
|
202
|
-
if (retryCount >= MaxRetries) {
|
203
|
-
debug("max retries exceded: couldn't create bg thread, exiting.\n");
|
204
|
-
abort();
|
205
|
-
}
|
206
|
-
}
|
207
|
-
}
|
208
|
-
|
209
|
-
void *Runtime::bgThread(void *arg) {
|
210
|
-
auto &rt = mesh::runtime();
|
211
|
-
|
212
|
-
// debug("libmesh: background thread started\n");
|
213
|
-
|
214
|
-
#ifdef __linux__
|
215
|
-
while (true) {
|
216
|
-
struct signalfd_siginfo siginfo;
|
217
|
-
|
218
|
-
ssize_t s = read(rt._signalFd, &siginfo, sizeof(struct signalfd_siginfo));
|
219
|
-
if (s != sizeof(struct signalfd_siginfo)) {
|
220
|
-
if (s >= 0) {
|
221
|
-
debug("bad read size: %lld\n", s);
|
222
|
-
abort();
|
223
|
-
} else {
|
224
|
-
// read returns -1 if the program gets a process-killing signal
|
225
|
-
return nullptr;
|
226
|
-
}
|
227
|
-
}
|
228
|
-
|
229
|
-
if (static_cast<int>(siginfo.ssi_signo) == SIGDUMP) {
|
230
|
-
// debug("libmesh: background thread received SIGDUMP, starting dump\n");
|
231
|
-
debug(">>>>>>>>>>\n");
|
232
|
-
rt.heap().dumpStrings();
|
233
|
-
// debug("<<<<<<<<<<\n");
|
234
|
-
|
235
|
-
// debug("<<<<<<<<<<\n");
|
236
|
-
} else {
|
237
|
-
auto _ __attribute__((unused)) =
|
238
|
-
write(STDERR_FILENO, "Read unexpected signal\n", strlen("Read unexpected signal\n"));
|
239
|
-
}
|
240
|
-
}
|
241
|
-
#endif
|
242
|
-
return nullptr;
|
243
|
-
}
|
244
|
-
|
245
|
-
void Runtime::lock() {
|
246
|
-
_mutex.lock();
|
247
|
-
}
|
248
|
-
|
249
|
-
void Runtime::unlock() {
|
250
|
-
_mutex.unlock();
|
251
|
-
}
|
252
|
-
|
253
|
-
#ifdef __linux__
|
254
|
-
int Runtime::epollWait(int __epfd, struct epoll_event *__events, int __maxevents, int __timeout) {
|
255
|
-
if (unlikely(mesh::real::epoll_wait == nullptr))
|
256
|
-
mesh::real::init();
|
257
|
-
|
258
|
-
_heap.maybeMesh();
|
259
|
-
|
260
|
-
return mesh::real::epoll_wait(__epfd, __events, __maxevents, __timeout);
|
261
|
-
}
|
262
|
-
|
263
|
-
int Runtime::epollPwait(int __epfd, struct epoll_event *__events, int __maxevents, int __timeout,
|
264
|
-
const __sigset_t *__ss) {
|
265
|
-
if (unlikely(mesh::real::epoll_pwait == nullptr))
|
266
|
-
mesh::real::init();
|
267
|
-
|
268
|
-
_heap.maybeMesh();
|
269
|
-
|
270
|
-
return mesh::real::epoll_pwait(__epfd, __events, __maxevents, __timeout, __ss);
|
271
|
-
}
|
272
|
-
#endif
|
273
|
-
|
274
|
-
static struct sigaction sigbusAction;
|
275
|
-
static struct sigaction sigsegvAction;
|
276
|
-
static mutex sigactionLock;
|
277
|
-
|
278
|
-
int Runtime::sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) {
|
279
|
-
if (unlikely(mesh::real::sigaction == nullptr)) {
|
280
|
-
mesh::real::init();
|
281
|
-
}
|
282
|
-
|
283
|
-
if (signum != SIGSEGV && signum != SIGBUS) {
|
284
|
-
return mesh::real::sigaction(signum, act, oldact);
|
285
|
-
}
|
286
|
-
|
287
|
-
// if a user is trying to install a segfault handler, record that
|
288
|
-
// here to proxy to later.
|
289
|
-
lock_guard<mutex> lock(sigactionLock);
|
290
|
-
|
291
|
-
auto nextAct = &sigsegvAction;
|
292
|
-
if (signum == SIGBUS) {
|
293
|
-
act = &sigbusAction;
|
294
|
-
}
|
295
|
-
|
296
|
-
if (oldact)
|
297
|
-
memcpy(oldact, nextAct, sizeof(*nextAct));
|
298
|
-
|
299
|
-
if (act == nullptr) {
|
300
|
-
memset(nextAct, 0, sizeof(*nextAct));
|
301
|
-
} else {
|
302
|
-
// debug("TODO: user installed a segfault handler");
|
303
|
-
memcpy(nextAct, act, sizeof(*nextAct));
|
304
|
-
}
|
305
|
-
|
306
|
-
return 0;
|
307
|
-
}
|
308
|
-
|
309
|
-
int Runtime::sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
|
310
|
-
if (unlikely(mesh::real::sigprocmask == nullptr))
|
311
|
-
mesh::real::init();
|
312
|
-
|
313
|
-
lock_guard<mutex> lock(sigactionLock);
|
314
|
-
|
315
|
-
// debug("TODO: ensure we never mask SIGSEGV\n");
|
316
|
-
|
317
|
-
return mesh::real::sigprocmask(how, set, oldset);
|
318
|
-
}
|
319
|
-
|
320
|
-
void Runtime::segfaultHandler(int sig, siginfo_t *siginfo, void *context) {
|
321
|
-
if (runtime().pid() != getpid()) {
|
322
|
-
// we are just after fork, and glibc sucks.
|
323
|
-
runtime().heap().doAfterForkChild();
|
324
|
-
}
|
325
|
-
|
326
|
-
// okToProceed is a barrier that ensures any in-progress meshing has
|
327
|
-
// completed, and the reason for the fault was 'just' a meshing
|
328
|
-
if (siginfo->si_code == SEGV_ACCERR && runtime().heap().okToProceed(siginfo->si_addr)) {
|
329
|
-
// debug("TODO: trapped access violation from meshing, log stat\n");
|
330
|
-
return;
|
331
|
-
}
|
332
|
-
|
333
|
-
struct sigaction *action = nullptr;
|
334
|
-
if (sig == SIGBUS) {
|
335
|
-
action = &sigbusAction;
|
336
|
-
} else {
|
337
|
-
action = &sigsegvAction;
|
338
|
-
}
|
339
|
-
|
340
|
-
if (action != nullptr) {
|
341
|
-
if (action->sa_sigaction != nullptr) {
|
342
|
-
action->sa_sigaction(sig, siginfo, context);
|
343
|
-
return;
|
344
|
-
} else if (action->sa_handler == SIG_IGN) {
|
345
|
-
// ignore
|
346
|
-
return;
|
347
|
-
} else if (action->sa_handler != nullptr && action->sa_handler != SIG_DFL) {
|
348
|
-
action->sa_handler(sig);
|
349
|
-
return;
|
350
|
-
}
|
351
|
-
}
|
352
|
-
|
353
|
-
if (siginfo->si_code == SEGV_MAPERR && siginfo->si_addr == nullptr) {
|
354
|
-
debug("libmesh: caught null pointer dereference (signal: %d)", sig);
|
355
|
-
raise(SIGABRT);
|
356
|
-
_Exit(1);
|
357
|
-
} else {
|
358
|
-
debug("segfault (%u/%p): in arena? %d\n", siginfo->si_code, siginfo->si_addr,
|
359
|
-
runtime().heap().contains(siginfo->si_addr));
|
360
|
-
raise(SIGABRT);
|
361
|
-
_Exit(1);
|
362
|
-
}
|
363
|
-
}
|
364
|
-
|
365
|
-
void Runtime::installSegfaultHandler() {
|
366
|
-
struct sigaction action;
|
367
|
-
struct sigaction oldAction;
|
368
|
-
|
369
|
-
memset(&action, 0, sizeof(action));
|
370
|
-
memset(&oldAction, 0, sizeof(oldAction));
|
371
|
-
|
372
|
-
action.sa_sigaction = segfaultHandler;
|
373
|
-
action.sa_flags = SA_SIGINFO | SA_NODEFER;
|
374
|
-
|
375
|
-
auto err = mesh::real::sigaction(SIGBUS, &action, &oldAction);
|
376
|
-
hard_assert(err == 0);
|
377
|
-
|
378
|
-
lock_guard<mutex> lock(sigactionLock);
|
379
|
-
|
380
|
-
if (oldAction.sa_sigaction != nullptr && oldAction.sa_sigaction != segfaultHandler) {
|
381
|
-
// debug("TODO: oldAction not null: %p\n", (void *)oldAction.sa_sigaction);
|
382
|
-
memcpy(&sigbusAction, &oldAction, sizeof(sigbusAction));
|
383
|
-
}
|
384
|
-
|
385
|
-
err = mesh::real::sigaction(SIGSEGV, &action, &oldAction);
|
386
|
-
hard_assert(err == 0);
|
387
|
-
|
388
|
-
if (oldAction.sa_sigaction != nullptr && oldAction.sa_sigaction != segfaultHandler) {
|
389
|
-
// debug("TODO: oldAction not null: %p\n", (void *)oldAction.sa_sigaction);
|
390
|
-
memcpy(&sigsegvAction, &oldAction, sizeof(sigsegvAction));
|
391
|
-
}
|
392
|
-
}
|
393
|
-
} // namespace mesh
|
data/ext/mesh/mesh/src/runtime.h
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil -*-
|
2
|
-
// Copyright 2019 The Mesh Authors. All rights reserved.
|
3
|
-
// Use of this source code is governed by the Apache License,
|
4
|
-
// Version 2.0, that can be found in the LICENSE file.
|
5
|
-
|
6
|
-
#pragma once
|
7
|
-
#ifndef MESH_RUNTIME_H
|
8
|
-
#define MESH_RUNTIME_H
|
9
|
-
|
10
|
-
#include <pthread.h>
|
11
|
-
#include <signal.h> // for stack_t
|
12
|
-
|
13
|
-
#include "internal.h"
|
14
|
-
|
15
|
-
#include "real.h"
|
16
|
-
|
17
|
-
#include "global_heap.h"
|
18
|
-
#include "mmap_heap.h"
|
19
|
-
|
20
|
-
#include "heaplayers.h"
|
21
|
-
|
22
|
-
namespace mesh {
|
23
|
-
|
24
|
-
// function passed to pthread_create
|
25
|
-
typedef void *(*PthreadFn)(void *);
|
26
|
-
|
27
|
-
class Runtime {
|
28
|
-
private:
|
29
|
-
DISALLOW_COPY_AND_ASSIGN(Runtime);
|
30
|
-
|
31
|
-
// ensure we don't mistakenly create additional runtime instances
|
32
|
-
explicit Runtime();
|
33
|
-
|
34
|
-
public:
|
35
|
-
void lock();
|
36
|
-
void unlock();
|
37
|
-
|
38
|
-
inline GlobalHeap &heap() {
|
39
|
-
return _heap;
|
40
|
-
}
|
41
|
-
|
42
|
-
void startBgThread();
|
43
|
-
void initMaxMapCount();
|
44
|
-
|
45
|
-
// we need to wrap pthread_create and pthread_exit so that we can
|
46
|
-
// install our segfault handler and cleanup thread-local heaps.
|
47
|
-
int createThread(pthread_t *thread, const pthread_attr_t *attr, mesh::PthreadFn startRoutine, void *arg);
|
48
|
-
void ATTRIBUTE_NORETURN exitThread(void *retval);
|
49
|
-
|
50
|
-
void setMeshPeriodMs(std::chrono::milliseconds period) {
|
51
|
-
_heap.setMeshPeriodMs(period);
|
52
|
-
}
|
53
|
-
|
54
|
-
#ifdef __linux__
|
55
|
-
int epollWait(int __epfd, struct epoll_event *__events, int __maxevents, int __timeout);
|
56
|
-
int epollPwait(int __epfd, struct epoll_event *__events, int __maxevents, int __timeout, const __sigset_t *__ss);
|
57
|
-
#endif
|
58
|
-
|
59
|
-
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
|
60
|
-
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
|
61
|
-
|
62
|
-
struct StartThreadArgs {
|
63
|
-
explicit StartThreadArgs(Runtime *runtime_, PthreadFn startRoutine_, void *arg_)
|
64
|
-
: runtime(runtime_), startRoutine(startRoutine_), arg(arg_) {
|
65
|
-
}
|
66
|
-
|
67
|
-
Runtime *runtime;
|
68
|
-
PthreadFn startRoutine;
|
69
|
-
void *arg;
|
70
|
-
};
|
71
|
-
|
72
|
-
static void *startThread(StartThreadArgs *threadArgs);
|
73
|
-
|
74
|
-
// so we can call from the libmesh init function
|
75
|
-
void createSignalFd();
|
76
|
-
void installSegfaultHandler();
|
77
|
-
|
78
|
-
void updatePid() {
|
79
|
-
_pid = getpid();
|
80
|
-
}
|
81
|
-
|
82
|
-
pid_t pid() const {
|
83
|
-
return _pid;
|
84
|
-
}
|
85
|
-
|
86
|
-
private:
|
87
|
-
// initialize our pointer to libc's pthread_create, etc. This
|
88
|
-
// happens lazily, as the dynamic linker's dlopen calls into malloc
|
89
|
-
// for memory allocation, so if we try to do this in MeshHeaps's
|
90
|
-
// constructor we deadlock before main even runs.
|
91
|
-
void initThreads();
|
92
|
-
|
93
|
-
static void segfaultHandler(int sig, siginfo_t *siginfo, void *context);
|
94
|
-
|
95
|
-
static void *bgThread(void *arg);
|
96
|
-
|
97
|
-
friend Runtime &runtime();
|
98
|
-
|
99
|
-
mutex _mutex{};
|
100
|
-
int _signalFd{-2};
|
101
|
-
pid_t _pid{};
|
102
|
-
GlobalHeap _heap{};
|
103
|
-
};
|
104
|
-
|
105
|
-
// get a reference to the Runtime singleton
|
106
|
-
inline Runtime &runtime() {
|
107
|
-
// force alignment by using a buffer of doubles.
|
108
|
-
static double buf[(sizeof(Runtime) + sizeof(double) - 1) / sizeof(double)];
|
109
|
-
static Runtime *runtimePtr = new (buf) Runtime{};
|
110
|
-
return *runtimePtr;
|
111
|
-
}
|
112
|
-
} // namespace mesh
|
113
|
-
|
114
|
-
#endif // MESH_RUNTIME_H
|