CyberEngineMkIII
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
CYBWin32VirtualMemory.cpp
1 #include "CYB.hpp"
2 
4  Win32::SYSTEM_INFO Info;
5  Core().FModuleManager.Call<Modules::Kernel32::GetSystemInfo>(&Info);
6  return Info.dwPageSize;
7 }
8 
9 void* CYB::Platform::System::Implementation::VirtualMemory::PageAlignedUpperBound(void* AMemory, const unsigned int APageSize) noexcept {
10  if ((reinterpret_cast<unsigned long long>(AMemory) % APageSize) == 0)
11  return AMemory;
12  return reinterpret_cast<void*>(reinterpret_cast<unsigned long long>(AMemory) + (APageSize - (reinterpret_cast<unsigned long long>(AMemory) % APageSize)));
13 }
14 
15 void* CYB::Platform::System::VirtualMemory::InitReservation(const unsigned long long ANumBytes) {
16  if (ANumBytes >= 1024) {
17  void* const Result(Core().FModuleManager.Call<Modules::Kernel32::VirtualAlloc>(nullptr, ANumBytes, Win32::DWORD(MEM_RESERVE), Win32::DWORD(PAGE_NOACCESS)));
18  if (Result != nullptr)
19  return Result;
20  }
22 }
23 
25  API::Assert::NotEqual<Win32::BOOL>(Core().FModuleManager.Call<Modules::Kernel32::VirtualFree>(FReservation, 0U, Win32::DWORD(MEM_RELEASE)), FALSE);
26 }
27 
28 void CYB::Platform::System::VirtualMemory::Commit(const unsigned long long ANumBytes) {
29  if (ANumBytes > FCommitSize) {
30  if (ANumBytes <= FReservationSize) {
31  bool ThrowOccurred(false);
32  try {
33  Access(AccessLevel::READ_WRITE);
34  }
35  catch (Exception::Internal AException) {
36  API::Assert::Equal<unsigned int>(AException.FErrorCode, Exception::Internal::MEMORY_PROTECT_FAILURE);
37  ThrowOccurred = true;
38  }
39  if (ThrowOccurred)
41  const void* const Result(Core().FModuleManager.Call<Modules::Kernel32::VirtualAlloc>(FReservation, ANumBytes, Win32::DWORD(MEM_COMMIT), Win32::DWORD(PAGE_READWRITE)));
42  if (Result == nullptr)
44  FCommitSize = ANumBytes;
45  }
46  else
48  }
49 }
50 
52  Win32::MEMORY_BASIC_INFORMATION Info;
53  if (Core().FModuleManager.Call<Modules::Kernel32::VirtualQuery>(FReservation, &Info, sizeof(Win32::MEMORY_BASIC_INFORMATION)) == 0)
55 
56  if (Info.State == MEM_COMMIT) {
57  Win32::DWORD Last;
58  //for some reason we can't use the base of the allocation when protecting :/
59  if (Core().FModuleManager.Call<Modules::Kernel32::VirtualProtect>(FReservation, Info.RegionSize, static_cast<Win32::DWORD>(
60  AAccessLevel == AccessLevel::READ_WRITE ?
61  PAGE_READWRITE :
62  (AAccessLevel == AccessLevel::NONE ?
63  PAGE_NOACCESS : PAGE_READONLY)),
64  &Last) == FALSE)
66  }
67 }
68 
69 void CYB::Platform::System::VirtualMemory::Discard(void* const AMemory, const unsigned long long ANumBytes) noexcept {
70  API::Assert::LessThanOrEqual(static_cast<byte*>(FReservation), static_cast<byte*>(AMemory));
71  API::Assert::LessThanOrEqual(static_cast<byte*>(AMemory), static_cast<byte*>(FReservation) + FCommitSize);
72  API::Assert::LessThanOrEqual(static_cast<byte*>(AMemory) + ANumBytes, static_cast<byte*>(FReservation) + FCommitSize);
73 
74  if (!Core().FModuleManager.Loaded<Modules::Kernel32Extended::DiscardVirtualMemory>())
75  return;
76 
77  const auto PageSize(Implementation::VirtualMemory::SystemPageSize());
78  if (ANumBytes < PageSize)
79  return;
80 
81  auto const AlignedMemory(Implementation::VirtualMemory::PageAlignedUpperBound(AMemory, PageSize));
82  const auto Difference(reinterpret_cast<unsigned long long>(AlignedMemory) - reinterpret_cast<unsigned long long>(AMemory));
83 
84  //Difference is inherently < PageSize
85 
86  const auto BytesAvailableToDiscard(ANumBytes - Difference);
87 
88  if (BytesAvailableToDiscard < PageSize)
89  return;
90 
91  const auto TrueDiscardSize(BytesAvailableToDiscard - (BytesAvailableToDiscard % PageSize));
92 
93  Core().FModuleManager.Call<Modules::Kernel32Extended::DiscardVirtualMemory>(AlignedMemory, TrueDiscardSize);
94 }
static void * PageAlignedUpperBound(void *const AMemory, const unsigned int APageSize) noexcept
Get the base address of a page on or after a given address.
void Commit(const unsigned long long ANumBytes)
Commit some amount of memory from a reserved address space. On return, the memory will be usable...
Memory protection could not be set.
Definition: Exception.hpp:109
Platform::Modules::Manager FModuleManager
Loads and contains required modules.
Definition: CYBCore.hpp:20
void Discard(void *const AMemory, const unsigned long long ANumBytes) noexcept
Designate an area of memory as not needed for the time being, improving performance. It may be reaccessed at any time, however, it should be assumed to be filled with random data upon doing so.
~VirtualMemory()
Release a reservation. All memory that was used in entire reserved address space will be lost...
const unsigned int FErrorCode
The assigned error code.
Definition: Exception.hpp:18
static void * InitReservation(const unsigned long long ANumBytes)
Reserve some amount of address space for future allocation.
Memory could not be commited from a reservation.
Definition: Exception.hpp:108
Precompiled header for inter-engine operations.
static unsigned int SystemPageSize(void) noexcept
Retrieve the system page size.
Engine::Core & Core(void) noexcept
Retrieve the Core singleton.
Definition: CYBCore.cpp:69
void Access(const AccessLevel AAccess)
Set the memory protection on a reservation. Does nothing without a previous commit.
static void LessThanOrEqual(const AType &ALHS, const AType &ARHS) noexcept
Less than or equal assertion function. May not be evaluated.
Exceptions that are thrown internally in the engine that the should never see, these are a superset o...
Definition: Exception.hpp:104
auto Call(AArgs &&...AArguments)
Call a loaded function.