Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

32-bits system support? #43

Open
jku65123 opened this issue Aug 1, 2019 · 2 comments
Open

32-bits system support? #43

jku65123 opened this issue Aug 1, 2019 · 2 comments

Comments

@jku65123
Copy link

jku65123 commented Aug 1, 2019

It looks like this cool library only works in 64-bits system, any ideas on how much works to make it on 32-bits system (there are a lot 32-bits devices out there) ? and where to change if we want to support 32-bits? Thanks!

@bpowers
Copy link
Member

bpowers commented Sep 17, 2019

you're right in that we only support 64-bit systems right now. At a minimum, we'd need to decrease the max arena size to 2 GB here: https://github.com/plasma-umass/Mesh/blob/master/src/common.h#L98

I'm not sure what else would be necessary TBH. I think we would be willing to take patches, as long as they aren't very intrusive or complex.

@drake7707
Copy link

drake7707 commented Sep 30, 2019

I got it working on a rpi3 rasbian with the following changes for 32 bit:

Basically:

In configure:

  • Set modern_cpu to false in configure because the check throws an index out of range

In meshable_arena.cc:

  • Change the include of unistd_64.h (doesn't exist on arm) to unistd.h

In bitmap.h:

  • The AtomicBitmapBase assumes 4 entries in _bits to be changed, I reverted that back to the loop as it will now contain 8 entries.
  • wordCount will be twice as much as the bits is divided by 32 instead of 64, so the static_asserts such as wordCount(representationSize(maxBits)) == 4 need to be changed to wordCount(representationSize(maxBits)) == 8
  • In RelaxedBitmapBase there are a few magic numbers 64 and 63. Those need to be changed to 32 and 31.
  • Static asserts at the bottom to check for bitmap size need to have its size doubled as well
  • The MaxBitCount enum needs to be based on uint32_t instead of uint64_t

In common.h:

  • The kArenaSize needed to be set to 1GB. I tried 2GB but it was refused in the syscall mmap2 (checked with strace)
  • The kMinObjectSize needs to be set to 8 instead of 16 so the unit test for alignment doesn't fail

In the size class unit test:

  • 2 asserts that check on kMinObjectSize needed to be adjusted for the change above

I don't know enough C++ magic to do these changes based on a compiler flag so I changed to code directly.

Full diff:

diff --git a/configure b/configure
index 0e84ff6..9659f03 100755
--- a/configure
+++ b/configure
@@ -46,9 +46,10 @@ modern_cpu = True
 if system() == 'Linux':
     # we need to check if the CPU is recent enough to use popcnt and
     # AVX instructions
-    cpuinfo = slurp('/proc/cpuinfo').splitlines()
-    flags = [l for l in cpuinfo if l.startswith('flags')][0]
-    modern_cpu = 'popcnt' in flags and 'avx' in flags
+#    cpuinfo = slurp('/proc/cpuinfo').splitlines()
+#    flags = [l for l in cpuinfo if l.startswith('flags')][0]
+#    modern_cpu = 'popcnt' in flags and 'avx' in flags
+     modern_cpu = 0

 if modern_cpu:
     c.append('cflags', '-march=westmere')
diff --git a/src/bitmap.h b/src/bitmap.h
index 0008833..d68b3b8 100644
--- a/src/bitmap.h
+++ b/src/bitmap.h
@@ -73,6 +73,12 @@ private:
   const Container &_cont;
 };

