System: Gracefully handle memory allocaion failure

This commit is contained in:
Stenzek
2024-02-25 18:20:34 +10:00
parent 9ac9fc0a1e
commit c1381cfda6
11 changed files with 92 additions and 39 deletions

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "bus.h"
@ -24,6 +24,7 @@
#include "common/align.h"
#include "common/assert.h"
#include "common/error.h"
#include "common/intrin.h"
#include "common/log.h"
#include "common/memmap.h"
@ -163,22 +164,31 @@ static constexpr size_t TOTAL_SIZE = LUT_OFFSET + LUT_SIZE;
#define FIXUP_HALFWORD_OFFSET(size, offset) ((size >= MemoryAccessSize::HalfWord) ? (offset) : ((offset) & ~1u))
#define FIXUP_HALFWORD_READ_VALUE(size, offset, value) \
((size >= MemoryAccessSize::HalfWord) ? (value) : ((value) >> (((offset)&u32(1)) * 8u)))
((size >= MemoryAccessSize::HalfWord) ? (value) : ((value) >> (((offset) & u32(1)) * 8u)))
#define FIXUP_HALFWORD_WRITE_VALUE(size, offset, value) \
((size >= MemoryAccessSize::HalfWord) ? (value) : ((value) << (((offset)&u32(1)) * 8u)))
((size >= MemoryAccessSize::HalfWord) ? (value) : ((value) << (((offset) & u32(1)) * 8u)))
#define FIXUP_WORD_OFFSET(size, offset) ((size == MemoryAccessSize::Word) ? (offset) : ((offset) & ~3u))
#define FIXUP_WORD_READ_VALUE(size, offset, value) \
((size == MemoryAccessSize::Word) ? (value) : ((value) >> (((offset)&3u) * 8)))
((size == MemoryAccessSize::Word) ? (value) : ((value) >> (((offset) & 3u) * 8)))
#define FIXUP_WORD_WRITE_VALUE(size, offset, value) \
((size == MemoryAccessSize::Word) ? (value) : ((value) << (((offset)&3u) * 8)))
((size == MemoryAccessSize::Word) ? (value) : ((value) << (((offset) & 3u) * 8)))
bool Bus::AllocateMemory()
{
s_shmem_handle = MemMap::CreateSharedMemory(MemMap::GetFileMappingName("duckstation").c_str(), MemoryMap::TOTAL_SIZE);
Error error;
s_shmem_handle =
MemMap::CreateSharedMemory(MemMap::GetFileMappingName("duckstation").c_str(), MemoryMap::TOTAL_SIZE, &error);
if (!s_shmem_handle)
{
Host::ReportErrorAsync("Error", "Failed to allocate memory");
#ifndef __linux__
error.AddSuffix("\nYou may need to close some programs to free up additional memory.");
#else
error.AddSuffix(
"\nYou may need to close some programs to free up additional memory, or increase the size of /dev/shm.");
#endif
Host::ReportFatalError("Memory Allocation Failed", error.GetDescription());
return false;
}
@ -188,7 +198,7 @@ bool Bus::AllocateMemory()
MemoryMap::RAM_SIZE, PageProtect::ReadWrite));
if (!g_ram || !g_unprotected_ram)
{
Host::ReportErrorAsync("Error", "Failed to map memory for RAM");
Host::ReportFatalError("Memory Allocation Failed", "Failed to map memory for RAM");
ReleaseMemory();
return false;
}
@ -199,7 +209,7 @@ bool Bus::AllocateMemory()
MemoryMap::BIOS_SIZE, PageProtect::ReadWrite));
if (!g_bios)
{
Host::ReportErrorAsync("Error", "Failed to map memory for BIOS");
Host::ReportFatalError("Memory Allocation Failed", "Failed to map memory for BIOS");
ReleaseMemory();
return false;
}
@ -210,7 +220,7 @@ bool Bus::AllocateMemory()
MemoryMap::LUT_SIZE, PageProtect::ReadWrite));
if (!g_memory_handlers)
{
Host::ReportErrorAsync("Error", "Failed to map memory for LUTs");
Host::ReportFatalError("Memory Allocation Failed", "Failed to map memory for LUTs");
ReleaseMemory();
return false;
}
@ -223,7 +233,7 @@ bool Bus::AllocateMemory()
if (!s_fastmem_arena.Create(FASTMEM_ARENA_SIZE))
{
// TODO: maybe make this non-fatal?
Host::ReportErrorAsync("Error", "Failed to create fastmem arena");
Host::ReportFatalError("Memory Allocation Failed", "Failed to create fastmem arena");
ReleaseMemory();
return false;
}

