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

Mingw support (2022-1) #451

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
9 changes: 8 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ if (NOT SNMALLOC_HEADER_ONLY_LIBRARY)
set(SNMALLOC_CLEANUP_DEFAULT THREAD_CLEANUP)
elseif (UNIX AND NOT APPLE)
set(SNMALLOC_CLEANUP_DEFAULT PTHREAD_DESTRUCTORS)
elseif(MINGW)
set(SNMALLOC_CLEANUP_DEFAULT PTHREAD_DESTRUCTORS)
else ()
set(SNMALLOC_CLEANUP_DEFAULT CXX11_DESTRUCTORS)
endif()
Expand Down Expand Up @@ -186,6 +188,10 @@ if (WIN32)
message(STATUS "snmalloc: Avoiding Windows 10 APIs is ${WIN8COMPAT}")
endif()

if (MINGW)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please can you add a comment explaining what this is needed for (getrandom?)

target_link_libraries(snmalloc INTERFACE -lbcrypt)
endif()

# Detect support for cmpxchg16b; Werror is needed to make sure mcx16 must be used by targets
check_cxx_compiler_flag("-Werror -Wextra -Wall -mcx16" SNMALLOC_COMPILER_SUPPORT_MCX16)
if(SNMALLOC_COMPILER_SUPPORT_MCX16)
Expand Down Expand Up @@ -227,7 +233,8 @@ if(MSVC)
target_compile_definitions(snmalloc INTERFACE -D_HAS_EXCEPTIONS=0)
else()
# All symbols are always dynamic on haiku and -rdynamic is redundant (and unsupported).
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Haiku")
# MinGW does not recognize rdynamic either.
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Haiku" AND NOT MINGW)
# Get better stack traces in CI and debug builds.
target_link_options(snmalloc INTERFACE $<${ci_or_debug}:-rdynamic>)
endif()
Expand Down
2 changes: 1 addition & 1 deletion src/override/memcpy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ using namespace snmalloc;
# define snprintf_l(buf, size, loc, msg, ...) \
snprintf(buf, size, msg, __VA_ARGS__)
// Windows has it with an underscore prefix
#elif defined(_MSC_VER)
#elif defined(_MSC_VER) || defined(__MINGW32__)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is gone now, please can you rebase the diff?

# define snprintf_l(buf, size, loc, msg, ...) \
_snprintf_s_l(buf, size, _TRUNCATE, msg, loc, __VA_ARGS__)
#endif
Expand Down
4 changes: 3 additions & 1 deletion src/pal/pal_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
# define NOMINMAX
# endif
# include <windows.h>
# pragma comment(lib, "bcrypt.lib")
# ifndef __MINGW32__
# pragma comment(lib, "bcrypt.lib")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're embedding something in the .lib to tell the linker to link bcrypt, then can we make bcrypt a PRIVATE library rather than an INTERFACE one in the cmake?

# endif
# include <bcrypt.h>
// VirtualAlloc2 is exposed in RS5 headers.
# ifdef NTDDI_WIN10_RS5
Expand Down
79 changes: 43 additions & 36 deletions src/test/func/malloc/malloc.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include <stdio.h>
#include <iomanip>
#include <ios>
#include <iostream>
#include <test/setup.h>

#define SNMALLOC_NAME_MANGLE(a) our_##a
Expand All @@ -15,23 +17,23 @@ void check_result(size_t size, size_t align, void* p, int err, bool null)
bool failed = false;
if (errno != err && err != SUCCESS)
{
printf("Expected error: %d but got %d\n", err, errno);
std::cout << "Expected error: " << err << " but got " << errno << std::endl;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These have all been replaced with the INFO and EXPECT macros. If there are any other places where they're necessary then please can you use the new formatting infrastructure rather than iostream?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure!

failed = true;
}

if (null)
{
if (p != nullptr)
{
printf("Expected null, and got non-null return!\n");
std::cout << "Expected null, and got non-null return!" << std::endl;
abort();
}
return;
}

