/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see .
*/
#include "PrecompiledHeader.h"
#include "PageFaultSource.h"
#include "EventSource.inl"
#include "MemsetFast.inl"
template class EventSource< IEventListener_PageFault >;
SrcType_PageFault* Source_PageFault = NULL;
EventListener_PageFault::EventListener_PageFault()
{
pxAssume(Source_PageFault);
Source_PageFault->Add( *this );
}
EventListener_PageFault::~EventListener_PageFault() throw()
{
if (Source_PageFault)
Source_PageFault->Remove( *this );
}
void SrcType_PageFault::Dispatch( const PageFaultInfo& params )
{
m_handled = false;
_parent::Dispatch( params );
}
void SrcType_PageFault::_DispatchRaw( ListenerIterator iter, const ListenerIterator& iend, const PageFaultInfo& evt )
{
do {
(*iter)->DispatchEvent( evt, m_handled );
} while( (++iter != iend) && !m_handled );
}
// --------------------------------------------------------------------------------------
// BaseVirtualMemoryReserve (implementations)
// --------------------------------------------------------------------------------------
BaseVirtualMemoryReserve::BaseVirtualMemoryReserve( const wxString& name )
: Name( name )
{
m_commited = 0;
m_reserved = 0;
m_baseptr = NULL;
m_block_size = __pagesize;
m_prot_mode = PageAccess_None();
}
// Parameters:
// upper_bounds - criteria that must be met for the allocation to be valid.
// If the OS refuses to allocate the memory below the specified address, the
// object will fail to initialize and an exception will be thrown.
void* BaseVirtualMemoryReserve::Reserve( uint size, uptr base, uptr upper_bounds )
{
if (!pxAssertDev( m_baseptr == NULL, "(VirtualMemoryReserve) Invalid object state; object has already been reserved." ))
return m_baseptr;
m_reserved = (size + __pagesize-4) / __pagesize;
uptr reserved_bytes = m_reserved * __pagesize;
m_baseptr = (void*)HostSys::MmapReserve(base, reserved_bytes);
if (!m_baseptr && (upper_bounds != 0 && (((uptr)m_baseptr + reserved_bytes) > upper_bounds)))
{
if (base)
{
DevCon.Warning( L"%s: address 0x%08x is unavailable; trying OS-selected address instead.", Name.c_str(), base );
// Let's try again at an OS-picked memory area, and then hope it meets needed
// boundschecking criteria below.
SafeSysMunmap( m_baseptr, reserved_bytes );
m_baseptr = (void*)HostSys::MmapReserve( NULL, reserved_bytes );
}
if ((upper_bounds != 0) && (((uptr)m_baseptr + reserved_bytes) > upper_bounds))
{
SafeSysMunmap( m_baseptr, reserved_bytes );
// returns null, caller should throw an exception or handle appropriately.
}
}
if (!m_baseptr) return NULL;
DevCon.WriteLn( Color_Blue, L"%-32s @ 0x%08X -> 0x%08X [%umb]", Name.c_str(),
m_baseptr, (uptr)m_baseptr+reserved_bytes, reserved_bytes / _1mb);
/*if (m_def_commit)
{
const uint camt = m_def_commit * __pagesize;
HostSys::MmapCommit(m_baseptr, camt);
HostSys::MemProtect(m_baseptr, camt, m_prot_mode);
u8* init = (u8*)m_baseptr;
u8* endpos = init + camt;
for( ; init= m_reserved) return;
try {
if (!m_commited && m_def_commit)
{
const uint camt = m_def_commit * __pagesize;
// first block being committed! Commit the default requested
// amount if its different from the blocksize.
HostSys::MmapCommit(m_baseptr, camt);
HostSys::MemProtect(m_baseptr, camt, m_prot_mode);
u8* init = (u8*)m_baseptr;
u8* endpos = init + camt;
for( ; init