Fix realloc on freebsd and macos (#1494)

This commit is contained in:
proller 2017-11-16 22:17:09 +03:00 committed by alexey-milovidov
parent ef1b559845
commit fa65bdcf48
6 changed files with 103 additions and 20 deletions

View File

@ -170,7 +170,13 @@ if (NOT MAKE_STATIC_LIBRARIES)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif ()
set (SAN_FLAGS "-O3 -g -fno-omit-frame-pointer")
set (SAN_FLAGS "${SAN_FLAGS} -g -fno-omit-frame-pointer")
if (SAN_DEBUG)
set (SAN_FLAGS "${SAN_FLAGS} -O0")
else ()
set (SAN_FLAGS "${SAN_FLAGS} -O3")
endif ()
set (CMAKE_CXX_FLAGS_ASAN "${CMAKE_CXX_FLAGS_ASAN} ${SAN_FLAGS} -fsanitize=address")
set (CMAKE_C_FLAGS_ASAN "${CMAKE_C_FLAGS_ASAN} ${SAN_FLAGS} -fsanitize=address")
set (CMAKE_CXX_FLAGS_UBSAN "${CMAKE_CXX_FLAGS_UBSAN} ${SAN_FLAGS} -fsanitize=undefined")

View File

@ -7,6 +7,7 @@
#include <cstdlib>
#include <sys/mman.h>
#include <common/mremap.h>
#include <Common/MemoryTracker.h>
#include <Common/Exception.h>
#include <Common/formatReadable.h>
@ -114,7 +115,6 @@ void Allocator<clear_memory_>::free(void * buf, size_t size)
template <bool clear_memory_>
void * Allocator<clear_memory_>::realloc(void * buf, size_t old_size, size_t new_size, size_t alignment)
{
#if !defined(__APPLE__) && !defined(__FreeBSD__)
if (old_size < MMAP_THRESHOLD && new_size < MMAP_THRESHOLD && alignment <= MALLOC_MIN_ALIGNMENT)
{
CurrentMemoryTracker::realloc(old_size, new_size);
@ -131,28 +131,13 @@ void * Allocator<clear_memory_>::realloc(void * buf, size_t old_size, size_t new
{
CurrentMemoryTracker::realloc(old_size, new_size);
buf = mremap(buf, old_size, new_size, MREMAP_MAYMOVE);
// On apple and freebsd self-implemented mremap used (common/mremap.h)
buf = clickhouse_mremap(buf, old_size, new_size, MREMAP_MAYMOVE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (MAP_FAILED == buf)
DB::throwFromErrno("Allocator: Cannot mremap memory chunk from " + formatReadableSizeWithBinarySuffix(old_size) + " to " + formatReadableSizeWithBinarySuffix(new_size) + ".", DB::ErrorCodes::CANNOT_MREMAP);
/// No need for zero-fill, because mmap guarantees it.
}
#else
// TODO: We need to use mmap/calloc on Apple too.
if ((old_size < MMAP_THRESHOLD && new_size < MMAP_THRESHOLD && alignment <= MALLOC_MIN_ALIGNMENT) ||
(old_size >= MMAP_THRESHOLD && new_size >= MMAP_THRESHOLD))
{
CurrentMemoryTracker::realloc(old_size, new_size);
buf = ::realloc(buf, new_size);
if (nullptr == buf)
DB::throwFromErrno("Allocator: Cannot realloc from " + formatReadableSizeWithBinarySuffix(old_size) + " to " + formatReadableSizeWithBinarySuffix(new_size) + ".", DB::ErrorCodes::CANNOT_ALLOCATE_MEMORY);
if (clear_memory)
memset(reinterpret_cast<char *>(buf) + old_size, 0, new_size - old_size);
}
#endif
else
{
void * new_buf = alloc(new_size, alignment);

View File

@ -21,6 +21,7 @@ add_library (common
src/DateLUT.cpp
src/DateLUTImpl.cpp
src/exp10.cpp
src/mremap.cpp
src/JSON.cpp
src/getMemoryAmount.cpp
src/ThreadPool.cpp
@ -34,6 +35,7 @@ add_library (common
include/common/LocalDateTime.h
include/common/ErrorHandlers.h
include/common/exp10.h
include/common/mremap.h
include/common/likely.h
include/common/logger_useful.h
include/common/MultiVersion.h

View File

@ -3,7 +3,13 @@ if (CMAKE_SYSTEM MATCHES "FreeBSD" OR ARCH_32)
else ()
option (USE_INTERNAL_GPERFTOOLS_LIBRARY "Set to FALSE to use system gperftools (tcmalloc) library instead of bundled" ${NOT_UNBUNDLED})
endif ()
option (ENABLE_LIBTCMALLOC "Set to TRUE to enable libtcmalloc" ON)
if (CMAKE_SYSTEM MATCHES "FreeBSD")
option (ENABLE_LIBTCMALLOC "Set to TRUE to enable libtcmalloc" OFF)
else ()
option (ENABLE_LIBTCMALLOC "Set to TRUE to enable libtcmalloc" ON)
endif ()
option (DEBUG_LIBTCMALLOC "Set to TRUE to use debug version of libtcmalloc" OFF)
if (ENABLE_LIBTCMALLOC)

View File

@ -0,0 +1,44 @@
#pragma once
#include <cstddef>
#include <sys/mman.h>
#if defined(MREMAP_MAYMOVE)
// we already have implementation (linux)
#else
#define MREMAP_MAYMOVE 1
void * mremap(void * old_address,
size_t old_size,
size_t new_size,
int flags = 0,
int mmap_prot = 0,
int mmap_flags = 0,
int mmap_fd = -1,
off_t mmap_offset = 0);
#endif
inline void * clickhouse_mremap(void * old_address,
size_t old_size,
size_t new_size,
int flags = 0,
int mmap_prot = 0,
int mmap_flags = 0,
int mmap_fd = -1,
off_t mmap_offset = 0)
{
return mremap(old_address,
old_size,
new_size,
flags
#if !defined(MREMAP_FIXED)
,
mmap_prot,
mmap_flags,
mmap_fd,
mmap_offset
#endif
);
}

View File

@ -0,0 +1,40 @@
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <sys/mman.h>
#include <common/mremap.h>
#if defined(MREMAP_FIXED)
// we already have implementation (linux)
#else
void * mremap(
void * old_address, size_t old_size, size_t new_size, int flags, int mmap_prot, int mmap_flags, int mmap_fd, off_t mmap_offset)
{
/// No actual shrink
if (new_size < old_size)
return old_address;
if (!(flags & MREMAP_MAYMOVE))
{
return nullptr;
}
void * new_address = mmap(nullptr, new_size, mmap_prot, mmap_flags, mmap_fd, mmap_offset);
if (MAP_FAILED == new_address)
{
return MAP_FAILED;
}
memcpy(new_address, old_address, old_size);
if (munmap(old_address, old_size))
{
abort();
}
return new_address;
}
#endif