8031dabf83
Reviewed-by: aboldtch, tschatzl
189 lines
5.3 KiB
C++
189 lines
5.3 KiB
C++
/*
|
|
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
#include "precompiled.hpp"
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
#include "gc/z/zAddress.inline.hpp"
|
|
#include "gc/z/zGlobals.hpp"
|
|
#include "gc/z/zList.inline.hpp"
|
|
#include "gc/z/zMemory.inline.hpp"
|
|
#include "gc/z/zSyscall_windows.hpp"
|
|
#include "gc/z/zVirtualMemory.hpp"
|
|
#include "runtime/os.hpp"
|
|
#include "unittest.hpp"
|
|
|
|
using namespace testing;
|
|
|
|
#define EXPECT_ALLOC_OK(offset) EXPECT_NE(offset, zoffset(UINTPTR_MAX))
|
|
|
|
class ZMapperTest : public Test {
|
|
private:
|
|
static constexpr size_t ZMapperTestReservationSize = 32 * M;
|
|
|
|
static bool _initialized;
|
|
static ZMemoryManager* _va;
|
|
|
|
ZVirtualMemoryManager* _vmm;
|
|
|
|
public:
|
|
bool reserve_for_test() {
|
|
// Initialize platform specific parts before reserving address space
|
|
_vmm->pd_initialize_before_reserve();
|
|
|
|
// Reserve address space
|
|
if (!_vmm->pd_reserve(ZOffset::address_unsafe(zoffset(0)), ZMapperTestReservationSize)) {
|
|
return false;
|
|
}
|
|
|
|
// Make the address range free before setting up callbacks below
|
|
_va->free(zoffset(0), ZMapperTestReservationSize);
|
|
|
|
// Initialize platform specific parts after reserving address space
|
|
_vmm->pd_initialize_after_reserve();
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual void SetUp() {
|
|
// Only run test on supported Windows versions
|
|
if (!ZSyscall::is_supported()) {
|
|
GTEST_SKIP() << "Requires Windows version 1803 or later";
|
|
return;
|
|
}
|
|
|
|
ZSyscall::initialize();
|
|
ZGlobalsPointers::initialize();
|
|
|
|
// Fake a ZVirtualMemoryManager
|
|
_vmm = (ZVirtualMemoryManager*)os::malloc(sizeof(ZVirtualMemoryManager), mtTest);
|
|
|
|
// Construct its internal ZMemoryManager
|
|
_va = new (&_vmm->_manager) ZMemoryManager();
|
|
|
|
// Reserve address space for the test
|
|
if (!reserve_for_test()) {
|
|
GTEST_SKIP() << "Failed to reserve address space";
|
|
return;
|
|
}
|
|
|
|
_initialized = true;
|
|
}
|
|
|
|
virtual void TearDown() {
|
|
if (!ZSyscall::is_supported()) {
|
|
// Test skipped, nothing to cleanup
|
|
return;
|
|
}
|
|
|
|
if (_initialized) {
|
|
_vmm->pd_unreserve(ZOffset::address_unsafe(zoffset(0)), 0);
|
|
}
|
|
os::free(_vmm);
|
|
}
|
|
|
|
static void test_alloc_low_address() {
|
|
// Verify that we get placeholder for first granule
|
|
zoffset bottom = _va->alloc_low_address(ZGranuleSize);
|
|
EXPECT_ALLOC_OK(bottom);
|
|
|
|
_va->free(bottom, ZGranuleSize);
|
|
|
|
// Alloc something larger than a granule and free it
|
|
bottom = _va->alloc_low_address(ZGranuleSize * 3);
|
|
EXPECT_ALLOC_OK(bottom);
|
|
|
|
_va->free(bottom, ZGranuleSize * 3);
|
|
|
|
// Free with more memory allocated
|
|
bottom = _va->alloc_low_address(ZGranuleSize);
|
|
EXPECT_ALLOC_OK(bottom);
|
|
|
|
zoffset next = _va->alloc_low_address(ZGranuleSize);
|
|
EXPECT_ALLOC_OK(next);
|
|
|
|
_va->free(bottom, ZGranuleSize);
|
|
_va->free(next, ZGranuleSize);
|
|
}
|
|
|
|
static void test_alloc_high_address() {
|
|
// Verify that we get placeholder for last granule
|
|
zoffset high = _va->alloc_high_address(ZGranuleSize);
|
|
EXPECT_ALLOC_OK(high);
|
|
|
|
zoffset prev = _va->alloc_high_address(ZGranuleSize);
|
|
EXPECT_ALLOC_OK(prev);
|
|
|
|
_va->free(high, ZGranuleSize);
|
|
_va->free(prev, ZGranuleSize);
|
|
|
|
// Alloc something larger than a granule and return it
|
|
high = _va->alloc_high_address(ZGranuleSize * 2);
|
|
EXPECT_ALLOC_OK(high);
|
|
|
|
_va->free(high, ZGranuleSize * 2);
|
|
}
|
|
|
|
static void test_alloc_whole_area() {
|
|
// Alloc the whole reservation
|
|
zoffset bottom = _va->alloc_low_address(ZMapperTestReservationSize);
|
|
EXPECT_ALLOC_OK(bottom);
|
|
|
|
// Free two chunks and then allocate them again
|
|
_va->free(bottom, ZGranuleSize * 4);
|
|
_va->free(bottom + ZGranuleSize * 6, ZGranuleSize * 6);
|
|
|
|
zoffset offset = _va->alloc_low_address(ZGranuleSize * 4);
|
|
EXPECT_ALLOC_OK(offset);
|
|
|
|
offset = _va->alloc_low_address(ZGranuleSize * 6);
|
|
EXPECT_ALLOC_OK(offset);
|
|
|
|
// Now free it all, and verify it can be re-allocated
|
|
_va->free(bottom, ZMapperTestReservationSize);
|
|
|
|
bottom = _va->alloc_low_address(ZMapperTestReservationSize);
|
|
EXPECT_ALLOC_OK(bottom);
|
|
|
|
_va->free(bottom, ZMapperTestReservationSize);
|
|
}
|
|
};
|
|
|
|
bool ZMapperTest::_initialized = false;
|
|
ZMemoryManager* ZMapperTest::_va = nullptr;
|
|
|
|
TEST_VM_F(ZMapperTest, test_alloc_low_address) {
|
|
test_alloc_low_address();
|
|
}
|
|
|
|
TEST_VM_F(ZMapperTest, test_alloc_high_address) {
|
|
test_alloc_high_address();
|
|
}
|
|
|
|
TEST_VM_F(ZMapperTest, test_alloc_whole_area) {
|
|
test_alloc_whole_area();
|
|
}
|
|
|
|
#endif // _WINDOWS
|