View File

@ -1,9 +1,12 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#include "common/bitfield.h"
#include "types.h"
#include "common/bitfield.h"
#include <array>
#include <bitset>
#include <optional>

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "bus.h"
@ -7,11 +7,13 @@
#include "cpu_core_private.h"
#include "cpu_disasm.h"
#include "cpu_recompiler_types.h"
#include "host.h"
#include "settings.h"
#include "system.h"
#include "timing_event.h"
#include "common/assert.h"
#include "common/error.h"
#include "common/intrin.h"
#include "common/log.h"
#include "common/memmap.h"
@ -162,7 +164,7 @@ bool CPU::CodeCache::IsUsingFastmem()
return IsUsingAnyRecompiler() && g_settings.cpu_fastmem_mode != CPUFastmemMode::Disabled;
}
void CPU::CodeCache::ProcessStartup()
bool CPU::CodeCache::ProcessStartup()
{
AllocateLUTs();
@ -175,12 +177,18 @@ void CPU::CodeCache::ProcessStartup()
#endif
if (!has_buffer && !s_code_buffer.Allocate(RECOMPILER_CODE_CACHE_SIZE, RECOMPILER_FAR_CODE_CACHE_SIZE))
{
Panic("Failed to initialize code space");
Host::ReportFatalError("Error", "Failed to initialize code space");
return false;
}
#endif
if (!Common::PageFaultHandler::InstallHandler(ExceptionHandler))
Panic("Failed to install page fault handler");
{
Host::ReportFatalError("Error", "Failed to install page fault handler");
return false;
}
return true;
}
void CPU::CodeCache::ProcessShutdown()

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
@ -15,7 +15,7 @@ bool IsUsingAnyRecompiler();
bool IsUsingFastmem();
/// Allocates resources, call once at startup.
void ProcessStartup();
bool ProcessStartup();
/// Frees resources, call once at shutdown.
void ProcessShutdown();

View File

@ -242,12 +242,13 @@ static TinyString GetTimestampStringForFileName()
return TinyString::from_format("{:%Y-%m-%d_%H-%M-%S}", fmt::localtime(std::time(nullptr)));
}
void System::Internal::ProcessStartup()
bool System::Internal::ProcessStartup()
{
if (!Bus::AllocateMemory())
Panic("Failed to allocate memory for emulated bus.");
return false;
CPU::CodeCache::ProcessStartup();
if (!CPU::CodeCache::ProcessStartup())
return false;
// This will call back to Host::LoadSettings() -> ReloadSources().
LoadSettings(false);
@ -263,6 +264,8 @@ void System::Internal::ProcessStartup()
if (g_settings.enable_discord_presence)
InitializeDiscordPresence();
#endif
return true;
}
void System::Internal::ProcessShutdown()

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
@ -12,6 +12,7 @@
class ByteStream;
class CDImage;
class Error;
class StateWrapper;
class Controller;
@ -485,7 +486,7 @@ void UpdateDiscordPresence(bool update_session_time);
namespace Internal {
/// Called on process startup.
void ProcessStartup();
bool ProcessStartup();
/// Called on process shutdown.
void ProcessShutdown();