+template<size_t A, size_t B> struct TAssertEquality {
+  static_assert(A==B, "Not equal");
+  static constexpr bool _cResult = (A==B);
+};
+
+
 template <size_t maxBits>
 class AtomicBitmapBase {
 private:
@@ -83,18 +89,25 @@ public:

   enum { MaxBitCount = maxBits };

+
 protected:
   AtomicBitmapBase(size_t bitCount) {
     d_assert_msg(bitCount <= maxBits, "max bits (%zu) exceeded: %zu", maxBits, bitCount);

-    static_assert(wordCount(representationSize(maxBits)) == 4, "unexpected representation size");
-    // for (size_t i = 0; i < wordCount(representationSize(maxBits)); i++) {
-    //   _bits[i].store(0, std::memory_order_relaxed);
-    // }
-    _bits[0].store(0, std::memory_order_relaxed);
+    static_assert(wordCount(representationSize(maxBits)) == 8, "unexpected representation size");
+     for (size_t i = 0; i < wordCount(representationSize(maxBits)); i++) {
+       _bits[i].store(0, std::memory_order_relaxed);
+     }
+    /*_bits[0].store(0, std::memory_order_relaxed);
     _bits[1].store(0, std::memory_order_relaxed);
     _bits[2].store(0, std::memory_order_relaxed);
     _bits[3].store(0, std::memory_order_relaxed);
+
+    _bits[4].store(0, std::memory_order_relaxed);
+    _bits[5].store(0, std::memory_order_relaxed);
+    _bits[6].store(0, std::memory_order_relaxed);
+    _bits[7].store(0, std::memory_order_relaxed);
+*/
     std::atomic_thread_fence(std::memory_order_release);
   }

@@ -102,13 +115,20 @@ protected:
   }

   inline void ATTRIBUTE_ALWAYS_INLINE setAndExchangeAll(size_t *oldBits, const size_t *newBits) {
-    // for (size_t i = 0; i < wordCount(representationSize(maxBits)); i++) {
-    //   oldBits[i] = _bits[i].exchange(newBits[i]);
-    // }
-    oldBits[0] = _bits[0].exchange(newBits[0], std::memory_order_acq_rel);
+     for (size_t i = 0; i < wordCount(representationSize(maxBits)); i++) {
+       oldBits[i] = _bits[i].exchange(newBits[i]);
+     }
+
+    /*oldBits[0] = _bits[0].exchange(newBits[0], std::memory_order_acq_rel);
     oldBits[1] = _bits[1].exchange(newBits[1], std::memory_order_acq_rel);
     oldBits[2] = _bits[2].exchange(newBits[2], std::memory_order_acq_rel);
     oldBits[3] = _bits[3].exchange(newBits[3], std::memory_order_acq_rel);
+
+    oldBits[4] = _bits[4].exchange(newBits[4], std::memory_order_acq_rel);
+    oldBits[5] = _bits[5].exchange(newBits[5], std::memory_order_acq_rel);
+    oldBits[6] = _bits[6].exchange(newBits[6], std::memory_order_acq_rel);
+    oldBits[7] = _bits[7].exchange(newBits[7], std::memory_order_acq_rel);
+    */
   }

 public:
@@ -163,7 +183,7 @@ private:
 public:
   typedef size_t word_t;

-  enum { MaxBitCount = std::numeric_limits<uint64_t>::max() };
+  enum { MaxBitCount = std::numeric_limits<uint32_t>::max() };

 protected:
   RelaxedBitmapBase(size_t bitCount)
