Skip to content

add rust support #113

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

Merged
merged 13 commits into from
Jan 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
12 changes: 6 additions & 6 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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'
Expand All @@ -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
Expand Down
12 changes: 12 additions & 0 deletions src/mem/sizeclass.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
32 changes: 3 additions & 29 deletions src/override/malloc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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*
Expand Down
38 changes: 38 additions & 0 deletions src/override/rust.cc
Original file line number Diff line number Diff line change
@@ -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;
}
58 changes: 58 additions & 0 deletions src/test/func/sizeclass/sizeclass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -53,4 +109,6 @@ int main(int, char**)

if (failed)
abort();

test_align_size();
}