if ((p == nullptr) && (size != 0))
{
printf("Unexpected null returned.\n");
std::cout << "Unexpected null returned." << std::endl;
failed = true;
}
const auto alloc_size = our_malloc_usable_size(p);
Expand All @@ -46,52 +48,52 @@ void check_result(size_t size, size_t align, void* p, int err, bool null)
#endif
if (exact_size && (alloc_size != expected_size) && (size != 0))
{
printf(
"Usable size is %zu, but required to be %zu.\n",
alloc_size,
expected_size);
std::cout << "Usable size is " << alloc_size << ", but required to be "
<< expected_size << "." << std::endl;
failed = true;
}
if ((!exact_size) && (alloc_size < expected_size))
{
printf(
"Usable size is %zu, but required to be at least %zu.\n",
alloc_size,
expected_size);
std::cout << "Usable size is " << alloc_size
<< ", but required to be at least " << expected_size << "."
<< std::endl;
failed = true;
}
if (
(static_cast<size_t>(reinterpret_cast<uintptr_t>(p) % align) != 0) &&
(size != 0))
{
printf(
"Address is 0x%zx, but required to be aligned to 0x%zx.\n",
reinterpret_cast<size_t>(p),
align);
std::ios_base::fmtflags f(std::cout.flags());
std::cout << std::hex << "Address is " << p
<< ", but required to be aligned to 0x" << align << "."
<< std::endl;
std::cout.flags(f);
failed = true;
}
if (
static_cast<size_t>(
reinterpret_cast<uintptr_t>(p) % natural_alignment(size)) != 0)
{
printf(
"Address is 0x%zx, but should have natural alignment to 0x%zx.\n",
reinterpret_cast<size_t>(p),
natural_alignment(size));
std::ios_base::fmtflags f(std::cout.flags());
std::cout << std::hex << "Address is " << p
<< ", but should have natural alignment to 0x"
<< natural_alignment(size) << "." << std::endl;
std::cout.flags(f);
failed = true;
}

if (failed)
{
printf("check_result failed! %p", p);
std::cout << "check_result failed! " << p << std::endl;
abort();
}
our_free(p);
}

