From 986dcf4f65af0050fcb3c571f8bf2d341b288956 Mon Sep 17 00:00:00 2001 From: Joel Linn Date: Thu, 24 Feb 2022 22:37:32 +0100 Subject: [PATCH] [Base] Check success of sync primitive creation - Mainly use `assert`s, since failure is very rare - Forward failure of `CreateSemaphore` to guests because it is more easy to trigger with invalid initial parameters. --- src/xenia/app/xenia_main.cc | 2 ++ src/xenia/apu/audio_system.cc | 6 +++- src/xenia/apu/xma_decoder.cc | 3 +- src/xenia/base/logging.cc | 3 +- src/xenia/base/socket_win.cc | 4 ++- src/xenia/base/testing/threading_test.cc | 28 ++++++++++++++++++- src/xenia/base/threading_win.cc | 3 +- src/xenia/gpu/command_processor.cc | 4 ++- src/xenia/gpu/d3d12/pipeline_cache.cc | 13 +++++++-- src/xenia/gpu/trace_player.cc | 1 + .../kernel/xboxkrnl/xboxkrnl_threading.cc | 8 +++++- src/xenia/kernel/xevent.cc | 5 +++- src/xenia/kernel/xfile.cc | 4 ++- src/xenia/kernel/xiocompletion.cc | 3 +- src/xenia/kernel/xmutant.cc | 3 +- src/xenia/kernel/xnotifylistener.cc | 4 ++- src/xenia/kernel/xobject.cc | 6 ++-- src/xenia/kernel/xsemaphore.cc | 9 ++++-- src/xenia/kernel/xsemaphore.h | 7 +++-- src/xenia/kernel/xthread.cc | 3 +- src/xenia/kernel/xtimer.cc | 3 +- 21 files changed, 96 insertions(+), 26 deletions(-) diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc index 98ceb6578..ed6f1e9f1 100644 --- a/src/xenia/app/xenia_main.cc +++ b/src/xenia/app/xenia_main.cc @@ -17,6 +17,7 @@ #include "xenia/app/discord/discord_presence.h" #include "xenia/app/emulator_window.h" +#include "xenia/base/assert.h" #include "xenia/base/cvar.h" #include "xenia/base/debugging.h" #include "xenia/base/logging.h" @@ -371,6 +372,7 @@ bool EmulatorApp::OnInitialize() { // Setup the emulator and run its loop in a separate thread. emulator_thread_quit_requested_.store(false, std::memory_order_relaxed); emulator_thread_event_ = xe::threading::Event::CreateAutoResetEvent(false); + assert_not_null(emulator_thread_event_); emulator_thread_ = std::thread(&EmulatorApp::EmulatorThread, this); return true; diff --git a/src/xenia/apu/audio_system.cc b/src/xenia/apu/audio_system.cc index c137a4853..371b0b82b 100644 --- a/src/xenia/apu/audio_system.cc +++ b/src/xenia/apu/audio_system.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -12,6 +12,7 @@ #include "xenia/apu/apu_flags.h" #include "xenia/apu/audio_driver.h" #include "xenia/apu/xma_decoder.h" +#include "xenia/base/assert.h" #include "xenia/base/byte_stream.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" @@ -45,14 +46,17 @@ AudioSystem::AudioSystem(cpu::Processor* processor) for (size_t i = 0; i < kMaximumClientCount; ++i) { client_semaphores_[i] = xe::threading::Semaphore::Create(0, kMaximumQueuedFrames); + assert_not_null(client_semaphores_[i]); wait_handles_[i] = client_semaphores_[i].get(); } shutdown_event_ = xe::threading::Event::CreateAutoResetEvent(false); + assert_not_null(shutdown_event_); wait_handles_[kMaximumClientCount] = shutdown_event_.get(); xma_decoder_ = std::make_unique(processor_); resume_event_ = xe::threading::Event::CreateAutoResetEvent(false); + assert_not_null(resume_event_); } AudioSystem::~AudioSystem() { diff --git a/src/xenia/apu/xma_decoder.cc b/src/xenia/apu/xma_decoder.cc index cd04ebd91..3ad45e821 100644 --- a/src/xenia/apu/xma_decoder.cc +++ b/src/xenia/apu/xma_decoder.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -139,6 +139,7 @@ X_STATUS XmaDecoder::Setup(kernel::KernelState* kernel_state) { worker_running_ = true; work_event_ = xe::threading::Event::CreateAutoResetEvent(false); + assert_not_null(work_event_); worker_thread_ = kernel::object_ref( new kernel::XHostThread(kernel_state, 128 * 1024, 0, [this]() { WorkerThreadMain(); diff --git a/src/xenia/base/logging.cc b/src/xenia/base/logging.cc index bed2fe43b..ed636e428 100644 --- a/src/xenia/base/logging.cc +++ b/src/xenia/base/logging.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -224,6 +224,7 @@ class Logger { write_thread_ = xe::threading::Thread::Create({}, [this]() { WriteThread(); }); + assert_not_null(write_thread_); write_thread_->set_name("Logging Writer"); } diff --git a/src/xenia/base/socket_win.cc b/src/xenia/base/socket_win.cc index 35b96d470..2d3644dda 100644 --- a/src/xenia/base/socket_win.cc +++ b/src/xenia/base/socket_win.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -91,6 +91,7 @@ class Win32Socket : public Socket { // notifications. // Set true to start so we'll force a query of the socket on first run. event_ = xe::threading::Event::CreateManualResetEvent(true); + assert_not_null(event_); WSAEventSelect(socket_, event_->native_handle(), FD_READ | FD_CLOSE); // Keepalive for a looong time, as we may be paused by the debugger/etc. @@ -279,6 +280,7 @@ class Win32SocketServer : public SocketServer { accept_callback_(std::move(client)); } }); + assert_not_null(accept_thread_); return true; } diff --git a/src/xenia/base/testing/threading_test.cc b/src/xenia/base/testing/threading_test.cc index 17a17a8e5..94d8ec11c 100644 --- a/src/xenia/base/testing/threading_test.cc +++ b/src/xenia/base/testing/threading_test.cc @@ -165,6 +165,7 @@ TEST_CASE("TlsHandle") { auto thread = Thread::Create({}, [&non_thread_local_value, &handle] { non_thread_local_value = threading::GetTlsValue(handle); }); + REQUIRE(thread); auto result = Wait(thread.get(), false, 50ms); REQUIRE(result == WaitResult::kSuccess); @@ -231,8 +232,11 @@ TEST_CASE("HighResolutionTimer") { TEST_CASE("Wait on Multiple Handles", "[wait]") { auto mutant = Mutant::Create(true); + REQUIRE(mutant); auto semaphore = Semaphore::Create(10, 10); + REQUIRE(semaphore); auto event_ = Event::CreateManualResetEvent(false); + REQUIRE(event_); auto thread = Thread::Create({}, [&mutant, &semaphore, &event_] { event_->Set(); Wait(mutant.get(), false, 25ms); @@ -259,7 +263,9 @@ TEST_CASE("Wait on Multiple Handles", "[wait]") { TEST_CASE("Signal and Wait") { WaitResult result; auto mutant = Mutant::Create(true); + REQUIRE(mutant); auto event_ = Event::CreateAutoResetEvent(false); + REQUIRE(event_); auto thread = Thread::Create({}, [&mutant, &event_] { Wait(mutant.get(), false); event_->Set(); @@ -274,6 +280,7 @@ TEST_CASE("Signal and Wait") { TEST_CASE("Wait on Event", "[event]") { auto evt = Event::CreateAutoResetEvent(false); + REQUIRE(evt); WaitResult result; // Call wait on unset Event @@ -292,6 +299,7 @@ TEST_CASE("Wait on Event", "[event]") { TEST_CASE("Reset Event", "[event]") { auto evt = Event::CreateAutoResetEvent(false); + REQUIRE(evt); WaitResult result; // Call wait on reset Event @@ -318,6 +326,9 @@ TEST_CASE("Wait on Multiple Events", "[event]") { Event::CreateAutoResetEvent(false), Event::CreateManualResetEvent(false), }; + for (auto& event : events) { + REQUIRE(event.get() != nullptr); + } std::atomic_uint threads_started(0); std::array order = {0}; @@ -398,6 +409,7 @@ TEST_CASE("Wait on Semaphore", "[semaphore]") { // Wait on semaphore with no room sem = Semaphore::Create(0, 5); + REQUIRE(sem); result = Wait(sem.get(), false, 10ms); REQUIRE(result == WaitResult::kTimeout); @@ -413,12 +425,14 @@ TEST_CASE("Wait on Semaphore", "[semaphore]") { // Set semaphore over maximum_count sem = Semaphore::Create(5, 5); + REQUIRE(sem); previous_count = -1; REQUIRE_FALSE(sem->Release(1, &previous_count)); REQUIRE(previous_count == -1); REQUIRE_FALSE(sem->Release(10, &previous_count)); REQUIRE(previous_count == -1); sem = Semaphore::Create(0, 5); + REQUIRE(sem); REQUIRE_FALSE(sem->Release(10, &previous_count)); REQUIRE(previous_count == -1); REQUIRE_FALSE(sem->Release(10, &previous_count)); @@ -432,6 +446,7 @@ TEST_CASE("Wait on Semaphore", "[semaphore]") { // Wait on fully available semaphore sem = Semaphore::Create(5, 5); + REQUIRE(sem); result = Wait(sem.get(), false, 10ms); REQUIRE(result == WaitResult::kSuccess); result = Wait(sem.get(), false, 10ms); @@ -447,6 +462,7 @@ TEST_CASE("Wait on Semaphore", "[semaphore]") { // Semaphore between threads sem = Semaphore::Create(5, 5); + REQUIRE(sem); // Occupy the semaphore with 5 threads std::atomic wait_count(0); std::atomic threads_terminate(false); @@ -505,6 +521,8 @@ TEST_CASE("Wait on Multiple Semaphores", "[semaphore]") { // Test Wait all which should fail sem0 = Semaphore::Create(0, 5); sem1 = Semaphore::Create(5, 5); + REQUIRE(sem0); + REQUIRE(sem1); all_result = WaitAll({sem0.get(), sem1.get()}, false, 10ms); REQUIRE(all_result == WaitResult::kTimeout); previous_count = -1; @@ -517,6 +535,8 @@ TEST_CASE("Wait on Multiple Semaphores", "[semaphore]") { // Test Wait all again which should succeed sem0 = Semaphore::Create(1, 5); sem1 = Semaphore::Create(5, 5); + REQUIRE(sem0); + REQUIRE(sem1); all_result = WaitAll({sem0.get(), sem1.get()}, false, 10ms); REQUIRE(all_result == WaitResult::kSuccess); previous_count = -1; @@ -529,6 +549,8 @@ TEST_CASE("Wait on Multiple Semaphores", "[semaphore]") { // Test Wait Any which should fail sem0 = Semaphore::Create(0, 5); sem1 = Semaphore::Create(0, 5); + REQUIRE(sem0); + REQUIRE(sem1); any_result = WaitAny({sem0.get(), sem1.get()}, false, 10ms); REQUIRE(any_result.first == WaitResult::kTimeout); REQUIRE(any_result.second == 0); @@ -542,6 +564,8 @@ TEST_CASE("Wait on Multiple Semaphores", "[semaphore]") { // Test Wait Any which should succeed sem0 = Semaphore::Create(0, 5); sem1 = Semaphore::Create(5, 5); + REQUIRE(sem0); + REQUIRE(sem1); any_result = WaitAny({sem0.get(), sem1.get()}, false, 10ms); REQUIRE(any_result.first == WaitResult::kSuccess); REQUIRE(any_result.second == 1); @@ -689,6 +713,7 @@ TEST_CASE("Wait on Timer", "[timer]") { // Test Manual Reset timer = Timer::CreateManualResetTimer(); + REQUIRE(timer); result = Wait(timer.get(), false, 1ms); REQUIRE(result == WaitResult::kTimeout); REQUIRE(timer->SetOnce(1ms)); // Signals it @@ -699,6 +724,7 @@ TEST_CASE("Wait on Timer", "[timer]") { // Test Synchronization timer = Timer::CreateSynchronizationTimer(); + REQUIRE(timer); result = Wait(timer.get(), false, 1ms); REQUIRE(result == WaitResult::kTimeout); REQUIRE(timer->SetOnce(1ms)); // Signals it @@ -813,7 +839,7 @@ TEST_CASE("Set and Test Current Thread ID", "[thread]") { // TODO(bwrsandman): Test on Thread object } -TEST_CASE("Set and Test Current Thread Name", "Thread") { +TEST_CASE("Set and Test Current Thread Name", "[thread]") { auto current_thread = Thread::GetCurrentThread(); REQUIRE(current_thread); auto old_thread_name = current_thread->name(); diff --git a/src/xenia/base/threading_win.cc b/src/xenia/base/threading_win.cc index dd2a063d8..cf760d603 100644 --- a/src/xenia/base/threading_win.cc +++ b/src/xenia/base/threading_win.cc @@ -66,7 +66,8 @@ static void set_name(HANDLE thread, const std::string_view name) { auto func = (SetThreadDescriptionFn)GetProcAddress(kernel, "SetThreadDescription"); if (func) { - func(thread, reinterpret_cast(xe::to_utf16(name).c_str())); + auto u16name = xe::to_utf16(name); + func(thread, reinterpret_cast(u16name.c_str())); } } raise_thread_name_exception(thread, std::string(name)); diff --git a/src/xenia/gpu/command_processor.cc b/src/xenia/gpu/command_processor.cc index 7a4ac4e23..0fe9d7cbf 100644 --- a/src/xenia/gpu/command_processor.cc +++ b/src/xenia/gpu/command_processor.cc @@ -41,7 +41,9 @@ CommandProcessor::CommandProcessor(GraphicsSystem* graphics_system, trace_writer_(graphics_system->memory()->physical_membase()), worker_running_(true), write_ptr_index_event_(xe::threading::Event::CreateAutoResetEvent(false)), - write_ptr_index_(0) {} + write_ptr_index_(0) { + assert_not_null(write_ptr_index_event_); +} CommandProcessor::~CommandProcessor() = default; diff --git a/src/xenia/gpu/d3d12/pipeline_cache.cc b/src/xenia/gpu/d3d12/pipeline_cache.cc index 01b0b9cd8..75a096f48 100644 --- a/src/xenia/gpu/d3d12/pipeline_cache.cc +++ b/src/xenia/gpu/d3d12/pipeline_cache.cc @@ -149,6 +149,7 @@ bool PipelineCache::Initialize() { creation_threads_busy_ = 0; creation_completion_event_ = xe::threading::Event::CreateManualResetEvent(true); + assert_not_null(creation_completion_event_); creation_completion_set_event_ = false; creation_threads_shutdown_from_ = SIZE_MAX; if (cvars::d3d12_pipeline_creation_threads != 0) { @@ -164,6 +165,7 @@ bool PipelineCache::Initialize() { for (size_t i = 0; i < creation_thread_count; ++i) { std::unique_ptr creation_thread = xe::threading::Thread::Create({}, [this, i]() { CreationThread(i); }); + assert_not_null(creation_thread); creation_thread->set_name("D3D12 Pipelines"); creation_threads_.push_back(std::move(creation_thread)); } @@ -540,9 +542,11 @@ void PipelineCache::InitializeShaderStorage( } while (shader_translation_threads.size() < shader_translation_threads_needed) { - shader_translation_threads.push_back(xe::threading::Thread::Create( - {}, shader_translation_thread_function)); - shader_translation_threads.back()->set_name("Shader Translation"); + auto thread = xe::threading::Thread::Create( + {}, shader_translation_thread_function); + assert_not_null(thread); + thread->set_name("Shader Translation"); + shader_translation_threads.push_back(std::move(thread)); } // Request ucode information gathering and translation of all the needed // shaders. @@ -606,6 +610,7 @@ void PipelineCache::InitializeShaderStorage( xe::threading::Thread::Create({}, [this, creation_thread_index]() { CreationThread(creation_thread_index); }); + assert_not_null(creation_thread); creation_thread->set_name("D3D12 Pipelines"); creation_threads_.push_back(std::move(creation_thread)); } @@ -771,6 +776,8 @@ void PipelineCache::InitializeShaderStorage( storage_write_thread_shutdown_ = false; storage_write_thread_ = xe::threading::Thread::Create({}, [this]() { StorageWriteThread(); }); + assert_not_null(storage_write_thread_); + storage_write_thread_->set_name("D3D12 Storage writer"); } void PipelineCache::ShutdownShaderStorage() { diff --git a/src/xenia/gpu/trace_player.cc b/src/xenia/gpu/trace_player.cc index 54db1156c..a141c9b8d 100644 --- a/src/xenia/gpu/trace_player.cc +++ b/src/xenia/gpu/trace_player.cc @@ -30,6 +30,7 @@ TracePlayer::TracePlayer(GraphicsSystem* graphics_system) kMemoryProtectRead | kMemoryProtectWrite); playback_event_ = xe::threading::Event::CreateAutoResetEvent(false); + assert_not_null(playback_event_); } TracePlayer::~TracePlayer() { delete[] edram_snapshot_; } diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc index f913643eb..7e6c605e4 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc @@ -590,7 +590,13 @@ dword_result_t NtCreateSemaphore_entry(lpdword_t handle_ptr, } auto sem = object_ref(new XSemaphore(kernel_state())); - sem->Initialize((int32_t)count, (int32_t)limit); + if (!sem->Initialize((int32_t)count, (int32_t)limit)) { + if (handle_ptr) { + *handle_ptr = 0; + } + sem->ReleaseHandle(); + return X_STATUS_INVALID_PARAMETER; + } // obj_attributes may have a name inside of it, if != NULL. if (obj_attributes_ptr) { diff --git a/src/xenia/kernel/xevent.cc b/src/xenia/kernel/xevent.cc index f46fdb5fb..03c947c7e 100644 --- a/src/xenia/kernel/xevent.cc +++ b/src/xenia/kernel/xevent.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -30,6 +30,7 @@ void XEvent::Initialize(bool manual_reset, bool initial_state) { } else { event_ = xe::threading::Event::CreateAutoResetEvent(initial_state); } + assert_not_null(event_); } void XEvent::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) { @@ -53,6 +54,7 @@ void XEvent::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) { } else { event_ = xe::threading::Event::CreateAutoResetEvent(initial_state); } + assert_not_null(event_); } int32_t XEvent::Set(uint32_t priority_increment, bool wait) { @@ -112,6 +114,7 @@ object_ref XEvent::Restore(KernelState* kernel_state, } else { evt->event_ = xe::threading::Event::CreateAutoResetEvent(false); } + assert_not_null(evt->event_); if (signaled) { evt->event_->Set(); diff --git a/src/xenia/kernel/xfile.cc b/src/xenia/kernel/xfile.cc index b9c134c01..f46a9e137 100644 --- a/src/xenia/kernel/xfile.cc +++ b/src/xenia/kernel/xfile.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -26,10 +26,12 @@ XFile::XFile(KernelState* kernel_state, vfs::File* file, bool synchronous) file_(file), is_synchronous_(synchronous) { async_event_ = threading::Event::CreateAutoResetEvent(false); + assert_not_null(async_event_); } XFile::XFile() : XObject(kObjectType) { async_event_ = threading::Event::CreateAutoResetEvent(false); + assert_not_null(async_event_); } XFile::~XFile() { diff --git a/src/xenia/kernel/xiocompletion.cc b/src/xenia/kernel/xiocompletion.cc index 638a0a3ef..9f0411bfe 100644 --- a/src/xenia/kernel/xiocompletion.cc +++ b/src/xenia/kernel/xiocompletion.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -15,6 +15,7 @@ namespace kernel { XIOCompletion::XIOCompletion(KernelState* kernel_state) : XObject(kernel_state, kObjectType) { notification_semaphore_ = threading::Semaphore::Create(0, kMaxNotifications); + assert_not_null(notification_semaphore_); } XIOCompletion::~XIOCompletion() = default; diff --git a/src/xenia/kernel/xmutant.cc b/src/xenia/kernel/xmutant.cc index 4328fc342..0a67f2183 100644 --- a/src/xenia/kernel/xmutant.cc +++ b/src/xenia/kernel/xmutant.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -28,6 +28,7 @@ void XMutant::Initialize(bool initial_owner) { assert_false(mutant_); mutant_ = xe::threading::Mutant::Create(initial_owner); + assert_not_null(mutant_); } void XMutant::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) { diff --git a/src/xenia/kernel/xnotifylistener.cc b/src/xenia/kernel/xnotifylistener.cc index 7c054db70..fc2d24c98 100644 --- a/src/xenia/kernel/xnotifylistener.cc +++ b/src/xenia/kernel/xnotifylistener.cc @@ -2,13 +2,14 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/kernel/xnotifylistener.h" +#include "xenia/base/assert.h" #include "xenia/base/byte_stream.h" #include "xenia/base/logging.h" #include "xenia/kernel/kernel_state.h" @@ -25,6 +26,7 @@ void XNotifyListener::Initialize(uint64_t mask, uint32_t max_version) { assert_false(wait_handle_); wait_handle_ = xe::threading::Event::CreateManualResetEvent(false); + assert_not_null(wait_handle_); mask_ = mask; max_version_ = max_version; diff --git a/src/xenia/kernel/xobject.cc b/src/xenia/kernel/xobject.cc index 4909dbaa1..20b85249b 100644 --- a/src/xenia/kernel/xobject.cc +++ b/src/xenia/kernel/xobject.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -410,7 +410,9 @@ object_ref XObject::GetNativeObject(KernelState* kernel_state, case 5: // SemaphoreObject { auto sem = new XSemaphore(kernel_state); - sem->InitializeNative(native_ptr, header); + auto success = sem->InitializeNative(native_ptr, header); + // Can't report failure to the guest at late initialization: + assert_true(success); object = sem; } break; case 3: // ProcessObject diff --git a/src/xenia/kernel/xsemaphore.cc b/src/xenia/kernel/xsemaphore.cc index a582fe6d6..34b960b25 100644 --- a/src/xenia/kernel/xsemaphore.cc +++ b/src/xenia/kernel/xsemaphore.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -20,22 +20,24 @@ XSemaphore::XSemaphore(KernelState* kernel_state) XSemaphore::~XSemaphore() = default; -void XSemaphore::Initialize(int32_t initial_count, int32_t maximum_count) { +bool XSemaphore::Initialize(int32_t initial_count, int32_t maximum_count) { assert_false(semaphore_); CreateNative(sizeof(X_KSEMAPHORE)); maximum_count_ = maximum_count; semaphore_ = xe::threading::Semaphore::Create(initial_count, maximum_count); + return !!semaphore_; } -void XSemaphore::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) { +bool XSemaphore::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) { assert_false(semaphore_); auto semaphore = reinterpret_cast(native_ptr); maximum_count_ = semaphore->limit; semaphore_ = xe::threading::Semaphore::Create(semaphore->header.signal_state, semaphore->limit); + return !!semaphore_; } int32_t XSemaphore::ReleaseSemaphore(int32_t release_count) { @@ -85,6 +87,7 @@ object_ref XSemaphore::Restore(KernelState* kernel_state, sem->semaphore_ = threading::Semaphore::Create(free_count, sem->maximum_count_); + assert_not_null(sem->semaphore_); return object_ref(sem); } diff --git a/src/xenia/kernel/xsemaphore.h b/src/xenia/kernel/xsemaphore.h index b9e78a0b1..40261398b 100644 --- a/src/xenia/kernel/xsemaphore.h +++ b/src/xenia/kernel/xsemaphore.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -30,8 +30,9 @@ class XSemaphore : public XObject { explicit XSemaphore(KernelState* kernel_state); ~XSemaphore() override; - void Initialize(int32_t initial_count, int32_t maximum_count); - void InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header); + [[nodiscard]] bool Initialize(int32_t initial_count, int32_t maximum_count); + [[nodiscard]] bool InitializeNative(void* native_ptr, + X_DISPATCH_HEADER* header); int32_t ReleaseSemaphore(int32_t release_count); diff --git a/src/xenia/kernel/xthread.cc b/src/xenia/kernel/xthread.cc index 9c269c6b7..b842c2c08 100644 --- a/src/xenia/kernel/xthread.cc +++ b/src/xenia/kernel/xthread.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -1057,6 +1057,7 @@ object_ref XThread::Restore(KernelState* kernel_state, // Release the self-reference to the thread. thread->ReleaseHandle(); }); + assert_not_null(thread->thread_); // Notify processor we were recreated. thread->emulator()->processor()->OnThreadCreated( diff --git a/src/xenia/kernel/xtimer.cc b/src/xenia/kernel/xtimer.cc index fe66a73b7..e98add6d3 100644 --- a/src/xenia/kernel/xtimer.cc +++ b/src/xenia/kernel/xtimer.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -35,6 +35,7 @@ void XTimer::Initialize(uint32_t timer_type) { assert_always(); break; } + assert_not_null(timer_); } X_STATUS XTimer::SetTimer(int64_t due_time, uint32_t period_ms,