my small contribution to MemoryBlock: build it on a tempfile instead of system pagefile. Couldnt test it because old gpgx.elf and don't know how to build?
This commit is contained in:
parent
0e9a34a074
commit
30b71d5e44
|
@ -150,40 +150,65 @@ namespace BizHawk.Emulation.Cores
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// allocate size bytes starting at a particular address
|
||||
/// Allocates a memory block as a memory-mapped file with the given size (created immediately) which can be Activated and Deactivated only at the given address.
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="size"></param>
|
||||
public MemoryBlock(ulong start, ulong size)
|
||||
{
|
||||
if (!Aligned(start))
|
||||
throw new ArgumentOutOfRangeException();
|
||||
if (size == 0)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
size = AlignUp(size);
|
||||
|
||||
_handle = Kernel32.CreateFileMapping(Kernel32.INVALID_HANDLE_VALUE, IntPtr.Zero,
|
||||
Kernel32.FileMapProtection.PageExecuteReadWrite | Kernel32.FileMapProtection.SectionCommit, (uint)(size >> 32), (uint)size, null);
|
||||
|
||||
if (_handle == IntPtr.Zero)
|
||||
throw new InvalidOperationException("CreateFileMapping() returned NULL");
|
||||
Start = start;
|
||||
End = start + size;
|
||||
Size = size;
|
||||
_pageData = new Protection[GetPage(End - 1) + 1];
|
||||
/// <param name="start">Location where this block can be Activated</param>
|
||||
/// <param name="size">Size of the block</param>
|
||||
public MemoryBlock(ulong start, ulong size)
|
||||
{
|
||||
size = 8 * 1024 * 1024 * 1024L;
|
||||
if (!Aligned(start))
|
||||
throw new ArgumentOutOfRangeException();
|
||||
if (size == 0)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
size = AlignUp(size);
|
||||
|
||||
//create a temporary file--the alternative is using the system pagefile(s)
|
||||
//some systems have disabled or too-small files and many systems have a few GBs pagefile and difficulty growing it.
|
||||
//creating a tempfile subverts the user's choice of pagefile locations, but %temp%'s location should be similarly chosen
|
||||
//Could use this as a fallback in case creation on the pagefile fails?
|
||||
var fname = BizHawk.Common.TempFileCleaner.GetTempFilename("MemoryBlock",null,false);
|
||||
IntPtr fhTemp = Kernel32.CreateFile(
|
||||
fname,
|
||||
unchecked((int)(0x80000000 | 0x40000000 | 0x20000000)), //+RWX (protections can later be added with finer granularity)
|
||||
3, //share RW
|
||||
IntPtr.Zero, //security stuff
|
||||
2, //create always
|
||||
0x04000000, //delete on close!
|
||||
IntPtr.Zero //template
|
||||
);
|
||||
|
||||
//create FileMapping around the tempfile
|
||||
//(again, protections can later be added with finer granularity)
|
||||
_handle = Kernel32.CreateFileMapping(fhTemp, IntPtr.Zero,
|
||||
Kernel32.FileMapProtection.PageExecuteReadWrite | Kernel32.FileMapProtection.SectionCommit, (uint)(size >> 32), (uint)size, null);
|
||||
|
||||
//releasing our tempfile handle, essentially yielding the handle to the FileMapping as sole owner
|
||||
new Microsoft.Win32.SafeHandles.SafeFileHandle(fhTemp, true).Dispose();
|
||||
|
||||
if (_handle == IntPtr.Zero)
|
||||
throw new InvalidOperationException("CreateFileMapping() returned NULL");
|
||||
Start = start;
|
||||
End = start + size;
|
||||
Size = size;
|
||||
_pageData = new Protection[GetPage(End - 1) + 1];
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// activate the memory block, swapping it in at the specified address
|
||||
/// activate the memory block, swapping it in at the predefined address
|
||||
/// </summary>
|
||||
public void Activate()
|
||||
{
|
||||
if (Active)
|
||||
throw new InvalidOperationException("Already active");
|
||||
if (Kernel32.MapViewOfFileEx(_handle, Kernel32.FileMapAccessType.Read | Kernel32.FileMapAccessType.Write | Kernel32.FileMapAccessType.Execute,
|
||||
0, 0, Z.UU(Size), Z.US(Start)) != Z.US(Start))
|
||||
throw new InvalidOperationException("Already active");
|
||||
|
||||
//(again, protections can later be added with finer granularity)
|
||||
IntPtr ptr = Kernel32.MapViewOfFileEx(_handle, Kernel32.FileMapAccessType.Read | Kernel32.FileMapAccessType.Write | Kernel32.FileMapAccessType.Execute,
|
||||
0, 0, Z.UU(Size), Z.US(Start));
|
||||
if (ptr != Z.US(Start))
|
||||
{
|
||||
throw new InvalidOperationException("MapViewOfFileEx() returned NULL");
|
||||
throw new InvalidOperationException("MapViewOfFileEx() returned incorrect starting address");
|
||||
}
|
||||
ProtectAll();
|
||||
Active = true;
|
||||
|
@ -197,7 +222,7 @@ namespace BizHawk.Emulation.Cores
|
|||
if (!Active)
|
||||
throw new InvalidOperationException("Not active");
|
||||
if (!Kernel32.UnmapViewOfFile(Z.US(Start)))
|
||||
throw new InvalidOperationException("UnmapViewOfFile() returned NULL");
|
||||
throw new InvalidOperationException("UnmapViewOfFile() returned false");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -438,7 +463,18 @@ namespace BizHawk.Emulation.Cores
|
|||
GUARD_Modifierflag = 0x100,
|
||||
NOCACHE_Modifierflag = 0x200,
|
||||
WRITECOMBINE_Modifierflag = 0x400
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern IntPtr CreateFile(
|
||||
string fileName,
|
||||
int desiredAccess,
|
||||
int shareMode,
|
||||
IntPtr securityAttributes,
|
||||
int creationDisposition,
|
||||
int flagsAndAttributes,
|
||||
IntPtr templateFile);
|
||||
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern IntPtr CreateFileMapping(
|
||||
|
|
Loading…
Reference in New Issue