/* 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