#[cfg(miri)]
use core::alloc::{GlobalAlloc, Layout};
#[cfg(not(miri))]
use core::ffi::c_void;
#[cfg(miri)]
use std::alloc::System;
#[cfg(miri)]
extern crate std;
#[cfg(not(miri))]
const MEM_COMMIT: u32 = 0x00001000;
#[cfg(not(miri))]
const MEM_RESERVE: u32 = 0x00002000;
#[cfg(not(miri))]
const MEM_RELEASE: u32 = 0x00008000;
#[cfg(not(miri))]
const MEM_DECOMMIT: u32 = 0x00004000;
#[cfg(not(miri))]
const MEM_RESET: u32 = 0x00080000;
#[cfg(not(miri))]
const PAGE_READWRITE: u32 = 0x04;
#[cfg(not(miri))]
const PAGE_NOACCESS: u32 = 0x01;
#[cfg(not(miri))]
unsafe extern "system" {
fn VirtualAlloc(
lpAddress: *const c_void,
dwSize: usize,
flAllocationType: u32,
flProtect: u32,
) -> *mut c_void;
fn VirtualFree(lpAddress: *mut c_void, dwSize: usize, dwFreeType: u32) -> i32;
fn VirtualProtect(
lpAddress: *mut c_void,
dwSize: usize,
flNewProtect: u32,
lpflOldProtect: *mut u32,
) -> i32;
}
#[inline(always)]
fn vm_args_valid(ptr: *mut u8, size: usize) -> bool {
if ptr.is_null() || size == 0 {
return false;
}
!cfg!(miri)
}
pub struct WindowsBackend;
impl mnemosyne_core::MemoryBackend for WindowsBackend {
const SUPPORTS_PAGE_RESET: bool = !cfg!(miri);
const SUPPORTS_MAKE_GUARD: bool = !cfg!(miri);
const SUPPORTS_DECOMMIT: bool = !cfg!(miri);
unsafe fn allocate(size: usize) -> *mut u8 {
#[cfg(miri)]
{
const OS_PAGE_ALIGN: usize = 4096;
let layout = unsafe { Layout::from_size_align_unchecked(size, OS_PAGE_ALIGN) };
return unsafe { System.alloc(layout) };
}
#[cfg(not(miri))]
{
let ptr = unsafe {
VirtualAlloc(
core::ptr::null(),
size,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE,
)
};
if ptr.is_null() {
core::ptr::null_mut()
} else {
ptr as *mut u8
}
}
}
unsafe fn deallocate(ptr: *mut u8, _size: usize) -> bool {
if ptr.is_null() {
return false;
}
#[cfg(miri)]
{
const OS_PAGE_ALIGN: usize = 4096;
let layout = unsafe { Layout::from_size_align_unchecked(_size, OS_PAGE_ALIGN) };
unsafe { System.dealloc(ptr, layout) };
return true;
}
#[cfg(not(miri))]
{
let res = unsafe { VirtualFree(ptr as *mut c_void, 0, MEM_RELEASE) };
debug_assert_ne!(res, 0, "VirtualFree failed");
res != 0
}
}
unsafe fn page_reset(ptr: *mut u8, size: usize) -> bool {
if !vm_args_valid(ptr, size) {
return false;
}
#[cfg(not(miri))]
{
let result =
unsafe { VirtualAlloc(ptr as *const c_void, size, MEM_RESET, PAGE_READWRITE) };
!result.is_null()
}
#[cfg(miri)]
{
false
}
}
unsafe fn decommit(ptr: *mut u8, size: usize) -> bool {
if !vm_args_valid(ptr, size) {
return false;
}
#[cfg(not(miri))]
{
let res = unsafe { VirtualFree(ptr as *mut c_void, size, MEM_DECOMMIT) };
res != 0
}
#[cfg(miri)]
{
false
}
}
unsafe fn make_guard(ptr: *mut u8, size: usize) -> bool {
if !vm_args_valid(ptr, size) {
return false;
}
#[cfg(not(miri))]
{
let mut old_protect: u32 = 0;
let res = unsafe {
VirtualProtect(
ptr as *mut c_void,
size,
PAGE_NOACCESS,
&mut old_protect as *mut u32,
)
};
res != 0
}
#[cfg(miri)]
{
false
}
}
}