add rust support (#113)

* add rust support

* move aligned_size to sizeclass.h

* add static qualifier

* adjust CMakeLists.txt, may broke CI tests

* fix msvc's complaining on c++17

* use SNMALLOC_FAST_PATH as the decorator of aligned_size

* adapt new alignment algorithm and add related test

Co-authored-by: mjp41 <mattpark@microsoft.com>

* fix test cases for msvc

* add extra test for size == 0

* treat memory block of same sizeclass as the same

* fix formatting problem

* remove extra declarations

Co-authored-by: Matthew Parkinson <mjp41@users.noreply.github.com>
This commit is contained in:
SchrodingerZhu
2020-01-23 15:08:18 +08:00
committed by Matthew Parkinson
parent 4212ac8e4e
commit 8304dedd17
6 changed files with 145 additions and 45 deletions

View File

@@ -174,4 +174,16 @@ namespace snmalloc
return relative;
}
#endif
SNMALLOC_FAST_PATH static size_t aligned_size(size_t alignment, size_t size)
{
// Client responsible for checking alignment is not zero
assert(alignment != 0);
// Client responsible for checking alignment is not above SUPERSLAB_SIZE
assert(alignment <= SUPERSLAB_SIZE);
// Client responsible for checking alignment is a power of two
assert(bits::next_pow2(alignment) == alignment);
return ((alignment - 1) | (size - 1)) + 1;
}
} // namespace snmalloc

View File

@@ -104,34 +104,6 @@ extern "C"
}
#endif
inline size_t aligned_size(size_t alignment, size_t size)
{
// Client responsible for checking alignment is not zero
assert(alignment != 0);
// Client responsible for checking alignment is not above SUPERSLAB_SIZE
assert(alignment <= SUPERSLAB_SIZE);
// Client responsible for checking alignment is a power of two
assert(bits::next_pow2(alignment) == alignment);
size = bits::max(size, alignment);
snmalloc::sizeclass_t sc = size_to_sizeclass(size);
if (sc >= NUM_SIZECLASSES)
{
// large allocs are 16M aligned, which is maximum we guarantee
return size;
}
for (; sc < NUM_SIZECLASSES; sc++)
{
size = sizeclass_to_size(sc);
if ((size & (~size + 1)) >= alignment)
{
return size;
}
}
// Give max alignment.
return SUPERSLAB_SIZE;
}
SNMALLOC_EXPORT void*
SNMALLOC_NAME_MANGLE(memalign)(size_t alignment, size_t size)
{
@@ -142,13 +114,15 @@ extern "C"
errno = EINVAL;
return nullptr;
}
if ((size + alignment) < size)
{
errno = ENOMEM;
return nullptr;
}
return SNMALLOC_NAME_MANGLE(malloc)(aligned_size(alignment, size));
return SNMALLOC_NAME_MANGLE(malloc)(
size ? aligned_size(alignment, size) : alignment);
}
SNMALLOC_EXPORT void*

38
src/override/rust.cc Normal file
View File

@@ -0,0 +1,38 @@
#include "../mem/slowalloc.h"
#include "../snmalloc.h"
#include <cstring>
#ifndef SNMALLOC_EXPORT
# define SNMALLOC_EXPORT
#endif
using namespace snmalloc;
extern "C" SNMALLOC_EXPORT void* rust_alloc(size_t alignment, size_t size)
{
return ThreadAlloc::get_noncachable()->alloc(aligned_size(alignment, size));
}
extern "C" SNMALLOC_EXPORT void
rust_dealloc(void* ptr, size_t alignment, size_t size)
{
ThreadAlloc::get_noncachable()->dealloc(ptr, aligned_size(alignment, size));
}
extern "C" SNMALLOC_EXPORT void*
rust_realloc(void* ptr, size_t alignment, size_t old_size, size_t new_size)
{
size_t aligned_old_size = aligned_size(alignment, old_size),
aligned_new_size = aligned_size(alignment, new_size);
if (
size_to_sizeclass(aligned_old_size) == size_to_sizeclass(aligned_new_size))
return ptr;
void* p = ThreadAlloc::get_noncachable()->alloc(aligned_new_size);
if (p)
{
std::memcpy(p, ptr, old_size < new_size ? old_size : new_size);
ThreadAlloc::get_noncachable()->dealloc(ptr, aligned_old_size);
}
return p;
}

View File

@@ -8,6 +8,62 @@ snmalloc::sizeclass_t size_to_sizeclass(size_t size)
return snmalloc::size_to_sizeclass(size);
}
void test_align_size()
{
bool failed = false;
assert(snmalloc::aligned_size(128, 160) == 256);
for (size_t size = 1;
size < snmalloc::sizeclass_to_size(snmalloc::NUM_SIZECLASSES - 1);
size++)
{
size_t rsize = snmalloc::sizeclass_to_size(size_to_sizeclass(size));
if (rsize < size)
{
std::cout << "Size class rounding shrunk: " << size << " -> " << rsize
<< std::endl;
failed |= true;
}
auto lsb_rsize = rsize & (~rsize + 1);
auto lsb_size = size & (~size + 1);
if (lsb_rsize < lsb_size)
{
std::cout << "Original size more aligned than rounded size: " << size
<< " (" << lsb_size << ") -> " << rsize << " (" << lsb_rsize
<< ")" << std::endl;
failed |= true;
}
for (size_t alignment_bits = 0; alignment_bits < snmalloc::SUPERSLAB_BITS;
alignment_bits++)
{
auto alignment = (size_t)1 << alignment_bits;
auto asize = snmalloc::aligned_size(alignment, size);
if (asize < size)
{
std::cout << "Shrunk! Alignment: " << alignment << " Size: " << size
<< " ASize: " << asize << std::endl;
failed |= true;
}
if ((asize & (alignment - 1)) != 0)
{
std::cout << "Not aligned! Alignment: " << alignment
<< " Size: " << size << " ASize: " << asize << std::endl;
failed |= true;
}
}
}
if (failed)
abort();
}
int main(int, char**)
{
setup();
@@ -53,4 +109,6 @@ int main(int, char**)
if (failed)
abort();
test_align_size();
}