// Maps a block of memory for use as a recompiled code buffer, and ensures that the // allocation is below a certain memory address (specified in "bounds" parameter). // The allocated block has code execution privileges. // Returns NULL on allocation failure. u8* SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller) { u8* Mem = (u8*)HostSys::Mmap( base, size ); if( (Mem == NULL) || (bounds != 0 && (((uptr)Mem + size) > bounds)) ) { if( base ) { DbgCon.Warning( "First try failed allocating %s at address 0x%x", caller, base ); // Let's try again at an OS-picked memory area, and then hope it meets needed // boundschecking criteria below. SafeSysMunmap( Mem, size ); Mem = (u8*)HostSys::Mmap( 0, size ); } if( (bounds != 0) && (((uptr)Mem + size) > bounds) ) { DevCon.Warning( "Second try failed allocating %s, block ptr 0x%x does not meet required criteria.", caller, Mem ); SafeSysMunmap( Mem, size ); // returns NULL, caller should throw an exception. } } return Mem; }
// Notes: // * This method should be called if the object is already in an released (unreserved) state. // Subsequent calls will be ignored, and the existing reserve will be returned. // // Parameters: // size - size of the reserve, in bytes. (optional) // If not specified (or zero), then the default size specified in the constructor for the // object instance is used. // // 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* VirtualMemoryReserve::Reserve( size_t size, uptr base, uptr upper_bounds ) { if (!pxAssertDev( m_baseptr == NULL, "(VirtualMemoryReserve) Invalid object state; object has already been reserved." )) return m_baseptr; if (!size) size = m_defsize; if (!size) return NULL; m_pages_reserved = (size + __pagesize-4) / __pagesize; uptr reserved_bytes = m_pages_reserved * __pagesize; m_baseptr = (void*)HostSys::MmapReserve(base, reserved_bytes); if (!m_baseptr || (upper_bounds != 0 && (((uptr)m_baseptr + reserved_bytes) > upper_bounds))) { DevCon.Warning( L"%s: host memory @ %s -> %s is unavailable; attempting to map elsewhere...", m_name.c_str(), pxsPtr(base), pxsPtr(base + size) ); SafeSysMunmap(m_baseptr, reserved_bytes); if (base) { // Let's try again at an OS-picked memory area, and then hope it meets needed // boundschecking criteria below. m_baseptr = HostSys::MmapReserve( 0, 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; FastFormatUnicode mbkb; uint mbytes = reserved_bytes / _1mb; if (mbytes) mbkb.Write( "[%umb]", mbytes ); else mbkb.Write( "[%ukb]", reserved_bytes / 1024 ); DevCon.WriteLn( Color_Gray, L"%-32s @ %s -> %s %s", m_name.c_str(), pxsPtr(m_baseptr), pxsPtr((uptr)m_baseptr+reserved_bytes), mbkb.c_str()); return m_baseptr; }
// Free Allocated Resources void mVUclose(microVU& mVU) { safe_delete (mVU.cache_reserve); SafeSysMunmap(mVU.dispCache, mVUdispCacheSize); // Delete Programs and Block Managers for (u32 i = 0; i < (mVU.progSize / 2); i++) { if (!mVU.prog.prog[i]) continue; std::deque<microProgram*>::iterator it(mVU.prog.prog[i]->begin()); for ( ; it != mVU.prog.prog[i]->end(); ++it) { mVUdeleteProg(mVU, it[0]); } safe_delete(mVU.prog.prog[i]); } }
void VirtualMemoryReserve::Release() { SafeSysMunmap(m_baseptr, m_pages_reserved*__pagesize); }