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.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/ext/mesh/extconf.rb +22 -4
  4. data/ext/mesh/mesh.tar.gz +0 -0
  5. data/lib/mesh/version.rb +1 -1
  6. data/mesh.gemspec +3 -2
  7. metadata +4 -120
  8. data/ext/mesh/mesh/.bazelrc +0 -20
  9. data/ext/mesh/mesh/.bazelversion +0 -1
  10. data/ext/mesh/mesh/.clang-format +0 -15
  11. data/ext/mesh/mesh/.dockerignore +0 -5
  12. data/ext/mesh/mesh/.editorconfig +0 -16
  13. data/ext/mesh/mesh/.gitattributes +0 -4
  14. data/ext/mesh/mesh/.github/workflows/main.yml +0 -144
  15. data/ext/mesh/mesh/.gitignore +0 -51
  16. data/ext/mesh/mesh/AUTHORS +0 -5
  17. data/ext/mesh/mesh/CMakeLists.txt +0 -270
  18. data/ext/mesh/mesh/CODE_OF_CONDUCT.md +0 -77
  19. data/ext/mesh/mesh/Dockerfile +0 -30
  20. data/ext/mesh/mesh/LICENSE +0 -201
  21. data/ext/mesh/mesh/Makefile +0 -81
  22. data/ext/mesh/mesh/README.md +0 -97
  23. data/ext/mesh/mesh/WORKSPACE +0 -50
  24. data/ext/mesh/mesh/bazel +0 -350
  25. data/ext/mesh/mesh/mesh-pldi19-powers.pdf +0 -0
  26. data/ext/mesh/mesh/src/BUILD +0 -222
  27. data/ext/mesh/mesh/src/CMakeLists.txt +0 -85
  28. data/ext/mesh/mesh/src/bitmap.h +0 -590
  29. data/ext/mesh/mesh/src/cheap_heap.h +0 -170
  30. data/ext/mesh/mesh/src/common.h +0 -377
  31. data/ext/mesh/mesh/src/copts.bzl +0 -31
  32. data/ext/mesh/mesh/src/d_assert.cc +0 -75
  33. data/ext/mesh/mesh/src/fixed_array.h +0 -124
  34. data/ext/mesh/mesh/src/global_heap.cc +0 -547
  35. data/ext/mesh/mesh/src/global_heap.h +0 -569
  36. data/ext/mesh/mesh/src/gnu_wrapper.cc +0 -75
  37. data/ext/mesh/mesh/src/internal.h +0 -356
  38. data/ext/mesh/mesh/src/libmesh.cc +0 -239
  39. data/ext/mesh/mesh/src/mac_wrapper.cc +0 -528
  40. data/ext/mesh/mesh/src/measure_rss.cc +0 -44
  41. data/ext/mesh/mesh/src/measure_rss.h +0 -20
  42. data/ext/mesh/mesh/src/meshable_arena.cc +0 -776
  43. data/ext/mesh/mesh/src/meshable_arena.h +0 -309
  44. data/ext/mesh/mesh/src/meshing.h +0 -60
  45. data/ext/mesh/mesh/src/mini_heap.h +0 -532
  46. data/ext/mesh/mesh/src/mmap_heap.h +0 -104
  47. data/ext/mesh/mesh/src/one_way_mmap_heap.h +0 -77
  48. data/ext/mesh/mesh/src/partitioned_heap.h +0 -111
  49. data/ext/mesh/mesh/src/plasma/mesh.h +0 -33
  50. data/ext/mesh/mesh/src/real.cc +0 -52
  51. data/ext/mesh/mesh/src/real.h +0 -36
  52. data/ext/mesh/mesh/src/rng/mwc.h +0 -296
  53. data/ext/mesh/mesh/src/rng/mwc64.h +0 -58
  54. data/ext/mesh/mesh/src/rpl_printf.c +0 -1991
  55. data/ext/mesh/mesh/src/runtime.cc +0 -393
  56. data/ext/mesh/mesh/src/runtime.h +0 -114
  57. data/ext/mesh/mesh/src/shuffle_vector.h +0 -287
  58. data/ext/mesh/mesh/src/size_classes.def +0 -251
  59. data/ext/mesh/mesh/src/static/if.h +0 -36
  60. data/ext/mesh/mesh/src/static/log.h +0 -43
  61. data/ext/mesh/mesh/src/testing/benchmark/local_refill.cc +0 -103
  62. data/ext/mesh/mesh/src/testing/big-alloc.c +0 -28
  63. data/ext/mesh/mesh/src/testing/fragmenter.cc +0 -128
  64. data/ext/mesh/mesh/src/testing/global-large-stress.cc +0 -25
  65. data/ext/mesh/mesh/src/testing/local-alloc.c +0 -16
  66. data/ext/mesh/mesh/src/testing/meshing_benchmark.cc +0 -189
  67. data/ext/mesh/mesh/src/testing/thread.cc +0 -35
  68. data/ext/mesh/mesh/src/testing/unit/alignment.cc +0 -56
  69. data/ext/mesh/mesh/src/testing/unit/bitmap_test.cc +0 -274
  70. data/ext/mesh/mesh/src/testing/unit/concurrent_mesh_test.cc +0 -185
  71. data/ext/mesh/mesh/src/testing/unit/mesh_test.cc +0 -143
  72. data/ext/mesh/mesh/src/testing/unit/rng_test.cc +0 -22
  73. data/ext/mesh/mesh/src/testing/unit/size_class_test.cc +0 -66
  74. data/ext/mesh/mesh/src/testing/unit/triple_mesh_test.cc +0 -285
  75. data/ext/mesh/mesh/src/testing/userfaultfd-kernel-copy.cc +0 -164
  76. data/ext/mesh/mesh/src/thread_local_heap.cc +0 -163
  77. data/ext/mesh/mesh/src/thread_local_heap.h +0 -268
  78. data/ext/mesh/mesh/src/wrapper.cc +0 -433
  79. data/ext/mesh/mesh/support/export_mesh.cmake +0 -28
  80. data/ext/mesh/mesh/support/gen-size-classes +0 -57
  81. data/ext/mesh/mesh/support/install_all_configs +0 -33
  82. data/ext/mesh/mesh/support/remove_export_mesh.cmake +0 -48
  83. data/ext/mesh/mesh/support/update-bazelisk +0 -8
  84. data/ext/mesh/mesh/theory/32m80.png +0 -0
  85. data/ext/mesh/mesh/theory/64m80ind.png +0 -0
  86. data/ext/mesh/mesh/theory/bound_comparison.py +0 -67
  87. data/ext/mesh/mesh/theory/bounds/impdeg+1 +0 -135
  88. data/ext/mesh/mesh/theory/choose.py +0 -43
  89. data/ext/mesh/mesh/theory/common.py +0 -42
  90. data/ext/mesh/mesh/theory/compute_exp_Y.py +0 -134
  91. data/ext/mesh/mesh/theory/createRandomString.py +0 -69
  92. data/ext/mesh/mesh/theory/deg_bound_check.py +0 -100
  93. data/ext/mesh/mesh/theory/degcheck.py +0 -47
  94. data/ext/mesh/mesh/theory/dumps/32,1,80,dumb.txt +0 -81
  95. data/ext/mesh/mesh/theory/dumps/32,2,80,dumb.txt +0 -81
  96. data/ext/mesh/mesh/theory/dumps/32,3,80,dumb.txt +0 -81
  97. data/ext/mesh/mesh/theory/dumps/32,4,80,dumb.txt +0 -81
  98. data/ext/mesh/mesh/theory/dumps/32,5,80,dumb.txt +0 -81
  99. data/ext/mesh/mesh/theory/dumps/32,6,80,dumb.txt +0 -81
  100. data/ext/mesh/mesh/theory/dumps/32,7,80,dumb.txt +0 -81
  101. data/ext/mesh/mesh/theory/dumps/32,8,80,dumb.txt +0 -81
  102. data/ext/mesh/mesh/theory/dumps/32,9,80,dumb.txt +0 -81
  103. data/ext/mesh/mesh/theory/experiment.py +0 -303
  104. data/ext/mesh/mesh/theory/experiment_raw_results/.gitignore +0 -0
  105. data/ext/mesh/mesh/theory/greedy_experiment.py +0 -66
  106. data/ext/mesh/mesh/theory/greedy_experiment_copy.py +0 -46
  107. data/ext/mesh/mesh/theory/greedy_experiment_q.py +0 -75
  108. data/ext/mesh/mesh/theory/makeGraph.py +0 -64
  109. data/ext/mesh/mesh/theory/manyreps.png +0 -0
  110. data/ext/mesh/mesh/theory/manystrings.png +0 -0
  111. data/ext/mesh/mesh/theory/match_vs_color_experiment.py +0 -94
  112. data/ext/mesh/mesh/theory/maxmatch_vs_E[Y].py +0 -162
  113. data/ext/mesh/mesh/theory/maxmatch_vs_greedymatch.py +0 -96
  114. data/ext/mesh/mesh/theory/maxvdeg+1imp++32,80.png +0 -0
  115. data/ext/mesh/mesh/theory/mesh_util.py +0 -322
  116. data/ext/mesh/mesh/theory/meshers.py +0 -452
  117. data/ext/mesh/mesh/theory/meshingBenchmark.py +0 -96
  118. data/ext/mesh/mesh/theory/occupancyComparison.py +0 -133
  119. data/ext/mesh/mesh/theory/randmatch_vs_greedymatch.py +0 -97
  120. data/ext/mesh/mesh/theory/randmatch_vs_greedymatch_q.py +0 -103
  121. data/ext/mesh/mesh/theory/randmatch_vs_greedymatch_time.py +0 -117
  122. data/ext/mesh/mesh/theory/read_mesh_dump.py +0 -82
  123. data/ext/mesh/mesh/theory/test.py +0 -70
  124. data/ext/mesh/mesh/tools/bazel +0 -1
