mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-02 15:49:48 -04:00
Results: Implement namespaced, type-safe results.
Because I was working on multiple things at once, this commit also: - Adds wrappers for/linker flags to wrap CXX exceptions to make them abort. This saves ~0x8000 of memory in every system module. - Broadly replaces lines of the pattern if (cond) { return ResultX; } with R_UNLESS(!cond, ResultX());. - Reworks the R_TRY_CATCH macros (and the result macros in general).
This commit is contained in:
parent
15773e4755
commit
4059dc6187
169 changed files with 2172 additions and 1868 deletions
|
@ -28,7 +28,7 @@ namespace sts::fatal::srv {
|
|||
u64 lr;
|
||||
};
|
||||
|
||||
bool IsThreadFatalCaller(u32 error_code, u32 debug_handle, u64 thread_id, u64 thread_tls_addr, ThreadContext *thread_ctx) {
|
||||
bool IsThreadFatalCaller(Result result, u32 debug_handle, u64 thread_id, u64 thread_tls_addr, ThreadContext *thread_ctx) {
|
||||
/* Verify that the thread is running or waiting. */
|
||||
{
|
||||
u64 _;
|
||||
|
@ -71,7 +71,7 @@ namespace sts::fatal::srv {
|
|||
|
||||
const struct {
|
||||
CmifInHeader header;
|
||||
u32 error_code;
|
||||
Result result;
|
||||
} *in_data = decltype(in_data)(request.data.data_words);
|
||||
static_assert(sizeof(*in_data) == 0x14, "InData!");
|
||||
|
||||
|
@ -112,7 +112,7 @@ namespace sts::fatal::srv {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (in_data->error_code != error_code) {
|
||||
if (in_data->result.GetValue() != result.GetValue()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ namespace sts::fatal::srv {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (IsThreadFatalCaller(ctx->error_code, debug_handle.Get(), cur_thread_id, thread_id_to_tls[cur_thread_id], &thread_ctx)) {
|
||||
if (IsThreadFatalCaller(ctx->result, debug_handle.Get(), cur_thread_id, thread_id_to_tls[cur_thread_id], &thread_ctx)) {
|
||||
thread_id = cur_thread_id;
|
||||
found_fatal_caller = true;
|
||||
break;
|
||||
|
|
|
@ -29,12 +29,10 @@ namespace sts::fatal::srv {
|
|||
std::scoped_lock lk{this->lock};
|
||||
|
||||
/* Only allow GetEvent to succeed NumFatalEvents times. */
|
||||
if (this->num_events_gotten >= FatalEventManager::NumFatalEvents) {
|
||||
return ResultFatalTooManyEvents;
|
||||
}
|
||||
R_UNLESS(this->num_events_gotten < FatalEventManager::NumFatalEvents, ResultTooManyEvents());
|
||||
|
||||
*out = this->events[this->num_events_gotten++].revent;
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void FatalEventManager::SignalEvents() {
|
||||
|
|
|
@ -57,6 +57,12 @@ namespace sts::ams {
|
|||
|
||||
}
|
||||
|
||||
namespace sts::result {
|
||||
|
||||
bool CallFatalOnResultAssertion = false;
|
||||
|
||||
}
|
||||
|
||||
using namespace sts;
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
|
|
|
@ -106,11 +106,11 @@ namespace sts::fatal::srv {
|
|||
|
||||
void CheckRepairStatus() {
|
||||
if (IsInRepairWithoutVolHeld()) {
|
||||
ThrowFatalForSelf(ResultFatalInRepairWithoutVolHeld);
|
||||
ThrowFatalForSelf(ResultInRepairWithoutVolHeld());
|
||||
}
|
||||
|
||||
if (IsInRepairWithoutTimeReviserCartridge()) {
|
||||
ThrowFatalForSelf(ResultFatalInRepairWithoutTimeReviserCartridge);
|
||||
ThrowFatalForSelf(ResultInRepairWithoutTimeReviserCartridge());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,11 +33,9 @@ namespace sts::fatal::srv {
|
|||
bool has_thrown;
|
||||
private:
|
||||
Result TrySetHasThrown() {
|
||||
if (this->has_thrown) {
|
||||
return ResultFatalAlreadyThrown;
|
||||
}
|
||||
R_UNLESS(!this->has_thrown, ResultAlreadyThrown());
|
||||
this->has_thrown = true;
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
public:
|
||||
ServiceContext() {
|
||||
|
@ -51,32 +49,30 @@ namespace sts::fatal::srv {
|
|||
return this->event_manager.GetEvent(out);
|
||||
}
|
||||
|
||||
Result ThrowFatal(u32 error_code, os::ProcessId process_id) {
|
||||
return this->ThrowFatalWithCpuContext(error_code, process_id, FatalType_ErrorReportAndErrorScreen, {});
|
||||
Result ThrowFatal(Result result, os::ProcessId process_id) {
|
||||
return this->ThrowFatalWithCpuContext(result, process_id, FatalType_ErrorReportAndErrorScreen, {});
|
||||
}
|
||||
|
||||
Result ThrowFatalWithPolicy(u32 error_code, os::ProcessId process_id, FatalType policy) {
|
||||
return this->ThrowFatalWithCpuContext(error_code, process_id, policy, {});
|
||||
Result ThrowFatalWithPolicy(Result result, os::ProcessId process_id, FatalType policy) {
|
||||
return this->ThrowFatalWithCpuContext(result, process_id, policy, {});
|
||||
}
|
||||
|
||||
Result ThrowFatalWithCpuContext(u32 error_code, os::ProcessId process_id, FatalType policy, const CpuContext &cpu_ctx);
|
||||
Result ThrowFatalWithCpuContext(Result result, os::ProcessId process_id, FatalType policy, const CpuContext &cpu_ctx);
|
||||
};
|
||||
|
||||
/* Context global. */
|
||||
ServiceContext g_context;
|
||||
|
||||
/* Throw implementation. */
|
||||
Result ServiceContext::ThrowFatalWithCpuContext(u32 error_code, os::ProcessId process_id, FatalType policy, const CpuContext &cpu_ctx) {
|
||||
Result ServiceContext::ThrowFatalWithCpuContext(Result result, os::ProcessId process_id, FatalType policy, const CpuContext &cpu_ctx) {
|
||||
/* We don't support Error Report only fatals. */
|
||||
if (policy == FatalType_ErrorReport) {
|
||||
return ResultSuccess;
|
||||
}
|
||||
R_UNLESS(policy != FatalType_ErrorReport, ResultSuccess());
|
||||
|
||||
/* Note that we've thrown fatal. */
|
||||
R_TRY(this->TrySetHasThrown());
|
||||
|
||||
/* At this point we have exclusive access to this->context. */
|
||||
this->context.error_code = error_code;
|
||||
this->context.result = result;
|
||||
this->context.cpu_ctx = cpu_ctx;
|
||||
|
||||
/* Cap the stack trace to a sane limit. */
|
||||
|
@ -108,8 +104,8 @@ namespace sts::fatal::srv {
|
|||
this->context.generate_error_report = (policy == FatalType_ErrorReportAndErrorScreen);
|
||||
|
||||
/* Adjust error code (2000-0000 -> 2162-0002). */
|
||||
if (this->context.error_code == ResultSuccess) {
|
||||
this->context.error_code = ResultErrSystemModuleAborted;
|
||||
if (R_SUCCEEDED(this->context.result)) {
|
||||
this->context.result = err::ResultSystemModuleAborted();
|
||||
}
|
||||
|
||||
switch (policy) {
|
||||
|
@ -126,25 +122,25 @@ namespace sts::fatal::srv {
|
|||
STS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Result ThrowFatalForSelf(Result error_code) {
|
||||
return g_context.ThrowFatalWithPolicy(static_cast<u32>(error_code), os::GetCurrentProcessId(), FatalType_ErrorScreen);
|
||||
Result ThrowFatalForSelf(Result result) {
|
||||
return g_context.ThrowFatalWithPolicy(result, os::GetCurrentProcessId(), FatalType_ErrorScreen);
|
||||
}
|
||||
|
||||
Result UserService::ThrowFatal(u32 error, const sf::ClientProcessId &client_pid) {
|
||||
return g_context.ThrowFatal(error, client_pid.GetValue());
|
||||
Result UserService::ThrowFatal(Result result, const sf::ClientProcessId &client_pid) {
|
||||
return g_context.ThrowFatal(result, client_pid.GetValue());
|
||||
}
|
||||
|
||||
Result UserService::ThrowFatalWithPolicy(u32 error, const sf::ClientProcessId &client_pid, FatalType policy) {
|
||||
return g_context.ThrowFatalWithPolicy(error, client_pid.GetValue(), policy);
|
||||
Result UserService::ThrowFatalWithPolicy(Result result, const sf::ClientProcessId &client_pid, FatalType policy) {
|
||||
return g_context.ThrowFatalWithPolicy(result, client_pid.GetValue(), policy);
|
||||
}
|
||||
|
||||
Result UserService::ThrowFatalWithCpuContext(u32 error, const sf::ClientProcessId &client_pid, FatalType policy, const CpuContext &cpu_ctx) {
|
||||
return g_context.ThrowFatalWithCpuContext(error, client_pid.GetValue(), policy, cpu_ctx);
|
||||
Result UserService::ThrowFatalWithCpuContext(Result result, const sf::ClientProcessId &client_pid, FatalType policy, const CpuContext &cpu_ctx) {
|
||||
return g_context.ThrowFatalWithCpuContext(result, client_pid.GetValue(), policy, cpu_ctx);
|
||||
}
|
||||
|
||||
Result PrivateService::GetFatalEvent(sf::OutCopyHandle out_h) {
|
||||
|
|
|
@ -29,9 +29,9 @@ namespace sts::fatal::srv {
|
|||
};
|
||||
private:
|
||||
/* Actual commands. */
|
||||
Result ThrowFatal(u32 error, const sf::ClientProcessId &client_pid);
|
||||
Result ThrowFatalWithPolicy(u32 error, const sf::ClientProcessId &client_pid, FatalType policy);
|
||||
Result ThrowFatalWithCpuContext(u32 error, const sf::ClientProcessId &client_pid, FatalType policy, const CpuContext &cpu_ctx);
|
||||
Result ThrowFatal(Result error, const sf::ClientProcessId &client_pid);
|
||||
Result ThrowFatalWithPolicy(Result error, const sf::ClientProcessId &client_pid, FatalType policy);
|
||||
Result ThrowFatalWithCpuContext(Result error, const sf::ClientProcessId &client_pid, FatalType policy, const CpuContext &cpu_ctx);
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MAKE_SERVICE_COMMAND_META(ThrowFatal),
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace sts::fatal::srv {
|
|||
R_TRY(pcvSetClockRate(module, hz));
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result AdjustClockTask::AdjustClock() {
|
||||
|
@ -66,7 +66,7 @@ namespace sts::fatal::srv {
|
|||
R_TRY(AdjustClockForModule(PcvModule_GPU, GPU_CLOCK_307MHZ));
|
||||
R_TRY(AdjustClockForModule(PcvModule_EMC, EMC_CLOCK_1331MHZ));
|
||||
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result AdjustClockTask::Run() {
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace sts::fatal::srv {
|
|||
ON_SCOPE_EXIT { fclose(f_report); };
|
||||
|
||||
fprintf(f_report, "Atmosphère Fatal Report (v1.0):\n");
|
||||
fprintf(f_report, "Result: 0x%X (2%03d-%04d)\n\n", this->context->error_code, R_MODULE(this->context->error_code), R_DESCRIPTION(this->context->error_code));
|
||||
fprintf(f_report, "Result: 0x%X (2%03d-%04d)\n\n", this->context->result.GetValue(), this->context->result.GetModule(), this->context->result.GetDescription());
|
||||
fprintf(f_report, "Title ID: %016lx\n", static_cast<u64>(this->context->title_id));
|
||||
if (strlen(this->context->proc_name)) {
|
||||
fprintf(f_report, "Process Name: %s\n", this->context->proc_name);
|
||||
|
@ -144,7 +144,7 @@ namespace sts::fatal::srv {
|
|||
/* Signal we're done with our job. */
|
||||
eventFire(const_cast<Event *>(&this->context->erpt_event));
|
||||
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -178,18 +178,18 @@ namespace sts::fatal::srv {
|
|||
|
||||
Result PowerControlTask::Run() {
|
||||
this->MonitorBatteryState();
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result PowerButtonObserveTask::Run() {
|
||||
this->WaitForPowerButton();
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result StateTransitionStopTask::Run() {
|
||||
/* Nintendo ignores the output of this call... */
|
||||
spsmPutErrorState();
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -90,9 +90,7 @@ namespace sts::fatal::srv {
|
|||
ViDisplay temp_display;
|
||||
/* Try to open the display. */
|
||||
R_TRY_CATCH(viOpenDisplay("Internal", &temp_display)) {
|
||||
R_CATCH(ResultViNotFound) {
|
||||
return ResultSuccess;
|
||||
}
|
||||
R_CONVERT(vi::ResultNotFound, ResultSuccess());
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
/* Guarantee we close the display. */
|
||||
|
@ -109,16 +107,14 @@ namespace sts::fatal::srv {
|
|||
/* Set alpha to 1.0f. */
|
||||
R_TRY(viSetDisplayAlpha(&temp_display, 1.0f));
|
||||
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ShowFatalTask::SetupDisplayExternal() {
|
||||
ViDisplay temp_display;
|
||||
/* Try to open the display. */
|
||||
R_TRY_CATCH(viOpenDisplay("External", &temp_display)) {
|
||||
R_CATCH(ResultViNotFound) {
|
||||
return ResultSuccess;
|
||||
}
|
||||
R_CONVERT(vi::ResultNotFound, ResultSuccess());
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
/* Guarantee we close the display. */
|
||||
|
@ -127,7 +123,7 @@ namespace sts::fatal::srv {
|
|||
/* Set alpha to 1.0f. */
|
||||
R_TRY(viSetDisplayAlpha(&temp_display, 1.0f));
|
||||
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ShowFatalTask::PrepareScreenForDrawing() {
|
||||
|
@ -182,7 +178,7 @@ namespace sts::fatal::srv {
|
|||
R_TRY(framebufferCreate(&this->fb, &this->win, raw_width, raw_height, PIXEL_FORMAT_RGB_565, 1));
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ShowFatalTask::ShowFatal() {
|
||||
|
@ -195,9 +191,7 @@ namespace sts::fatal::srv {
|
|||
|
||||
/* Dequeue a buffer. */
|
||||
u16 *tiled_buf = reinterpret_cast<u16 *>(framebufferBegin(&this->fb, NULL));
|
||||
if (tiled_buf == nullptr) {
|
||||
return ResultFatalNullGraphicsBuffer;
|
||||
}
|
||||
R_UNLESS(tiled_buf != nullptr, ResultNullGraphicsBuffer());
|
||||
|
||||
/* Let the font manager know about our framebuffer. */
|
||||
font::ConfigureFontFramebuffer(tiled_buf, GetPixelOffset);
|
||||
|
@ -218,13 +212,13 @@ namespace sts::fatal::srv {
|
|||
/* TODO: Actually draw meaningful shit here. */
|
||||
font::SetPosition(32, 64);
|
||||
font::SetFontSize(16.0f);
|
||||
font::PrintFormat(config.GetErrorMessage(), R_MODULE(this->context->error_code), R_DESCRIPTION(this->context->error_code), this->context->error_code);
|
||||
font::PrintFormat(config.GetErrorMessage(), this->context->result.GetModule(), this->context->result.GetDescription(), this->context->result.GetValue());
|
||||
font::AddSpacingLines(0.5f);
|
||||
font::PrintFormatLine("Title: %016lX", static_cast<u64>(this->context->title_id));
|
||||
font::AddSpacingLines(0.5f);
|
||||
font::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", config.GetFirmwareVersion().display_version, ATMOSPHERE_RELEASE_VERSION, ams::GetGitRevision());
|
||||
font::AddSpacingLines(1.5f);
|
||||
if (this->context->error_code != ResultAtmosphereVersionMismatch) {
|
||||
if (!ams::ResultVersionMismatch::Includes(this->context->result)) {
|
||||
font::Print(config.GetErrorDescription());
|
||||
} else {
|
||||
/* Print a special message for atmosphere version mismatch. */
|
||||
|
@ -415,7 +409,7 @@ namespace sts::fatal::srv {
|
|||
/* Enqueue the buffer. */
|
||||
framebufferEnd(&fb);
|
||||
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ShowFatalTask::Run() {
|
||||
|
@ -431,7 +425,7 @@ namespace sts::fatal::srv {
|
|||
|
||||
Result BacklightControlTask::Run() {
|
||||
TurnOnBacklight();
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace sts::fatal::srv {
|
|||
|
||||
Result StopSoundTask::Run() {
|
||||
StopSound();
|
||||
return ResultSuccess;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue