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:
committed by
Matthew Parkinson
parent
4212ac8e4e
commit
8304dedd17
@@ -6,7 +6,7 @@ option(SNMALLOC_CI_BUILD "Disable features not sensible for CI" OFF)
|
||||
option(USE_MEASURE "Measure performance with histograms" OFF)
|
||||
option(EXPOSE_EXTERNAL_PAGEMAP "Expose the global pagemap" OFF)
|
||||
option(EXPOSE_EXTERNAL_RESERVE "Expose an interface to reserve memory using the default memory provider" OFF)
|
||||
|
||||
option(SNMALLOC_RUST_SUPPORT "Build static library for rust" OFF)
|
||||
set(CACHE_FRIENDLY_OFFSET OFF CACHE STRING "Base offset to place linked-list nodes.")
|
||||
|
||||
# Provide as macro so other projects can reuse
|
||||
@@ -142,32 +142,50 @@ if(NOT DEFINED SNMALLOC_ONLY_HEADER_LIBRARY)
|
||||
set(${result} ${dirlist})
|
||||
endmacro()
|
||||
|
||||
macro(add_shim name)
|
||||
add_library(${name} SHARED src/override/malloc.cc src/override/new.cc)
|
||||
macro(add_shim name type)
|
||||
add_library(${name} ${type} ${ARGN})
|
||||
target_link_libraries(${name} snmalloc_lib)
|
||||
target_compile_definitions(${name} PRIVATE "SNMALLOC_EXPORT=__attribute__((visibility(\"default\")))")
|
||||
if(NOT MSVC)
|
||||
target_compile_definitions(${name} PRIVATE "SNMALLOC_EXPORT=__attribute__((visibility(\"default\")))")
|
||||
endif()
|
||||
set_target_properties(${name} PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
|
||||
if(EXPOSE_EXTERNAL_PAGEMAP)
|
||||
target_compile_definitions(${name} PRIVATE -DSNMALLOC_EXPOSE_PAGEMAP)
|
||||
if(MSVC)
|
||||
target_compile_definitions(${name} PRIVATE /DSNMALLOC_EXPOSE_PAGEMAP)
|
||||
else()
|
||||
target_compile_definitions(${name} PRIVATE -DSNMALLOC_EXPOSE_PAGEMAP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(EXPOSE_EXTERNAL_RESERVE)
|
||||
target_compile_definitions(${name} PRIVATE -DSNMALLOC_EXPOSE_RESERVE)
|
||||
if(MSVC)
|
||||
target_compile_definitions(${name} PRIVATE /DSNMALLOC_EXPOSE_RESERVE)
|
||||
else()
|
||||
target_compile_definitions(${name} PRIVATE -DSNMALLOC_EXPOSE_RESERVE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Ensure that we do not link against C++ stdlib when compiling shims.
|
||||
set_target_properties(${name} PROPERTIES LINKER_LANGUAGE C)
|
||||
if(NOT MSVC)
|
||||
set_target_properties(${name} PROPERTIES LINKER_LANGUAGE C)
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
|
||||
if(NOT MSVC)
|
||||
add_shim(snmallocshim)
|
||||
|
||||
add_shim(snmallocshim-1mib)
|
||||
set(SHARED_FILES src/override/new.cc src/override/malloc.cc)
|
||||
add_shim(snmallocshim SHARED ${SHARED_FILES})
|
||||
add_shim(snmallocshim-1mib SHARED ${SHARED_FILES})
|
||||
target_compile_definitions(snmallocshim-1mib PRIVATE IS_ADDRESS_SPACE_CONSTRAINED)
|
||||
endif()
|
||||
|
||||
if(SNMALLOC_RUST_SUPPORT)
|
||||
add_shim(snmallocshim-rust STATIC src/override/rust.cc)
|
||||
add_shim(snmallocshim-1mib-rust STATIC src/override/rust.cc)
|
||||
target_compile_definitions(snmallocshim-1mib-rust PRIVATE IS_ADDRESS_SPACE_CONSTRAINED)
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(TESTDIR ${CMAKE_CURRENT_SOURCE_DIR}/src/test)
|
||||
|
||||
@@ -72,9 +72,9 @@ jobs:
|
||||
displayName: 'Install Build Dependencies'
|
||||
|
||||
- task: CMake@1
|
||||
displayName: 'CMake .. $(CMakeArgs) -GNinja -DCMAKE_BUILD_TYPE=$(BuildType) -DCMAKE_CXX_FLAGS="$CMAKE_CXX_FLAGS" -DSNMALLOC_CI_BUILD=On'
|
||||
displayName: 'CMake .. $(CMakeArgs) -GNinja -DCMAKE_BUILD_TYPE=$(BuildType) -DCMAKE_CXX_FLAGS="$CMAKE_CXX_FLAGS" -DSNMALLOC_CI_BUILD=On -DSNMALLOC_RUST_SUPPORT=On'
|
||||
inputs:
|
||||
cmakeArgs: '.. $(CMakeArgs) -GNinja -DCMAKE_BUILD_TYPE=$(BuildType) -DCMAKE_CXX_FLAGS="$CMAKE_CXX_FLAGS" -DSNMALLOC_CI_BUILD=On'
|
||||
cmakeArgs: '.. $(CMakeArgs) -GNinja -DCMAKE_BUILD_TYPE=$(BuildType) -DCMAKE_CXX_FLAGS="$CMAKE_CXX_FLAGS" -DSNMALLOC_CI_BUILD=On -DSNMALLOC_RUST_SUPPORT=On'
|
||||
|
||||
- script: |
|
||||
ninja
|
||||
@@ -137,9 +137,9 @@ jobs:
|
||||
|
||||
|
||||
- task: CMake@1
|
||||
displayName: 'CMake .. $(CMakeArgs) -DCMAKE_BUILD_TYPE=$(BuildType) -DSNMALLOC_CI_BUILD=On'
|
||||
displayName: 'CMake .. $(CMakeArgs) -DCMAKE_BUILD_TYPE=$(BuildType) -DSNMALLOC_CI_BUILD=On -DSNMALLOC_RUST_SUPPORT=On'
|
||||
inputs:
|
||||
cmakeArgs: '.. $(CMakeArgs) -DCMAKE_BUILD_TYPE=$(BuildType) -DSNMALLOC_CI_BUILD=On'
|
||||
cmakeArgs: '.. $(CMakeArgs) -DCMAKE_BUILD_TYPE=$(BuildType) -DSNMALLOC_CI_BUILD=On -DSNMALLOC_RUST_SUPPORT=On'
|
||||
|
||||
- task: MSBuild@1
|
||||
displayName: 'Build solution build/snmalloc.sln'
|
||||
@@ -164,9 +164,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- task: CMake@1
|
||||
displayName: 'CMake .. -DCMAKE_BUILD_TYPE=$(BuildType) -DSNMALLOC_CI_BUILD=On'
|
||||
displayName: 'CMake .. -DCMAKE_BUILD_TYPE=$(BuildType) -DSNMALLOC_CI_BUILD=On -DSNMALLOC_RUST_SUPPORT=On'
|
||||
inputs:
|
||||
cmakeArgs: '.. -DCMAKE_BUILD_TYPE=$(BuildType) -DSNMALLOC_CI_BUILD=On'
|
||||
cmakeArgs: '.. -DCMAKE_BUILD_TYPE=$(BuildType) -DSNMALLOC_CI_BUILD=On -DSNMALLOC_RUST_SUPPORT=On'
|
||||
|
||||
- script: |
|
||||
make -j 4
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
38
src/override/rust.cc
Normal 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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
Reference in New Issue
Block a user