diff --git a/cmake/configuration.cmake b/cmake/configuration.cmake
index 1145b44..70de629 100644
--- a/cmake/configuration.cmake
+++ b/cmake/configuration.cmake
@@ -64,3 +64,5 @@ option(FOONATHAN_MEMORY_EXTERN_TEMPLATE
"whether or not common template instantiations are already provided by the library" ON)
set(FOONATHAN_MEMORY_TEMPORARY_STACK_MODE 2 CACHE STRING
"set to 0 to disable the per-thread stack completely, to 1 to disable the nitfy counter and to 2 to enable everything")
+ set(FOONATHAN_MEMORY_ALLOW_VIRTUAL_MEMORY_PAGE_SIZE OFF CACHE BOOL
+ "enable to provide the deprecated variable foonathan::memory::virtual_memory_page_size")
diff --git a/doc/options.md b/doc/options.md
index 9fc1a1e..9cf6933 100644
--- a/doc/options.md
+++ b/doc/options.md
@@ -25,6 +25,8 @@ Mode `2` has a slight runtime overhead.
* `FOONATHAN_MEMORY_DEBUG_*`: Specifies debugging options such as pointer check in `deallocate()` or filling newly allocated memory with values. They are set automatically for certain build types and cannot be overriden: All of them are enabled in `Debug` builds, the faster ones in `RelWithDebInfo` and none in `Release`. See [debugging](md_doc_debug_error.html#debugging) for a detailed description.
+* `FOONATHAN_MEMORY_ALLOW_VIRTUAL_MEMORY_PAGE_SIZE`: The variable `virtual_memory_page_size` was deprecated in 2022, with release 0.7-2. It will henceforth be removed, unless `FOONATHAN_MEMORY_ALLOW_VIRTUAL_MEMORY_PAGE_SIZE` is defined.
+
A list of all options with description is generated by calling `cmake -LH`.
## Variables and targets
diff --git a/include/foonathan/memory/virtual_memory.hpp b/include/foonathan/memory/virtual_memory.hpp
index a5d1662..972675d 100644
--- a/include/foonathan/memory/virtual_memory.hpp
+++ b/include/foonathan/memory/virtual_memory.hpp
@@ -33,12 +33,14 @@ namespace foonathan
virtual_memory_allocator_leak_checker)
} // namespace detail
+#if defined(FOONATHAN_MEMORY_ALLOW_VIRTUAL_MEMORY_PAGE_SIZE)
/// The page size of the virtual memory.
/// All virtual memory allocations must be multiple of this size.
/// It is usually 4KiB.
/// \ingroup allocator
/// \deprecated use \ref get_virtual_memory_page_size instead.
extern const std::size_t virtual_memory_page_size;
+#endif
/// \returns the page size of the virtual memory.
/// All virtual memory allocations must be multiple of this size.
@@ -48,7 +50,7 @@ namespace foonathan
/// Reserves virtual memory.
/// \effects Reserves the given number of pages.
- /// Each page is \ref virtual_memory_page_size big.
+ /// Each page is \ref get_virtual_memory_page_size big.
/// \returns The address of the first reserved page,
/// or \c nullptr in case of error.
/// \note The memory may not be used, it must first be commited.
@@ -111,7 +113,7 @@ namespace foonathan
/// \returns The maximum node size by returning the maximum value.
std::size_t max_node_size() const noexcept;
- /// \returns The maximum alignment which is the same as the \ref virtual_memory_page_size.
+ /// \returns The maximum alignment which is the same as the \ref get_virtual_memory_page_size.
std::size_t max_alignment() const noexcept;
};
@@ -131,7 +133,7 @@ namespace foonathan
public:
/// \effects Creates it giving it the block size and the total number of blocks it can allocate.
/// It reserves enough virtual memory for block_size * no_blocks.
- /// \requires \c block_size must be non-zero and a multiple of the \ref virtual_memory_page_size.
+ /// \requires \c block_size must be non-zero and a multiple of the \ref get_virtual_memory_page_size.
/// \c no_blocks must be bigger than \c 1.
/// \throws \ref out_of_memory if it cannot reserve the virtual memory.
explicit virtual_block_allocator(std::size_t block_size, std::size_t no_blocks);
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e736ae5..c54aacb 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -90,6 +90,11 @@ target_compile_definitions(foonathan_memory PUBLIC
FOONATHAN_MEMORY_VERSION_MAJOR=$CACHE{FOONATHAN_MEMORY_VERSION_MAJOR}
FOONATHAN_MEMORY_VERSION_MINOR=$CACHE{FOONATHAN_MEMORY_VERSION_MINOR}
FOONATHAN_MEMORY_VERSION_PATCH=$CACHE{FOONATHAN_MEMORY_VERSION_PATCH})
+if(FOONATHAN_MEMORY_ALLOW_VIRTUAL_MEMORY_PAGE_SIZE)
+ target_compile_definitions(foonathan_memory PUBLIC
+ FOONATHAN_MEMORY_ALLOW_VIRTUAL_MEMORY_PAGE_SIZE=1)
+endif()
+
if(NOT MSVC)
target_compile_features(foonathan_memory PUBLIC cxx_constexpr)
endif()
diff --git a/src/virtual_memory.cpp b/src/virtual_memory.cpp
index 7c8ca00..0aba09d 100644
--- a/src/virtual_memory.cpp
+++ b/src/virtual_memory.cpp
@@ -31,15 +31,25 @@ namespace
}
} // namespace
-const std::size_t foonathan::memory::virtual_memory_page_size = get_page_size();
+std::size_t foonathan::memory::get_virtual_memory_page_size() noexcept
+{
+ static const std::size_t page_size = get_page_size();
+ return page_size;
+}
+
+#if defined(FOONATHAN_MEMORY_ALLOW_VIRTUAL_MEMORY_PAGE_SIZE)
+const std::size_t foonathan::memory::virtual_memory_page_size =
+ foonathan::memory::get_virtual_memory_page_size();
+#endif
void* foonathan::memory::virtual_memory_reserve(std::size_t no_pages) noexcept
{
auto pages =
#if (_MSC_VER <= 1900) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
- VirtualAlloc(nullptr, no_pages * virtual_memory_page_size, MEM_RESERVE, PAGE_READWRITE);
+ VirtualAlloc(nullptr, no_pages * get_virtual_memory_page_size(), MEM_RESERVE,
+ PAGE_READWRITE);
#else
- VirtualAllocFromApp(nullptr, no_pages * virtual_memory_page_size, MEM_RESERVE,
+ VirtualAllocFromApp(nullptr, no_pages * get_virtual_memory_page_size(), MEM_RESERVE,
PAGE_READWRITE);
#endif
return pages;
@@ -56,9 +66,9 @@ void* foonathan::memory::virtual_memory_commit(void* memory, std::size_t no_page
{
auto region =
#if (_MSC_VER <= 1900) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
- VirtualAlloc(memory, no_pages * virtual_memory_page_size, MEM_COMMIT, PAGE_READWRITE);
+ VirtualAlloc(memory, no_pages * get_virtual_memory_page_size(), MEM_COMMIT, PAGE_READWRITE);
#else
- VirtualAllocFromApp(memory, no_pages * virtual_memory_page_size, MEM_COMMIT,
+ VirtualAllocFromApp(memory, no_pages * get_virtual_memory_page_size(), MEM_COMMIT,
PAGE_READWRITE);
#endif
if (!region)
@@ -69,7 +79,7 @@ void* foonathan::memory::virtual_memory_commit(void* memory, std::size_t no_page
void foonathan::memory::virtual_memory_decommit(void* memory, std::size_t no_pages) noexcept
{
- auto result = VirtualFree(memory, no_pages * virtual_memory_page_size, MEM_DECOMMIT);
+ auto result = VirtualFree(memory, no_pages * get_virtual_memory_page_size(), MEM_DECOMMIT);
FOONATHAN_MEMORY_ASSERT_MSG(result, "cannot decommit memory");
(void)result;
}
@@ -78,13 +88,21 @@ void foonathan::memory::virtual_memory_decommit(void* memory, std::size_t no_pag
#include
#include
+std::size_t foonathan::memory::get_virtual_memory_page_size() noexcept
+{
#if defined(PAGESIZE)
-const std::size_t foonathan::memory::virtual_memory_page_size = PAGESIZE;
+ return PAGESIZE;
#elif defined(PAGE_SIZE)
-const std::size_t foonathan::memory::virtual_memory_page_size = PAGE_SIZE;
+ return PAGE_SIZE;
#else
+ static const std::size_t page_size = static_cast(sysconf(_SC_PAGESIZE));
+ return page_size;
+#endif
+}
+
+#if defined(FOONATHAN_MEMORY_ALLOW_VIRTUAL_MEMORY_PAGE_SIZE)
const std::size_t foonathan::memory::virtual_memory_page_size =
- static_cast(sysconf(_SC_PAGESIZE));
+ foonathan::memory::get_virtual_memory_page_size();
#endif
#ifndef MAP_ANONYMOUS
@@ -93,21 +111,21 @@ const std::size_t foonathan::memory::virtual_memory_page_size =
void* foonathan::memory::virtual_memory_reserve(std::size_t no_pages) noexcept
{
- auto pages = mmap(nullptr, no_pages * virtual_memory_page_size, PROT_NONE,
+ auto pages = mmap(nullptr, no_pages * get_virtual_memory_page_size(), PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
return pages == MAP_FAILED ? nullptr : pages;
}
void foonathan::memory::virtual_memory_release(void* pages, std::size_t no_pages) noexcept
{
- auto result = munmap(pages, no_pages * virtual_memory_page_size);
+ auto result = munmap(pages, no_pages * get_virtual_memory_page_size());
FOONATHAN_MEMORY_ASSERT_MSG(result == 0, "cannot release pages");
(void)result;
}
void* foonathan::memory::virtual_memory_commit(void* memory, std::size_t no_pages) noexcept
{
- auto size = no_pages * virtual_memory_page_size;
+ auto size = no_pages * get_virtual_memory_page_size();
auto result = mprotect(memory, size, PROT_WRITE | PROT_READ);
if (result != 0)
return nullptr;
@@ -124,7 +142,7 @@ void* foonathan::memory::virtual_memory_commit(void* memory, std::size_t no_page
void foonathan::memory::virtual_memory_decommit(void* memory, std::size_t no_pages) noexcept
{
- auto size = no_pages * virtual_memory_page_size;
+ auto size = no_pages * get_virtual_memory_page_size();
// advise that the memory won't be needed anymore
#if defined(MADV_FREE)
madvise(memory, size, MADV_FREE);
@@ -142,17 +160,13 @@ void foonathan::memory::virtual_memory_decommit(void* memory, std::size_t no_pag
#warning "virtual memory functions not available on your platform, define your own"
#endif
-std::size_t foonathan::memory::get_virtual_memory_page_size() noexcept
-{
- return virtual_memory_page_size;
-}
-
namespace
{
std::size_t calc_no_pages(std::size_t size) noexcept
{
- auto div = size / virtual_memory_page_size;
- auto rest = size % virtual_memory_page_size;
+ auto const page_size = get_virtual_memory_page_size();
+ auto div = size / page_size;
+ auto rest = size % page_size;
return div + (rest != 0u) + (detail::debug_fence_size ? 2u : 1u);
}
@@ -165,15 +179,15 @@ void* virtual_memory_allocator::allocate_node(std::size_t size, std::size_t)
if (!pages || !virtual_memory_commit(pages, no_pages))
FOONATHAN_THROW(
out_of_memory({FOONATHAN_MEMORY_LOG_PREFIX "::virtual_memory_allocator", nullptr},
- no_pages * virtual_memory_page_size));
+ no_pages * get_virtual_memory_page_size()));
on_allocate(size);
- return detail::debug_fill_new(pages, size, virtual_memory_page_size);
+ return detail::debug_fill_new(pages, size, get_virtual_memory_page_size());
}
void virtual_memory_allocator::deallocate_node(void* node, std::size_t size, std::size_t) noexcept
{
- auto pages = detail::debug_fill_free(node, size, virtual_memory_page_size);
+ auto pages = detail::debug_fill_free(node, size, get_virtual_memory_page_size());
on_deallocate(size);
@@ -189,7 +203,7 @@ std::size_t virtual_memory_allocator::max_node_size() const noexcept
std::size_t virtual_memory_allocator::max_alignment() const noexcept
{
- return virtual_memory_page_size;
+ return get_virtual_memory_page_size();
}
#if FOONATHAN_MEMORY_EXTERN_TEMPLATE
@@ -199,10 +213,11 @@ template class foonathan::memory::allocator_traits;
virtual_block_allocator::virtual_block_allocator(std::size_t block_size, std::size_t no_blocks)
: block_size_(block_size)
{
- FOONATHAN_MEMORY_ASSERT(block_size % virtual_memory_page_size == 0u);
+ auto const page_size = get_virtual_memory_page_size();
+ FOONATHAN_MEMORY_ASSERT(block_size % page_size == 0u);
FOONATHAN_MEMORY_ASSERT(no_blocks > 0);
auto total_size = block_size_ * no_blocks;
- auto no_pages = total_size / virtual_memory_page_size;
+ auto no_pages = total_size / page_size;
cur_ = static_cast(virtual_memory_reserve(no_pages));
if (!cur_)
@@ -212,14 +227,15 @@ virtual_block_allocator::virtual_block_allocator(std::size_t block_size, std::si
virtual_block_allocator::~virtual_block_allocator() noexcept
{
- virtual_memory_release(cur_, static_cast(end_ - cur_) / virtual_memory_page_size);
+ virtual_memory_release(cur_,
+ static_cast(end_ - cur_) / get_virtual_memory_page_size());
}
memory_block virtual_block_allocator::allocate_block()
{
if (std::size_t(end_ - cur_) < block_size_)
FOONATHAN_THROW(out_of_fixed_memory(info(), block_size_));
- auto mem = virtual_memory_commit(cur_, block_size_ / virtual_memory_page_size);
+ auto mem = virtual_memory_commit(cur_, block_size_ / get_virtual_memory_page_size());
if (!mem)
FOONATHAN_THROW(out_of_fixed_memory(info(), block_size_));
cur_ += block_size_;
@@ -232,7 +248,7 @@ void virtual_block_allocator::deallocate_block(memory_block block) noexcept
{ return static_cast(block.memory) == cur_ - block_size_; },
info(), block.memory);
cur_ -= block_size_;
- virtual_memory_decommit(cur_, block_size_ / virtual_memory_page_size);
+ virtual_memory_decommit(cur_, block_size_ / get_virtual_memory_page_size());
}
allocator_info virtual_block_allocator::info() noexcept
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 787dc61..808dbe4 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -35,7 +35,8 @@ set(tests
memory_resource_adapter.cpp
memory_stack.cpp
segregator.cpp
- smart_ptr.cpp)
+ smart_ptr.cpp
+ virtual_memory.cpp)
add_executable(foonathan_memory_test ${tests})
target_link_libraries(foonathan_memory_test PRIVATE foonathan_memory doctest::doctest)
diff --git a/test/virtual_memory.cpp b/test/virtual_memory.cpp
new file mode 100644
index 0000000..c0d4d76
--- /dev/null
+++ b/test/virtual_memory.cpp
@@ -0,0 +1,29 @@
+// Copyright (C) 2015-2025 Jonathan Müller and foonathan/memory contributors
+// SPDX-License-Identifier: Zlib
+
+// tests all possible default allocator classes
+
+#include "virtual_memory.hpp"
+
+#include
+
+namespace
+{
+
+ using namespace foonathan::memory;
+
+ static void* pages = virtual_memory_reserve(10);
+
+ TEST_CASE("can use virtual_memory during static initialization")
+ {
+ REQUIRE(pages != nullptr);
+
+ virtual_memory_release(pages, 10);
+ pages = nullptr;
+
+#if defined(FOONATHAN_MEMORY_ALLOW_VIRTUAL_MEMORY_PAGE_SIZE)
+ CHECK(virtual_memory_page_size == get_virtual_memory_page_size());
+#endif
+ }
+
+} // namespace