/[pcsx2_0.9.7]/trunk/common/src/Utilities/Windows/WinHostSys.cpp
ViewVC logotype

Diff of /trunk/common/src/Utilities/Windows/WinHostSys.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

--- trunk/common/src/Utilities/Windows/WinHostSys.cpp	2010/12/23 11:48:33	279
+++ trunk/common/src/Utilities/Windows/WinHostSys.cpp	2010/12/23 12:02:12	280
@@ -15,48 +15,125 @@
 
 #include "PrecompiledHeader.h"
 #include "Utilities/RedtapeWindows.h"
+#include "PageFaultSource.h"
+
 #include <winnt.h>
 
-namespace HostSys
+
+int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps )
+{
+	if( eps->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION )
+		return EXCEPTION_CONTINUE_SEARCH;
+
+	Source_PageFault->Dispatch( PageFaultInfo( (uptr)eps->ExceptionRecord->ExceptionInformation[1] ) );
+	return Source_PageFault->WasHandled() ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
+}
+
+void _platform_InstallSignalHandler()
 {
-	void *Mmap(uptr base, u32 size)
+	// NOP on Win32 systems -- we use __try{} __except{} instead.
+}
+
+
+static DWORD ConvertToWinApi( const PageProtectionMode& mode )
+{
+	DWORD winmode = PAGE_NOACCESS;
+
+	// Windows has some really bizarre memory protection enumeration that uses bitwise
+	// numbering (like flags) but is in fact not a flag value.  *Someone* from the early
+	// microsoft days wasn't a very good coder, me thinks.  --air
+
+	if (mode.CanExecute())
 	{
-		return VirtualAlloc((void*)base, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+		winmode = mode.CanWrite() ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
 	}
+	else if (mode.CanRead())
+	{
+		winmode = mode.CanWrite() ? PAGE_READWRITE : PAGE_READONLY;
+	}
+
+	return winmode;
+}
 
-	void Munmap(uptr base, u32 size)
+void* HostSys::MmapReservePtr(void* base, size_t size)
+{
+	return VirtualAlloc(base, size, MEM_RESERVE, PAGE_NOACCESS);
+}
+
+bool HostSys::MmapCommitPtr(void* base, size_t size, const PageProtectionMode& mode)
+{
+	void* result = VirtualAlloc(base, size, MEM_COMMIT, ConvertToWinApi(mode));
+	if (result) return true;
+
+	const DWORD errcode = GetLastError();
+	if (errcode == ERROR_COMMITMENT_MINIMUM)
+	{
+		Console.Warning("(MmapCommit) Received windows error %u {Virtual Memory Minimum Too Low}.", ERROR_COMMITMENT_MINIMUM);
+		Sleep(1000);	// Cut windows some time to rework its memory...
+	}
+	else if (errcode != ERROR_NOT_ENOUGH_MEMORY && errcode != ERROR_OUTOFMEMORY)
 	{
-		if( base == NULL ) return;
-		VirtualFree((void*)base, size, MEM_DECOMMIT);
-		VirtualFree((void*)base, 0, MEM_RELEASE);
+		pxFailDev(L"VirtualAlloc COMMIT failed: " + Exception::WinApiError().GetMsgFromWindows());
+		return false;
 	}
 
-	void MemProtect( void* baseaddr, size_t size, PageProtectionMode mode, bool allowExecution )
+	if (!pxDoOutOfMemory) return false;
+	pxDoOutOfMemory(size);
+	return VirtualAlloc(base, size, MEM_COMMIT, ConvertToWinApi(mode)) != NULL;
+}
+
+void HostSys::MmapResetPtr(void* base, size_t size)
+{
+	VirtualFree(base, size, MEM_DECOMMIT);
+}
+
+
+void* HostSys::MmapReserve(uptr base, size_t size)
+{
+	return MmapReservePtr((void*)base, size);
+}
+
+bool HostSys::MmapCommit(uptr base, size_t size, const PageProtectionMode& mode)
+{
+	return MmapCommitPtr( (void*)base, size, mode );
+}
+
+void HostSys::MmapReset(uptr base, size_t size)
+{
+	MmapResetPtr((void*)base, size);
+}
+
+
+void* HostSys::Mmap(uptr base, size_t size)
+{
+	return VirtualAlloc((void*)base, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+}
+
+void HostSys::Munmap(uptr base, size_t size)
+{
+	if (!base) return;
+	//VirtualFree((void*)base, size, MEM_DECOMMIT);
+	VirtualFree((void*)base, 0, MEM_RELEASE);
+}
+
+void HostSys::MemProtect( void* baseaddr, size_t size, const PageProtectionMode& mode )
+{
+	pxAssertDev( ((size & (__pagesize-1)) == 0), pxsFmt(
+		L"Memory block size must be a multiple of the target platform's page size.\n"
+		L"\tPage Size: 0x%04x (%d), Block Size: 0x%04x (%d)",
+		__pagesize, __pagesize, size, size )
+	);
+	
+	DWORD OldProtect;	// enjoy my uselessness, yo!
+	if (!VirtualProtect( baseaddr, size, ConvertToWinApi(mode), &OldProtect ))
 	{
-		pxAssertDev( ((size & (__pagesize-1)) == 0), wxsFormat(
-			L"Memory block size must be a multiple of the target platform's page size.\n"
-			L"\tPage Size: 0x%04x (%d), Block Size: 0x%04x (%d)",
-			__pagesize, __pagesize, size, size )
-		);
-
-		DWORD winmode = 0;
-
-		switch( mode )
-		{
-			case Protect_NoAccess:
-				winmode = ( allowExecution ) ? PAGE_EXECUTE : PAGE_NOACCESS;
-			break;
-
-			case Protect_ReadOnly:
-				winmode = ( allowExecution ) ? PAGE_EXECUTE_READ : PAGE_READONLY;
-			break;
-
-			case Protect_ReadWrite:
-				winmode = ( allowExecution ) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
-			break;
-		}
+		Exception::WinApiError apiError;
+		
+		apiError.SetDiagMsg(
+			pxsFmt(L"VirtualProtect failed @ 0x%08X -> 0x%08X  (mode=%s)",
+			baseaddr, (uptr)baseaddr + size, mode.ToString().c_str()
+		));
 
-		DWORD OldProtect;	// enjoy my uselessness, yo!
-		VirtualProtect( baseaddr, size, winmode, &OldProtect );
+		pxFailDev( apiError.FormatDiagnosticMessage() );
 	}
 }

 

  ViewVC Help
Powered by ViewVC 1.1.22