@@ -1,143 +0,0 @@
1
- // -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2
- // Copyright 2017 University of Massachusetts, Amherst
3
-
4
- #include <stdint.h>
5
- #include <stdlib.h>
6
-
7
- #include "gtest/gtest.h"
8
-
9
- #include "internal.h"
10
- #include "meshing.h"
11
- #include "runtime.h"
12
-
13
- using namespace mesh;
14
-
15
- static constexpr uint32_t StrLen = 128;
16
- static constexpr uint32_t ObjCount = 32;
17
-
18
- // shows up in strace logs, but otherwise does nothing
19
- static inline void note(const char *note) {
20
- int _ __attribute__((unused)) = write(-1, note, strlen(note));
21
- }
22
-
23
- static void meshTest(bool invert) {
24
- if (!kMeshingEnabled) {
25
- GTEST_SKIP();
26
- }
27
-
28
- const auto tid = gettid();
29
- GlobalHeap &gheap = runtime().heap();
30
-
31
- // disable automatic meshing for this test
32
- gheap.setMeshPeriodMs(kZeroMs);
33
-
34
- ASSERT_EQ(gheap.getAllocatedMiniheapCount(), 0UL);
35
-
36
- FixedArray<MiniHeap, 1> array{};
37
-
38
- // allocate two miniheaps for the same object size from our global heap
39
- gheap.allocSmallMiniheaps(SizeMap::SizeClass(StrLen), StrLen, array, tid);
40
- MiniHeap *mh1 = array[0];
41
- array.clear();
42
-
43
- gheap.allocSmallMiniheaps(SizeMap::SizeClass(StrLen), StrLen, array, tid);
44
- MiniHeap *mh2 = array[0];
45
- array.clear();
46
-
47
- ASSERT_EQ(gheap.getAllocatedMiniheapCount(), 2UL);
48
-
49
- // sanity checks
50
- ASSERT_TRUE(mh1 != mh2);
51
- ASSERT_EQ(mh1->maxCount(), mh2->maxCount());
52
- ASSERT_EQ(mh1->maxCount(), ObjCount);
53
-
54
- ASSERT_EQ(mh1->bitmap().inUseCount(), 0UL);
55
- ASSERT_EQ(mh2->bitmap().inUseCount(), 0UL);
56
-
57
- // allocate two c strings, one from each miniheap at different offsets
58
- char *s1 = reinterpret_cast<char *>(mh1->mallocAt(gheap.arenaBegin(), 0));
59
- char *s2 = reinterpret_cast<char *>(mh2->mallocAt(gheap.arenaBegin(), ObjCount - 1));
60
-
61
- ASSERT_TRUE(s1 != nullptr);
62
- ASSERT_TRUE(s2 != nullptr);
63
-
64
- // fill in the strings, set the trailing null byte
65
- memset(s1, 'A', StrLen);
66
- memset(s2, 'Z', StrLen);
67
- s1[StrLen - 1] = 0;
68
- s2[StrLen - 1] = 0;
69
-
70
- // copy these strings so we can check the contents after meshing
71
- char *v1 = strdup(s1);
72
- char *v2 = strdup(s2);
73
- ASSERT_STREQ(s1, v1);
74
- ASSERT_STREQ(s2, v2);
75
-
76
- ASSERT_EQ(mh1->inUseCount(), 1UL);
77
- ASSERT_EQ(mh2->inUseCount(), 1UL);
78
-
79
- ASSERT_EQ(mh1->bitmap().inUseCount(), 1UL);
80
- ASSERT_EQ(mh2->bitmap().inUseCount(), 1UL);
81
-
82
- if (invert) {
83
- MiniHeap *tmp = mh1;
84
- mh1 = mh2;
85
- mh2 = tmp;
86
- }
87
-
88
- const auto bitmap1 = mh1->bitmap().bits();
89
- const auto bitmap2 = mh2->bitmap().bits();
90
- const auto len = mh1->bitmap().byteCount();
91
- ASSERT_EQ(len, mh2->bitmap().byteCount());
92
-
93
- ASSERT_TRUE(mesh::bitmapsMeshable(bitmap1, bitmap2, len));
94
-
95
- note("ABOUT TO MESH");
96
- // mesh the two miniheaps together
97
- gheap.meshLocked(mh1, mh2);
98
- note("DONE MESHING");
99
-
100
- // ensure the count of set bits looks right
101
- ASSERT_EQ(mh1->inUseCount(), 2UL);
102
-
103
- // check that our two allocated objects still look right
104
- ASSERT_STREQ(s1, v1);
105
- ASSERT_STREQ(s2, v2);
106
-
107
- // get an aliased pointer to the second string by pointer arithmetic
108
- // on the first string
109
- char *s3 = s1 + (ObjCount - 1) * StrLen;
110
- ASSERT_STREQ(s2, s3);
111
-
112
- // modify the second string, ensure the modification shows up on
113
- // string 3 (would fail if the two miniheaps weren't meshed)
114
- s2[0] = 'b';
115
- ASSERT_EQ(s3[0], 'b');
116
-
117
- ASSERT_EQ(mh1->meshCount(), 2ULL);
118
-
119
- // now free the objects by going through the global heap -- it
120
- // should redirect both objects to the same miniheap
121
- gheap.free(s1);
122
- ASSERT_TRUE(!mh1->isEmpty());
123
- gheap.free(s2);
124
- ASSERT_TRUE(mh1->isEmpty()); // safe because mh1 isn't "done"
125
-
126
- note("ABOUT TO FREE");
127
- gheap.freeMiniheap(mh1);
128
- note("DONE FREE");
129
-
130
- note("ABOUT TO SCAVENGE");
131
- gheap.scavenge(true);
132
- note("DONE SCAVENGE");
133
-
134
- ASSERT_EQ(gheap.getAllocatedMiniheapCount(), 0UL);
135
- }
136
-
137
- TEST(MeshTest, TryMesh) {
138
- meshTest(false);
139
- }
140
-
141
- TEST(MeshTest, TryMeshInverse) {
142
- meshTest(true);
143
- }
@@ -1,22 +0,0 @@
1
- // -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2
- // Copyright 2017 University of Massachusetts, Amherst
3
-
4
- #include <stdalign.h>
5
- #include <cstdint>
6
- #include <cstdlib>
7
-
8
- #include "gtest/gtest.h"
9
-
10
- #include "rng/mwc.h"
11
-
12
- using namespace mesh;
13
-
14
- TEST(RNG, MWCRange) {
15
- MWC mwc{internal::seed(), internal::seed()};
16
- for (size_t i = 0; i < 1000; i++) {
17
- size_t n = mwc.inRange(0, 1);
18
- if (n != 0 && n != 1) {
19
- ASSERT_TRUE(false);
20
- }
21
- }
22
- }
@@ -1,66 +0,0 @@
1
- // -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2
- // Copyright 2017 University of Massachusetts, Amherst
3
-
4
- #include <stdalign.h>
5
- #include <cstdint>
6
- #include <cstdlib>
7
-
8
- #include "gtest/gtest.h"
9
-
10
- #include "common.h"
11
- #include "internal.h"
12
-
13
- using namespace mesh;
14
-
15
- #define roundtrip(n) ASSERT_TRUE(n == SizeMap::ByteSizeForClass(SizeMap::SizeClass(n)))
16
- #define rt_debug(n) \
17
- debug("%d c2s: %zu s2c: %d", n, SizeMap::ByteSizeForClass(SizeMap::SizeClass(n)), SizeMap::SizeClass(n))
18
-
19
- #define pow2Roundtrip(n) ASSERT_TRUE(n == powerOfTwo::ByteSizeForClass(powerOfTwo::ClassForByteSize(n)))
20
-
21
- TEST(SizeClass, MinObjectSize) {
22
- ASSERT_EQ(alignof(max_align_t), kMinObjectSize);
23
-
24
- ASSERT_EQ(kMinObjectSize, 16UL);
25
-
26
- ASSERT_EQ(staticlog(kMinObjectSize), 4);
27
- }
28
-
29
- TEST(SizeClass, SmallClasses) {
30
- roundtrip(16);
31
- // rt_debug(16);
32
-
33
- // ASSERT_TRUE(size2Class(8) >= 0);
34
- // roundtrip(8);
35
- // rt_debug(8);
36
-
37
- roundtrip(32);
38
- }
39
-
40
- TEST(SizeClass, PowerOfTwo) {
41
- ASSERT_TRUE(powerOfTwo::kMinObjectSize == 8);
42
- ASSERT_TRUE(powerOfTwo::ClassForByteSize(8) >= 0);
43
-
44
- pow2Roundtrip(8);
45
- pow2Roundtrip(16);
46
- pow2Roundtrip(32);
47
- }
48
-
49
- TEST(SizeClass, Reciprocal) {
50
- for (size_t i = 0; i < kClassSizesMax; i++) {
51
- volatile const size_t objectSize = SizeMap::class_to_size(i);
52
- // volatile to avoid the compiler compiling it away
53
- volatile const float recip = 1.0 / (float)objectSize;
54
-
55
- for (size_t j = 0; j <= kPageSize; j += 8) {
56
- // we depend on this floating point calcuation always being
57
- // equivalent to the integer division operation
58
- volatile const size_t off = j * recip;
59
- volatile const size_t off2 = j / objectSize;
60
- ASSERT_TRUE(off == off2);
61
- }
62
-
63
- const size_t newObjectSize = __builtin_roundf(1 / recip);
64
- ASSERT_TRUE(newObjectSize == objectSize);
65
- }
66
- }
@@ -1,285 +0,0 @@
1
- // -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2
- // Copyright 2017 University of Massachusetts, Amherst
3
-
4
- #include <sched.h>
5
- #include <stdint.h>
6
- #include <stdlib.h>
7
-
8
- #include <atomic>
9
- #include <mutex>
10
- #include <thread>
11
-
12
- #include "gtest/gtest.h"
13
-
14
- #include "internal.h"
15
- #include "meshing.h"
16
- #include "runtime.h"
17
- #include "shuffle_vector.h"
18
-
19
- using namespace std;
20
- using namespace mesh;
21
-
22
- static constexpr uint32_t StrLen = 128;
23
- static constexpr uint32_t ObjCount = 32;
24
-
25
- static char *s1;
26
- static char *s2;
27
- static char *s3;
28
-
29
- static atomic<int> ShouldExit1;
30
- static atomic<int> ShouldContinueTest1;
31
- static atomic<int> ShouldExit2;
32
- static atomic<int> ShouldContinueTest2;
33
-
34
- #ifdef __APPLE__
35
- #define PTHREAD_CREATE_THROW
36
- #else
37
- #define PTHREAD_CREATE_THROW throw()
38
- #endif
39
-
40
- // we need to wrap pthread_create so that we can safely implement a
41
- // stop-the-world quiescent period for the copy/mremap phase of
42
- // meshing -- copied from libmesh.cc
43
- extern "C" int pthread_create(pthread_t *thread, const pthread_attr_t *attr, mesh::PthreadFn startRoutine,
44
- void *arg) PTHREAD_CREATE_THROW;
45
-
46
- static void writerThread1() {
47
- ShouldContinueTest1 = 1;
48
-
49
- for (size_t i = 1; i < numeric_limits<uint64_t>::max(); i++) {
50
- if (i % 1000000 == 0 && ShouldExit1)
51
- return;
52
-
53
- s1[0] = 'A';
54
- s2[0] = 'B';
55
- }
56
-
57
- debug("loop ended before ShouldExit\n");
58
- }
59
-
60
- static void writerThread2() {
61
- ShouldContinueTest2 = 1;
62
-
63
- for (size_t i = 1; i < numeric_limits<uint64_t>::max(); i++) {
64
- if (i % 1000000 == 0 && ShouldExit2)
65
- return;
66
-
67
- s1[0] = 'A';
68
- s3[0] = 'Z';
69
- }
70
-
71
- debug("loop ended before ShouldExit\n");
72
- }
73
-
74
- // shows up in strace logs, but otherwise does nothing
75
- static inline void note(const char *note) {
76
- int _ __attribute__((unused)) = write(-1, note, strlen(note));
77
- }
78
-
79
- static void meshTestConcurrentWrite(bool invert1, bool invert2) {
80
- const auto tid = gettid();
81
- GlobalHeap &gheap = runtime().heap();
82
-
83
- // disable automatic meshing for this test
84
- gheap.setMeshPeriodMs(kZeroMs);
85
-
86
- ASSERT_EQ(gheap.getAllocatedMiniheapCount(), 0UL);
87
-
88
- FixedArray<MiniHeap, 1> array{};
89
-
90
- // allocate three miniheaps for the same object size from our global heap
91
- gheap.allocSmallMiniheaps(SizeMap::SizeClass(StrLen), StrLen, array, tid);
92
- MiniHeap *mh1 = array[0];
93
- array.clear();
94
-
95
- gheap.allocSmallMiniheaps(SizeMap::SizeClass(StrLen), StrLen, array, tid);
96
- MiniHeap *mh2 = array[0];
97
- array.clear();
98
-
99
- gheap.allocSmallMiniheaps(SizeMap::SizeClass(StrLen), StrLen, array, tid);
100
- MiniHeap *mh3 = array[0];
101
- array.clear();
102
-
103
- const auto sizeClass = mh1->sizeClass();
104
- ASSERT_EQ(SizeMap::SizeClass(StrLen), sizeClass);
105
-
106
- ASSERT_TRUE(mh1->isAttached());
107
- ASSERT_TRUE(mh2->isAttached());
108
- ASSERT_TRUE(mh3->isAttached());
109
-
110
- ASSERT_EQ(gheap.getAllocatedMiniheapCount(), 3UL);
111
-
112
- // sanity checks
113
- ASSERT_TRUE(mh1 != mh2);
114
- ASSERT_TRUE(mh2 != mh3);
115
- ASSERT_EQ(mh1->maxCount(), mh2->maxCount());
116
- ASSERT_EQ(mh2->maxCount(), mh3->maxCount());
117
- ASSERT_EQ(mh1->maxCount(), ObjCount);
118
-
119
- // allocate two c strings, one from each miniheap at different offsets
120
- s1 = reinterpret_cast<char *>(mh1->mallocAt(gheap.arenaBegin(), 0));
121
- s2 = reinterpret_cast<char *>(mh2->mallocAt(gheap.arenaBegin(), ObjCount - 1));
122
- s3 = reinterpret_cast<char *>(mh3->mallocAt(gheap.arenaBegin(), 3));
123
-
124
- ASSERT_TRUE(s1 != nullptr);
125
- ASSERT_TRUE(s2 != nullptr);
126
- ASSERT_TRUE(s3 != nullptr);
127
-
128
- {
129
- const auto f1 = reinterpret_cast<char *>(mh1->mallocAt(gheap.arenaBegin(), 2));
130
- const auto f2 = reinterpret_cast<char *>(mh2->mallocAt(gheap.arenaBegin(), 2));
131
- const auto f3 = reinterpret_cast<char *>(mh3->mallocAt(gheap.arenaBegin(), 2));
132
-
133
- gheap.releaseMiniheapLocked(mh1, mh1->sizeClass());
134
- gheap.releaseMiniheapLocked(mh2, mh1->sizeClass());
135
- gheap.releaseMiniheapLocked(mh3, mh1->sizeClass());
136
-
137
- gheap.free(f1);
138
- gheap.free(f2);
139
- gheap.free(f3);
140
- }
141
-
142
- ASSERT_TRUE(!mh1->isAttached());
143
- ASSERT_TRUE(!mh2->isAttached());
144
- ASSERT_TRUE(!mh3->isAttached());
145
-
146
- // fill in the strings, set the trailing null byte
147
- memset(s1, 'A', StrLen);
148
- memset(s2, 'B', StrLen);
149
- memset(s3, 'Z', StrLen);
150
- s1[StrLen - 1] = 0;
151
- s2[StrLen - 1] = 0;
152
- s3[StrLen - 1] = 0;
153
-
154
- // copy these strings so we can check the contents after meshing
155
- char *v1 = strdup(s1);
156
- char *v2 = strdup(s2);
157
- char *v3 = strdup(s3);
158
- ASSERT_STREQ(s1, v1);
159
- ASSERT_STREQ(s2, v2);
160
- ASSERT_STREQ(s3, v3);
161
-
162
- ASSERT_EQ(mh1->inUseCount(), 1UL);
163
- ASSERT_EQ(mh2->inUseCount(), 1UL);
164
- ASSERT_EQ(mh3->inUseCount(), 1UL);
165
-
166
- if (invert1) {
167
- MiniHeap *tmp = mh1;
168
- mh1 = mh2;
169
- mh2 = tmp;
170
- }
171
-
172
- thread writer1(writerThread1);
173
- thread writer2(writerThread2);
174
-
175
- while (ShouldContinueTest1 != 1)
176
- sched_yield();
177
- while (ShouldContinueTest2 != 1)
178
- sched_yield();
179
-
180
- const auto bitmap1 = mh1->bitmap().bits();
181
- const auto bitmap2 = mh2->bitmap().bits();
182
- const auto bitmap3 = mh3->bitmap().bits();
183
- const auto len = mh1->bitmap().byteCount();
184
- ASSERT_EQ(len, mh2->bitmap().byteCount());
185
- ASSERT_EQ(len, mh3->bitmap().byteCount());
186
-
187
- ASSERT_TRUE(mh1->isMeshingCandidate());
188
- ASSERT_TRUE(mh2->isMeshingCandidate());
189
- ASSERT_TRUE(mh3->isMeshingCandidate());
190
-
191
- // we have a clique
192
- ASSERT_TRUE(mesh::bitmapsMeshable(bitmap1, bitmap2, len));
193
- ASSERT_TRUE(mesh::bitmapsMeshable(bitmap2, bitmap3, len));
194
- ASSERT_TRUE(mesh::bitmapsMeshable(bitmap1, bitmap3, len));
195
-
196
- {
197
- const internal::vector<MiniHeap *> candidates = gheap.meshingCandidatesLocked(mh1->sizeClass());
198
- ASSERT_EQ(candidates.size(), 3ULL);
199
- ASSERT_TRUE(std::find(candidates.begin(), candidates.end(), mh1) != candidates.end());
200
- ASSERT_TRUE(std::find(candidates.begin(), candidates.end(), mh2) != candidates.end());
201
- ASSERT_TRUE(std::find(candidates.begin(), candidates.end(), mh3) != candidates.end());
202
- }
203
-
204
- note("ABOUT TO MESH");
205
- if (!invert2) {
206
- gheap.meshLocked(mh1, mh2);
207
- gheap.meshLocked(mh1, mh3);
208
- } else {
209
- gheap.meshLocked(mh2, mh3);
210
- gheap.meshLocked(mh1, mh2);
211
- }
212
- note("DONE MESHING");
213
-
214
- // ensure the count of set bits looks right
215
- ASSERT_EQ(mh1->inUseCount(), 3UL);
216
-
217
- // check that our two allocated objects still look right
218
- ASSERT_STREQ(s1, v1);
219
- ASSERT_STREQ(s2, v2);
220
- ASSERT_STREQ(s3, v3);
221
-
222
- // get an aliased pointer to the second string by pointer arithmetic
223
- // on the first string
224
- char *t2 = s1 + (ObjCount - 1) * StrLen;
225
- ASSERT_STREQ(s2, t2);
226
- char *t3 = s1 + (3) * StrLen;
227
- ASSERT_STREQ(s3, t3);
228
-
229
- ShouldExit1 = 1;
230
- ShouldExit2 = 1;
231
- writer1.join();
232
- writer2.join();
233
-
234
- // modify the second string, ensure the modification shows up on
235
- // string 3 (would fail if the two miniheaps weren't meshed)
236
- s2[0] = 'b';
237
- ASSERT_EQ(t2[0], 'b');
238
-
239
- s3[0] = 'b';
240
- ASSERT_EQ(t3[0], 'b');
241
-
242
- ASSERT_EQ(mh1->getOff(gheap.arenaBegin(), s1), 0);
243
- ASSERT_EQ(mh1->getOff(gheap.arenaBegin(), s2), ObjCount - 1);
244
- ASSERT_EQ(mh1->getOff(gheap.arenaBegin(), s3), 3);
245
-
246
- {
247
- const internal::vector<MiniHeap *> candidates = gheap.meshingCandidatesLocked(mh1->sizeClass());
248
- ASSERT_EQ(candidates.size(), 1ULL);
249
- ASSERT_EQ(candidates[0], mh1);
250
- }
251
-
252
- // we need to attach the miniheap, otherwise
253
- ASSERT_TRUE(!mh1->isAttached());
254
- mh1->setAttached(gettid(), gheap.freelistFor(mh1->freelistId(), sizeClass));
255
- ASSERT_TRUE(mh1->isAttached());
256
-
257
- // now free the objects by going through the global heap -- it
258
- // should redirect both objects to the same miniheap
259
- gheap.free(s1);
260
- ASSERT_TRUE(!mh1->isEmpty());
261
- gheap.free(s2);
262
- ASSERT_TRUE(!mh1->isEmpty());
263
- gheap.free(s3);
264
- ASSERT_TRUE(mh1->isEmpty());
265
-
266
- note("ABOUT TO FREE");
267
- gheap.freeMiniheap(mh1);
268
- note("DONE FREE");
269
-
270
- note("ABOUT TO SCAVENGE");
271
- gheap.scavenge(true);
272
- note("DONE SCAVENGE");
273
-
274
- ASSERT_EQ(gheap.getAllocatedMiniheapCount(), 0UL);
275
- }
276
-
277
- TEST(TripleMeshTest, MeshAll) {
278
- if (!kMeshingEnabled) {
279
- GTEST_SKIP();
280
- }
281
- meshTestConcurrentWrite(false, false);
282
- meshTestConcurrentWrite(false, true);
283
- meshTestConcurrentWrite(true, false);
284
- meshTestConcurrentWrite(true, true);
285
- }