void test_calloc(size_t nmemb, size_t size, int err, bool null)
{
printf("calloc(%zu, %zu) combined size %zu\n", nmemb, size, nmemb * size);
std::cout << "calloc(" << nmemb << ", " << size << ")"
<< " combined size " << nmemb * size << std::endl;
errno = SUCCESS;
void* p = our_calloc(nmemb, size);

Expand All @@ -101,7 +103,7 @@ void test_calloc(size_t nmemb, size_t size, int err, bool null)
{
if (((uint8_t*)p)[i] != 0)
{
printf("non-zero at @%zu\n", i);
std::cout << "non-zero at @" << i << std::endl;
abort();
}
}
Expand All @@ -115,7 +117,8 @@ void test_realloc(void* p, size_t size, int err, bool null)
if (p != nullptr)
old_size = our_malloc_usable_size(p);

printf("realloc(%p(%zu), %zu)\n", p, old_size, size);
std::cout << "realloc(" << p << "(" << old_size << ")"
<< ", " << size << ")" << std::endl;
errno = SUCCESS;
auto new_p = our_realloc(p, size);
// Realloc failure case, deallocate original block
Expand All @@ -126,15 +129,16 @@ void test_realloc(void* p, size_t size, int err, bool null)

void test_posix_memalign(size_t size, size_t align, int err, bool null)
{
printf("posix_memalign(&p, %zu, %zu)\n", align, size);
std::cout << "posix_memalign(&p, " << align << ", " << size << ")"
<< std::endl;
void* p = nullptr;
errno = our_posix_memalign(&p, align, size);
check_result(size, align, p, err, null);
}

void test_memalign(size_t size, size_t align, int err, bool null)
{
printf("memalign(%zu, %zu)\n", align, size);
std::cout << "memalign(" << align << ", " << size << ")" << std::endl;
errno = SUCCESS;
void* p = our_memalign(align, size);
check_result(size, align, p, err, null);
Expand All @@ -147,7 +151,8 @@ void test_reallocarray(void* p, size_t nmemb, size_t size, int err, bool null)
if (p != nullptr)
old_size = our_malloc_usable_size(p);

printf("reallocarray(%p(%zu), %zu)\n", p, old_size, tsize);
std::cout << "reallocarray(" << p << "(" << old_size << ")"
<< ", " << tsize << ")" << std::endl;
errno = SUCCESS;
auto new_p = our_reallocarray(p, nmemb, size);
if (new_p == nullptr && tsize != 0)
Expand All @@ -166,11 +171,13 @@ void test_reallocarr(
int r = our_reallocarr(&p, nmemb, size);
if (r != err)
{
printf("reallocarr failed! expected %d got %d\n", err, r);
std::cout << "reallocarr failed! expected " << err << " got " << r
<< std::endl;
abort();
}

printf("reallocarr(%p(%zu), %zu)\n", p, nmemb, size);
std::cout << "reallocarr(" << p << "(" << nmemb << ")"
<< ", " << size << ")" << std::endl;
check_result(nmemb * size, 1, p, err, null);
p = our_malloc(size);
if (!p)
Expand All @@ -187,7 +194,7 @@ void test_reallocarr(
{
if (static_cast<char*>(p)[i] != 1)
{
printf("data consistency failed! at %zu", i);
std::cout << "data consistency failed! at " << i << std::endl;
abort();
}
}
Expand All @@ -206,7 +213,7 @@ int main(int argc, char** argv)
for (smallsizeclass_t sc = 0; sc < (MAX_SMALL_SIZECLASS_BITS + 4); sc++)
{
const size_t size = bits::one_at_bit(sc);
printf("malloc: %zu\n", size);
std::cout << "malloc: " << size << std::endl;
errno = SUCCESS;
check_result(size, 1, our_malloc(size), SUCCESS, false);
errno = SUCCESS;
Expand Down Expand Up @@ -258,7 +265,7 @@ int main(int argc, char** argv)
for (smallsizeclass_t sc2 = 0; sc2 < (MAX_SMALL_SIZECLASS_BITS + 4); sc2++)
{
const size_t size2 = bits::one_at_bit(sc2);
printf("size1: %zu, size2:%zu\n", size, size2);
std::cout << "size1: " << size << ", size2: " << size2 << std::endl;
test_realloc(our_malloc(size), size2, SUCCESS, false);
test_realloc(our_malloc(size + 1), size2, SUCCESS, false);
}
Expand Down Expand Up @@ -313,28 +320,28 @@ int main(int argc, char** argv)
void* p = our_malloc(size);
if (p == nullptr)
{
printf("realloc alloc failed with %zu\n", size);
std::cout << "realloc alloc failed with " << size << std::endl;
abort();
}
int r = our_reallocarr(&p, 1, ((size_t)-1) / 2);
if (r != ENOMEM)
{
printf("expected failure on allocation\n");
std::cout << "expected failure on allocation" << std::endl;
abort();
}
our_free(p);

for (smallsizeclass_t sc2 = 0; sc2 < (MAX_SMALL_SIZECLASS_BITS + 4); sc2++)
{
const size_t size2 = bits::one_at_bit(sc2);
printf("size1: %zu, size2:%zu\n", size, size2);
std::cout << "size1: " << size << ", size2: " << size2 << std::endl;
test_reallocarr(size, 1, size2, SUCCESS, false);
}
}

if (our_malloc_usable_size(nullptr) != 0)
{
printf("malloc_usable_size(nullptr) should be zero");
std::cout << "malloc_usable_size(nullptr) should be zero" << std::endl;
abort();
}

Expand Down