@@ -200,9 +220,9 @@ public:
   inline void setAll(uint64_t bitCount) {
     const size_t numWords = wordCount(representationSize(bitCount));
     for (size_t i = 0; bitCount > 0; i++) {
-      if (bitCount >= 64) {
+      if (bitCount >= 32) {
         _bits[i] = (unsigned long)-1;
-        bitCount -= 64;
+        bitCount -= 32;
       } else {
         _bits[i] = (1ULL << bitCount) - 1;
         bitCount = 0;
@@ -251,7 +271,7 @@ protected:
     return _bitCount;
   }

-  const size_t _bitCount : 63;
+  const size_t _bitCount : 31;
   const size_t _isDynamicallyAllocated : 1;
   word_t *_bits;
 };
@@ -273,21 +293,21 @@ protected:

 public:
   inline void ATTRIBUTE_ALWAYS_INLINE invert() {
-    // constexpr size_t numWords = wordCount(representationSize(maxBits));
-    // for (size_t i = 0; i < numWords; i++) {
-    //   _bits[i] = ~_bits[i];
-    // }
-    _bits[0] = ~_bits[0];
+     constexpr size_t numWords = wordCount(representationSize(maxBits));
+     for (size_t i = 0; i < numWords; i++) {
+       _bits[i] = ~_bits[i];
+     }
+    /*_bits[0] = ~_bits[0];
     _bits[1] = ~_bits[1];
     _bits[2] = ~_bits[2];
-    _bits[3] = ~_bits[3];
+    _bits[3] = ~_bits[3];*/
   }

   inline void ATTRIBUTE_ALWAYS_INLINE setAll(uint64_t bitCount) {
     for (size_t i = 0; bitCount > 0; i++) {
-      if (bitCount >= 64) {
+      if (bitCount >= 32) {
         _bits[i] = (unsigned long)-1;
-        bitCount -= 64;
+        bitCount -= 32;
       } else {
         _bits[i] = (1ULL << bitCount) - 1;
         bitCount = 0;
@@ -538,17 +558,17 @@ public:
     const auto wordCount = byteCount() / sizeof(size_t);
     for (ssize_t i = startWord; i >= 0; i--) {
       uint64_t mask = (1UL << (startOff + 1)) - 1;
-      if (startOff == 63) {
+      if (startOff == 31) {
         mask = ~0UL;
       }
       const auto bits = Super::_bits[i] & mask;
       const auto origStartOff = startOff;
-      startOff = 63;
+      startOff = 31;

       if (bits == 0ULL)
         continue;

-      const size_t off = 64 - __builtin_clzl(bits) - 1;
+      const size_t off = 32 - __builtin_clzl(bits) - 1;

       const auto bit = kWordBits * i + off;
       return bit < bitCount() ? bit : bitCount();
@@ -578,8 +598,10 @@ typedef bitmap::BitmapBase<bitmap::AtomicBitmapBase<256>> Bitmap;
 typedef bitmap::BitmapBase<bitmap::RelaxedFixedBitmapBase<256>> RelaxedFixedBitmap;
 typedef bitmap::BitmapBase<bitmap::RelaxedBitmapBase> RelaxedBitmap;

-static_assert(sizeof(Bitmap) == sizeof(size_t) * 4, "Bitmap unexpected size");
-static_assert(sizeof(RelaxedFixedBitmap) == sizeof(size_t) * 4, "Bitmap unexpected size");
+
+
+static_assert(sizeof(Bitmap) == sizeof(size_t) * 8, "Bitmap unexpected size");
+static_assert(sizeof(RelaxedFixedBitmap) == sizeof(size_t) * 8, "Bitmap unexpected size");
 static_assert(sizeof(RelaxedBitmap) == sizeof(size_t) * 2, "Bitmap unexpected size");
 }  // namespace internal
 }  // namespace mesh
diff --git a/src/common.h b/src/common.h
index 7854558..ae7198b 100644
--- a/src/common.h
+++ b/src/common.h
@@ -52,7 +52,7 @@ static constexpr int kMapShared = 1;
 static constexpr int kMapShared = kMeshingEnabled ? MAP_SHARED : MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
 #endif

-static constexpr size_t kMinObjectSize = 16;
+static constexpr size_t kMinObjectSize = 8;
 static constexpr size_t kMaxSize = 16384;
 static constexpr size_t kClassSizesMax = 96;
 static constexpr size_t kAlignment = 8;
@@ -101,7 +101,7 @@ static constexpr std::chrono::milliseconds kMeshPeriodMs{100};  // 100 ms
 // controls aspects of miniheaps
 static constexpr size_t kMaxMeshes = 256;  // 1 per bit

-static constexpr size_t kArenaSize = 64ULL * 1024ULL * 1024ULL * 1024ULL;  // 64 GB
+static constexpr size_t kArenaSize = 1ULL * 1024ULL * 1024ULL * 1024ULL;  // 1 GB
 static constexpr size_t kAltStackSize = 16 * 1024UL;                       // 16k sigaltstacks
 #define SIGQUIESCE (SIGRTMIN + 7)
 #define SIGDUMP (SIGRTMIN + 8)
diff --git a/src/meshable_arena.cc b/src/meshable_arena.cc
index b325531..023b2a5 100644
--- a/src/meshable_arena.cc
+++ b/src/meshable_arena.cc
@@ -15,7 +15,7 @@
 #include <unistd.h>

 //#include <sys/memfd.h>
-#include <asm/unistd_64.h>
+#include <asm/unistd.h>
 #include <linux/memfd.h>
 #endif

diff --git a/src/unit/bitmap_test.cc b/src/unit/bitmap_test.cc
index 5c0fcc9..30a7f22 100644
--- a/src/unit/bitmap_test.cc
+++ b/src/unit/bitmap_test.cc
@@ -13,10 +13,10 @@

 TEST(BitmapTest, RepresentationSize) {
   ASSERT_EQ(0UL, mesh::bitmap::representationSize(0));
-  ASSERT_EQ(8UL, mesh::bitmap::representationSize(1));
+  ASSERT_EQ(4UL, mesh::bitmap::representationSize(1));
   ASSERT_EQ(8UL, mesh::bitmap::representationSize(64));
   ASSERT_EQ(32UL, mesh::bitmap::representationSize(256));
-  ASSERT_EQ(4UL, mesh::bitmap::representationSize(256) / sizeof(size_t));
+  ASSERT_EQ(8UL, mesh::bitmap::representationSize(256) / sizeof(size_t));
 }

 TEST(BitmapTest, LowestSetBitAt) {
diff --git a/src/unit/size_class_test.cc b/src/unit/size_class_test.cc
index f9e61c3..cefce8c 100644
--- a/src/unit/size_class_test.cc
+++ b/src/unit/size_class_test.cc
@@ -21,9 +21,9 @@ using namespace mesh;
 TEST(SizeClass, MinObjectSize) {
   ASSERT_EQ(alignof(max_align_t), kMinObjectSize);

-  ASSERT_EQ(kMinObjectSize, 16UL);
+  ASSERT_EQ(kMinObjectSize, 8UL);

-  ASSERT_EQ(staticlog(kMinObjectSize), 4);
+  ASSERT_EQ(staticlog(kMinObjectSize), 3);
 }

 TEST(SizeClass, SmallClasses) {

@bpowers Is there any stress test I can run to make sure there aren't any issues after a long period of time?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants