[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.
This commit is contained in:
parent
6bd1279fc0
commit
986dcf4f65
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "xenia/app/discord/discord_presence.h"
|
#include "xenia/app/discord/discord_presence.h"
|
||||||
#include "xenia/app/emulator_window.h"
|
#include "xenia/app/emulator_window.h"
|
||||||
|
#include "xenia/base/assert.h"
|
||||||
#include "xenia/base/cvar.h"
|
#include "xenia/base/cvar.h"
|
||||||
#include "xenia/base/debugging.h"
|
#include "xenia/base/debugging.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
|
@ -371,6 +372,7 @@ bool EmulatorApp::OnInitialize() {
|
||||||
// Setup the emulator and run its loop in a separate thread.
|
// Setup the emulator and run its loop in a separate thread.
|
||||||
emulator_thread_quit_requested_.store(false, std::memory_order_relaxed);
|
emulator_thread_quit_requested_.store(false, std::memory_order_relaxed);
|
||||||
emulator_thread_event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
emulator_thread_event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
||||||
|
assert_not_null(emulator_thread_event_);
|
||||||
emulator_thread_ = std::thread(&EmulatorApp::EmulatorThread, this);
|
emulator_thread_ = std::thread(&EmulatorApp::EmulatorThread, this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* 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/apu_flags.h"
|
||||||
#include "xenia/apu/audio_driver.h"
|
#include "xenia/apu/audio_driver.h"
|
||||||
#include "xenia/apu/xma_decoder.h"
|
#include "xenia/apu/xma_decoder.h"
|
||||||
|
#include "xenia/base/assert.h"
|
||||||
#include "xenia/base/byte_stream.h"
|
#include "xenia/base/byte_stream.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/base/math.h"
|
#include "xenia/base/math.h"
|
||||||
|
@ -45,14 +46,17 @@ AudioSystem::AudioSystem(cpu::Processor* processor)
|
||||||
for (size_t i = 0; i < kMaximumClientCount; ++i) {
|
for (size_t i = 0; i < kMaximumClientCount; ++i) {
|
||||||
client_semaphores_[i] =
|
client_semaphores_[i] =
|
||||||
xe::threading::Semaphore::Create(0, kMaximumQueuedFrames);
|
xe::threading::Semaphore::Create(0, kMaximumQueuedFrames);
|
||||||
|
assert_not_null(client_semaphores_[i]);
|
||||||
wait_handles_[i] = client_semaphores_[i].get();
|
wait_handles_[i] = client_semaphores_[i].get();
|
||||||
}
|
}
|
||||||
shutdown_event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
shutdown_event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
||||||
|
assert_not_null(shutdown_event_);
|
||||||
wait_handles_[kMaximumClientCount] = shutdown_event_.get();
|
wait_handles_[kMaximumClientCount] = shutdown_event_.get();
|
||||||
|
|
||||||
xma_decoder_ = std::make_unique<xe::apu::XmaDecoder>(processor_);
|
xma_decoder_ = std::make_unique<xe::apu::XmaDecoder>(processor_);
|
||||||
|
|
||||||
resume_event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
resume_event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
||||||
|
assert_not_null(resume_event_);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioSystem::~AudioSystem() {
|
AudioSystem::~AudioSystem() {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* 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;
|
worker_running_ = true;
|
||||||
work_event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
work_event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
||||||
|
assert_not_null(work_event_);
|
||||||
worker_thread_ = kernel::object_ref<kernel::XHostThread>(
|
worker_thread_ = kernel::object_ref<kernel::XHostThread>(
|
||||||
new kernel::XHostThread(kernel_state, 128 * 1024, 0, [this]() {
|
new kernel::XHostThread(kernel_state, 128 * 1024, 0, [this]() {
|
||||||
WorkerThreadMain();
|
WorkerThreadMain();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
@ -224,6 +224,7 @@ class Logger {
|
||||||
|
|
||||||
write_thread_ =
|
write_thread_ =
|
||||||
xe::threading::Thread::Create({}, [this]() { WriteThread(); });
|
xe::threading::Thread::Create({}, [this]() { WriteThread(); });
|
||||||
|
assert_not_null(write_thread_);
|
||||||
write_thread_->set_name("Logging Writer");
|
write_thread_->set_name("Logging Writer");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
@ -91,6 +91,7 @@ class Win32Socket : public Socket {
|
||||||
// notifications.
|
// notifications.
|
||||||
// Set true to start so we'll force a query of the socket on first run.
|
// Set true to start so we'll force a query of the socket on first run.
|
||||||
event_ = xe::threading::Event::CreateManualResetEvent(true);
|
event_ = xe::threading::Event::CreateManualResetEvent(true);
|
||||||
|
assert_not_null(event_);
|
||||||
WSAEventSelect(socket_, event_->native_handle(), FD_READ | FD_CLOSE);
|
WSAEventSelect(socket_, event_->native_handle(), FD_READ | FD_CLOSE);
|
||||||
|
|
||||||
// Keepalive for a looong time, as we may be paused by the debugger/etc.
|
// 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));
|
accept_callback_(std::move(client));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
assert_not_null(accept_thread_);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,6 +165,7 @@ TEST_CASE("TlsHandle") {
|
||||||
auto thread = Thread::Create({}, [&non_thread_local_value, &handle] {
|
auto thread = Thread::Create({}, [&non_thread_local_value, &handle] {
|
||||||
non_thread_local_value = threading::GetTlsValue(handle);
|
non_thread_local_value = threading::GetTlsValue(handle);
|
||||||
});
|
});
|
||||||
|
REQUIRE(thread);
|
||||||
|
|
||||||
auto result = Wait(thread.get(), false, 50ms);
|
auto result = Wait(thread.get(), false, 50ms);
|
||||||
REQUIRE(result == WaitResult::kSuccess);
|
REQUIRE(result == WaitResult::kSuccess);
|
||||||
|
@ -231,8 +232,11 @@ TEST_CASE("HighResolutionTimer") {
|
||||||
|
|
||||||
TEST_CASE("Wait on Multiple Handles", "[wait]") {
|
TEST_CASE("Wait on Multiple Handles", "[wait]") {
|
||||||
auto mutant = Mutant::Create(true);
|
auto mutant = Mutant::Create(true);
|
||||||
|
REQUIRE(mutant);
|
||||||
auto semaphore = Semaphore::Create(10, 10);
|
auto semaphore = Semaphore::Create(10, 10);
|
||||||
|
REQUIRE(semaphore);
|
||||||
auto event_ = Event::CreateManualResetEvent(false);
|
auto event_ = Event::CreateManualResetEvent(false);
|
||||||
|
REQUIRE(event_);
|
||||||
auto thread = Thread::Create({}, [&mutant, &semaphore, &event_] {
|
auto thread = Thread::Create({}, [&mutant, &semaphore, &event_] {
|
||||||
event_->Set();
|
event_->Set();
|
||||||
Wait(mutant.get(), false, 25ms);
|
Wait(mutant.get(), false, 25ms);
|
||||||
|
@ -259,7 +263,9 @@ TEST_CASE("Wait on Multiple Handles", "[wait]") {
|
||||||
TEST_CASE("Signal and Wait") {
|
TEST_CASE("Signal and Wait") {
|
||||||
WaitResult result;
|
WaitResult result;
|
||||||
auto mutant = Mutant::Create(true);
|
auto mutant = Mutant::Create(true);
|
||||||
|
REQUIRE(mutant);
|
||||||
auto event_ = Event::CreateAutoResetEvent(false);
|
auto event_ = Event::CreateAutoResetEvent(false);
|
||||||
|
REQUIRE(event_);
|
||||||
auto thread = Thread::Create({}, [&mutant, &event_] {
|
auto thread = Thread::Create({}, [&mutant, &event_] {
|
||||||
Wait(mutant.get(), false);
|
Wait(mutant.get(), false);
|
||||||
event_->Set();
|
event_->Set();
|
||||||
|
@ -274,6 +280,7 @@ TEST_CASE("Signal and Wait") {
|
||||||
|
|
||||||
TEST_CASE("Wait on Event", "[event]") {
|
TEST_CASE("Wait on Event", "[event]") {
|
||||||
auto evt = Event::CreateAutoResetEvent(false);
|
auto evt = Event::CreateAutoResetEvent(false);
|
||||||
|
REQUIRE(evt);
|
||||||
WaitResult result;
|
WaitResult result;
|
||||||
|
|
||||||
// Call wait on unset Event
|
// Call wait on unset Event
|
||||||
|
@ -292,6 +299,7 @@ TEST_CASE("Wait on Event", "[event]") {
|
||||||
|
|
||||||
TEST_CASE("Reset Event", "[event]") {
|
TEST_CASE("Reset Event", "[event]") {
|
||||||
auto evt = Event::CreateAutoResetEvent(false);
|
auto evt = Event::CreateAutoResetEvent(false);
|
||||||
|
REQUIRE(evt);
|
||||||
WaitResult result;
|
WaitResult result;
|
||||||
|
|
||||||
// Call wait on reset Event
|
// Call wait on reset Event
|
||||||
|
@ -318,6 +326,9 @@ TEST_CASE("Wait on Multiple Events", "[event]") {
|
||||||
Event::CreateAutoResetEvent(false),
|
Event::CreateAutoResetEvent(false),
|
||||||
Event::CreateManualResetEvent(false),
|
Event::CreateManualResetEvent(false),
|
||||||
};
|
};
|
||||||
|
for (auto& event : events) {
|
||||||
|
REQUIRE(event.get() != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
std::atomic_uint threads_started(0);
|
std::atomic_uint threads_started(0);
|
||||||
std::array<char, 8> order = {0};
|
std::array<char, 8> order = {0};
|
||||||
|
@ -398,6 +409,7 @@ TEST_CASE("Wait on Semaphore", "[semaphore]") {
|
||||||
|
|
||||||
// Wait on semaphore with no room
|
// Wait on semaphore with no room
|
||||||
sem = Semaphore::Create(0, 5);
|
sem = Semaphore::Create(0, 5);
|
||||||
|
REQUIRE(sem);
|
||||||
result = Wait(sem.get(), false, 10ms);
|
result = Wait(sem.get(), false, 10ms);
|
||||||
REQUIRE(result == WaitResult::kTimeout);
|
REQUIRE(result == WaitResult::kTimeout);
|
||||||
|
|
||||||
|
@ -413,12 +425,14 @@ TEST_CASE("Wait on Semaphore", "[semaphore]") {
|
||||||
|
|
||||||
// Set semaphore over maximum_count
|
// Set semaphore over maximum_count
|
||||||
sem = Semaphore::Create(5, 5);
|
sem = Semaphore::Create(5, 5);
|
||||||
|
REQUIRE(sem);
|
||||||
previous_count = -1;
|
previous_count = -1;
|
||||||
REQUIRE_FALSE(sem->Release(1, &previous_count));
|
REQUIRE_FALSE(sem->Release(1, &previous_count));
|
||||||
REQUIRE(previous_count == -1);
|
REQUIRE(previous_count == -1);
|
||||||
REQUIRE_FALSE(sem->Release(10, &previous_count));
|
REQUIRE_FALSE(sem->Release(10, &previous_count));
|
||||||
REQUIRE(previous_count == -1);
|
REQUIRE(previous_count == -1);
|
||||||
sem = Semaphore::Create(0, 5);
|
sem = Semaphore::Create(0, 5);
|
||||||
|
REQUIRE(sem);
|
||||||
REQUIRE_FALSE(sem->Release(10, &previous_count));
|
REQUIRE_FALSE(sem->Release(10, &previous_count));
|
||||||
REQUIRE(previous_count == -1);
|
REQUIRE(previous_count == -1);
|
||||||
REQUIRE_FALSE(sem->Release(10, &previous_count));
|
REQUIRE_FALSE(sem->Release(10, &previous_count));
|
||||||
|
@ -432,6 +446,7 @@ TEST_CASE("Wait on Semaphore", "[semaphore]") {
|
||||||
|
|
||||||
// Wait on fully available semaphore
|
// Wait on fully available semaphore
|
||||||
sem = Semaphore::Create(5, 5);
|
sem = Semaphore::Create(5, 5);
|
||||||
|
REQUIRE(sem);
|
||||||
result = Wait(sem.get(), false, 10ms);
|
result = Wait(sem.get(), false, 10ms);
|
||||||
REQUIRE(result == WaitResult::kSuccess);
|
REQUIRE(result == WaitResult::kSuccess);
|
||||||
result = Wait(sem.get(), false, 10ms);
|
result = Wait(sem.get(), false, 10ms);
|
||||||
|
@ -447,6 +462,7 @@ TEST_CASE("Wait on Semaphore", "[semaphore]") {
|
||||||
|
|
||||||
// Semaphore between threads
|
// Semaphore between threads
|
||||||
sem = Semaphore::Create(5, 5);
|
sem = Semaphore::Create(5, 5);
|
||||||
|
REQUIRE(sem);
|
||||||
// Occupy the semaphore with 5 threads
|
// Occupy the semaphore with 5 threads
|
||||||
std::atomic<int> wait_count(0);
|
std::atomic<int> wait_count(0);
|
||||||
std::atomic<bool> threads_terminate(false);
|
std::atomic<bool> threads_terminate(false);
|
||||||
|
@ -505,6 +521,8 @@ TEST_CASE("Wait on Multiple Semaphores", "[semaphore]") {
|
||||||
// Test Wait all which should fail
|
// Test Wait all which should fail
|
||||||
sem0 = Semaphore::Create(0, 5);
|
sem0 = Semaphore::Create(0, 5);
|
||||||
sem1 = Semaphore::Create(5, 5);
|
sem1 = Semaphore::Create(5, 5);
|
||||||
|
REQUIRE(sem0);
|
||||||
|
REQUIRE(sem1);
|
||||||
all_result = WaitAll({sem0.get(), sem1.get()}, false, 10ms);
|
all_result = WaitAll({sem0.get(), sem1.get()}, false, 10ms);
|
||||||
REQUIRE(all_result == WaitResult::kTimeout);
|
REQUIRE(all_result == WaitResult::kTimeout);
|
||||||
previous_count = -1;
|
previous_count = -1;
|
||||||
|
@ -517,6 +535,8 @@ TEST_CASE("Wait on Multiple Semaphores", "[semaphore]") {
|
||||||
// Test Wait all again which should succeed
|
// Test Wait all again which should succeed
|
||||||
sem0 = Semaphore::Create(1, 5);
|
sem0 = Semaphore::Create(1, 5);
|
||||||
sem1 = Semaphore::Create(5, 5);
|
sem1 = Semaphore::Create(5, 5);
|
||||||
|
REQUIRE(sem0);
|
||||||
|
REQUIRE(sem1);
|
||||||
all_result = WaitAll({sem0.get(), sem1.get()}, false, 10ms);
|
all_result = WaitAll({sem0.get(), sem1.get()}, false, 10ms);
|
||||||
REQUIRE(all_result == WaitResult::kSuccess);
|
REQUIRE(all_result == WaitResult::kSuccess);
|
||||||
previous_count = -1;
|
previous_count = -1;
|
||||||
|
@ -529,6 +549,8 @@ TEST_CASE("Wait on Multiple Semaphores", "[semaphore]") {
|
||||||
// Test Wait Any which should fail
|
// Test Wait Any which should fail
|
||||||
sem0 = Semaphore::Create(0, 5);
|
sem0 = Semaphore::Create(0, 5);
|
||||||
sem1 = Semaphore::Create(0, 5);
|
sem1 = Semaphore::Create(0, 5);
|
||||||
|
REQUIRE(sem0);
|
||||||
|
REQUIRE(sem1);
|
||||||
any_result = WaitAny({sem0.get(), sem1.get()}, false, 10ms);
|
any_result = WaitAny({sem0.get(), sem1.get()}, false, 10ms);
|
||||||
REQUIRE(any_result.first == WaitResult::kTimeout);
|
REQUIRE(any_result.first == WaitResult::kTimeout);
|
||||||
REQUIRE(any_result.second == 0);
|
REQUIRE(any_result.second == 0);
|
||||||
|
@ -542,6 +564,8 @@ TEST_CASE("Wait on Multiple Semaphores", "[semaphore]") {
|
||||||
// Test Wait Any which should succeed
|
// Test Wait Any which should succeed
|
||||||
sem0 = Semaphore::Create(0, 5);
|
sem0 = Semaphore::Create(0, 5);
|
||||||
sem1 = Semaphore::Create(5, 5);
|
sem1 = Semaphore::Create(5, 5);
|
||||||
|
REQUIRE(sem0);
|
||||||
|
REQUIRE(sem1);
|
||||||
any_result = WaitAny({sem0.get(), sem1.get()}, false, 10ms);
|
any_result = WaitAny({sem0.get(), sem1.get()}, false, 10ms);
|
||||||
REQUIRE(any_result.first == WaitResult::kSuccess);
|
REQUIRE(any_result.first == WaitResult::kSuccess);
|
||||||
REQUIRE(any_result.second == 1);
|
REQUIRE(any_result.second == 1);
|
||||||
|
@ -689,6 +713,7 @@ TEST_CASE("Wait on Timer", "[timer]") {
|
||||||
|
|
||||||
// Test Manual Reset
|
// Test Manual Reset
|
||||||
timer = Timer::CreateManualResetTimer();
|
timer = Timer::CreateManualResetTimer();
|
||||||
|
REQUIRE(timer);
|
||||||
result = Wait(timer.get(), false, 1ms);
|
result = Wait(timer.get(), false, 1ms);
|
||||||
REQUIRE(result == WaitResult::kTimeout);
|
REQUIRE(result == WaitResult::kTimeout);
|
||||||
REQUIRE(timer->SetOnce(1ms)); // Signals it
|
REQUIRE(timer->SetOnce(1ms)); // Signals it
|
||||||
|
@ -699,6 +724,7 @@ TEST_CASE("Wait on Timer", "[timer]") {
|
||||||
|
|
||||||
// Test Synchronization
|
// Test Synchronization
|
||||||
timer = Timer::CreateSynchronizationTimer();
|
timer = Timer::CreateSynchronizationTimer();
|
||||||
|
REQUIRE(timer);
|
||||||
result = Wait(timer.get(), false, 1ms);
|
result = Wait(timer.get(), false, 1ms);
|
||||||
REQUIRE(result == WaitResult::kTimeout);
|
REQUIRE(result == WaitResult::kTimeout);
|
||||||
REQUIRE(timer->SetOnce(1ms)); // Signals it
|
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
|
// 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();
|
auto current_thread = Thread::GetCurrentThread();
|
||||||
REQUIRE(current_thread);
|
REQUIRE(current_thread);
|
||||||
auto old_thread_name = current_thread->name();
|
auto old_thread_name = current_thread->name();
|
||||||
|
|
|
@ -66,7 +66,8 @@ static void set_name(HANDLE thread, const std::string_view name) {
|
||||||
auto func =
|
auto func =
|
||||||
(SetThreadDescriptionFn)GetProcAddress(kernel, "SetThreadDescription");
|
(SetThreadDescriptionFn)GetProcAddress(kernel, "SetThreadDescription");
|
||||||
if (func) {
|
if (func) {
|
||||||
func(thread, reinterpret_cast<PCWSTR>(xe::to_utf16(name).c_str()));
|
auto u16name = xe::to_utf16(name);
|
||||||
|
func(thread, reinterpret_cast<PCWSTR>(u16name.c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
raise_thread_name_exception(thread, std::string(name));
|
raise_thread_name_exception(thread, std::string(name));
|
||||||
|
|
|
@ -41,7 +41,9 @@ CommandProcessor::CommandProcessor(GraphicsSystem* graphics_system,
|
||||||
trace_writer_(graphics_system->memory()->physical_membase()),
|
trace_writer_(graphics_system->memory()->physical_membase()),
|
||||||
worker_running_(true),
|
worker_running_(true),
|
||||||
write_ptr_index_event_(xe::threading::Event::CreateAutoResetEvent(false)),
|
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;
|
CommandProcessor::~CommandProcessor() = default;
|
||||||
|
|
||||||
|
|
|
@ -149,6 +149,7 @@ bool PipelineCache::Initialize() {
|
||||||
creation_threads_busy_ = 0;
|
creation_threads_busy_ = 0;
|
||||||
creation_completion_event_ =
|
creation_completion_event_ =
|
||||||
xe::threading::Event::CreateManualResetEvent(true);
|
xe::threading::Event::CreateManualResetEvent(true);
|
||||||
|
assert_not_null(creation_completion_event_);
|
||||||
creation_completion_set_event_ = false;
|
creation_completion_set_event_ = false;
|
||||||
creation_threads_shutdown_from_ = SIZE_MAX;
|
creation_threads_shutdown_from_ = SIZE_MAX;
|
||||||
if (cvars::d3d12_pipeline_creation_threads != 0) {
|
if (cvars::d3d12_pipeline_creation_threads != 0) {
|
||||||
|
@ -164,6 +165,7 @@ bool PipelineCache::Initialize() {
|
||||||
for (size_t i = 0; i < creation_thread_count; ++i) {
|
for (size_t i = 0; i < creation_thread_count; ++i) {
|
||||||
std::unique_ptr<xe::threading::Thread> creation_thread =
|
std::unique_ptr<xe::threading::Thread> creation_thread =
|
||||||
xe::threading::Thread::Create({}, [this, i]() { CreationThread(i); });
|
xe::threading::Thread::Create({}, [this, i]() { CreationThread(i); });
|
||||||
|
assert_not_null(creation_thread);
|
||||||
creation_thread->set_name("D3D12 Pipelines");
|
creation_thread->set_name("D3D12 Pipelines");
|
||||||
creation_threads_.push_back(std::move(creation_thread));
|
creation_threads_.push_back(std::move(creation_thread));
|
||||||
}
|
}
|
||||||
|
@ -540,9 +542,11 @@ void PipelineCache::InitializeShaderStorage(
|
||||||
}
|
}
|
||||||
while (shader_translation_threads.size() <
|
while (shader_translation_threads.size() <
|
||||||
shader_translation_threads_needed) {
|
shader_translation_threads_needed) {
|
||||||
shader_translation_threads.push_back(xe::threading::Thread::Create(
|
auto thread = xe::threading::Thread::Create(
|
||||||
{}, shader_translation_thread_function));
|
{}, shader_translation_thread_function);
|
||||||
shader_translation_threads.back()->set_name("Shader Translation");
|
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
|
// Request ucode information gathering and translation of all the needed
|
||||||
// shaders.
|
// shaders.
|
||||||
|
@ -606,6 +610,7 @@ void PipelineCache::InitializeShaderStorage(
|
||||||
xe::threading::Thread::Create({}, [this, creation_thread_index]() {
|
xe::threading::Thread::Create({}, [this, creation_thread_index]() {
|
||||||
CreationThread(creation_thread_index);
|
CreationThread(creation_thread_index);
|
||||||
});
|
});
|
||||||
|
assert_not_null(creation_thread);
|
||||||
creation_thread->set_name("D3D12 Pipelines");
|
creation_thread->set_name("D3D12 Pipelines");
|
||||||
creation_threads_.push_back(std::move(creation_thread));
|
creation_threads_.push_back(std::move(creation_thread));
|
||||||
}
|
}
|
||||||
|
@ -771,6 +776,8 @@ void PipelineCache::InitializeShaderStorage(
|
||||||
storage_write_thread_shutdown_ = false;
|
storage_write_thread_shutdown_ = false;
|
||||||
storage_write_thread_ =
|
storage_write_thread_ =
|
||||||
xe::threading::Thread::Create({}, [this]() { StorageWriteThread(); });
|
xe::threading::Thread::Create({}, [this]() { StorageWriteThread(); });
|
||||||
|
assert_not_null(storage_write_thread_);
|
||||||
|
storage_write_thread_->set_name("D3D12 Storage writer");
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipelineCache::ShutdownShaderStorage() {
|
void PipelineCache::ShutdownShaderStorage() {
|
||||||
|
|
|
@ -30,6 +30,7 @@ TracePlayer::TracePlayer(GraphicsSystem* graphics_system)
|
||||||
kMemoryProtectRead | kMemoryProtectWrite);
|
kMemoryProtectRead | kMemoryProtectWrite);
|
||||||
|
|
||||||
playback_event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
playback_event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
||||||
|
assert_not_null(playback_event_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TracePlayer::~TracePlayer() { delete[] edram_snapshot_; }
|
TracePlayer::~TracePlayer() { delete[] edram_snapshot_; }
|
||||||
|
|
|
@ -590,7 +590,13 @@ dword_result_t NtCreateSemaphore_entry(lpdword_t handle_ptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sem = object_ref<XSemaphore>(new XSemaphore(kernel_state()));
|
auto sem = object_ref<XSemaphore>(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.
|
// obj_attributes may have a name inside of it, if != NULL.
|
||||||
if (obj_attributes_ptr) {
|
if (obj_attributes_ptr) {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* 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 {
|
} else {
|
||||||
event_ = xe::threading::Event::CreateAutoResetEvent(initial_state);
|
event_ = xe::threading::Event::CreateAutoResetEvent(initial_state);
|
||||||
}
|
}
|
||||||
|
assert_not_null(event_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XEvent::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) {
|
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 {
|
} else {
|
||||||
event_ = xe::threading::Event::CreateAutoResetEvent(initial_state);
|
event_ = xe::threading::Event::CreateAutoResetEvent(initial_state);
|
||||||
}
|
}
|
||||||
|
assert_not_null(event_);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t XEvent::Set(uint32_t priority_increment, bool wait) {
|
int32_t XEvent::Set(uint32_t priority_increment, bool wait) {
|
||||||
|
@ -112,6 +114,7 @@ object_ref<XEvent> XEvent::Restore(KernelState* kernel_state,
|
||||||
} else {
|
} else {
|
||||||
evt->event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
evt->event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
||||||
}
|
}
|
||||||
|
assert_not_null(evt->event_);
|
||||||
|
|
||||||
if (signaled) {
|
if (signaled) {
|
||||||
evt->event_->Set();
|
evt->event_->Set();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* 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),
|
file_(file),
|
||||||
is_synchronous_(synchronous) {
|
is_synchronous_(synchronous) {
|
||||||
async_event_ = threading::Event::CreateAutoResetEvent(false);
|
async_event_ = threading::Event::CreateAutoResetEvent(false);
|
||||||
|
assert_not_null(async_event_);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFile::XFile() : XObject(kObjectType) {
|
XFile::XFile() : XObject(kObjectType) {
|
||||||
async_event_ = threading::Event::CreateAutoResetEvent(false);
|
async_event_ = threading::Event::CreateAutoResetEvent(false);
|
||||||
|
assert_not_null(async_event_);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFile::~XFile() {
|
XFile::~XFile() {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
@ -15,6 +15,7 @@ namespace kernel {
|
||||||
XIOCompletion::XIOCompletion(KernelState* kernel_state)
|
XIOCompletion::XIOCompletion(KernelState* kernel_state)
|
||||||
: XObject(kernel_state, kObjectType) {
|
: XObject(kernel_state, kObjectType) {
|
||||||
notification_semaphore_ = threading::Semaphore::Create(0, kMaxNotifications);
|
notification_semaphore_ = threading::Semaphore::Create(0, kMaxNotifications);
|
||||||
|
assert_not_null(notification_semaphore_);
|
||||||
}
|
}
|
||||||
|
|
||||||
XIOCompletion::~XIOCompletion() = default;
|
XIOCompletion::~XIOCompletion() = default;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* 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_);
|
assert_false(mutant_);
|
||||||
|
|
||||||
mutant_ = xe::threading::Mutant::Create(initial_owner);
|
mutant_ = xe::threading::Mutant::Create(initial_owner);
|
||||||
|
assert_not_null(mutant_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XMutant::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) {
|
void XMutant::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) {
|
||||||
|
|
|
@ -2,13 +2,14 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "xenia/kernel/xnotifylistener.h"
|
#include "xenia/kernel/xnotifylistener.h"
|
||||||
|
|
||||||
|
#include "xenia/base/assert.h"
|
||||||
#include "xenia/base/byte_stream.h"
|
#include "xenia/base/byte_stream.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/kernel/kernel_state.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_);
|
assert_false(wait_handle_);
|
||||||
|
|
||||||
wait_handle_ = xe::threading::Event::CreateManualResetEvent(false);
|
wait_handle_ = xe::threading::Event::CreateManualResetEvent(false);
|
||||||
|
assert_not_null(wait_handle_);
|
||||||
mask_ = mask;
|
mask_ = mask;
|
||||||
max_version_ = max_version;
|
max_version_ = max_version;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
@ -410,7 +410,9 @@ object_ref<XObject> XObject::GetNativeObject(KernelState* kernel_state,
|
||||||
case 5: // SemaphoreObject
|
case 5: // SemaphoreObject
|
||||||
{
|
{
|
||||||
auto sem = new XSemaphore(kernel_state);
|
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;
|
object = sem;
|
||||||
} break;
|
} break;
|
||||||
case 3: // ProcessObject
|
case 3: // ProcessObject
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* 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;
|
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_);
|
assert_false(semaphore_);
|
||||||
|
|
||||||
CreateNative(sizeof(X_KSEMAPHORE));
|
CreateNative(sizeof(X_KSEMAPHORE));
|
||||||
|
|
||||||
maximum_count_ = maximum_count;
|
maximum_count_ = maximum_count;
|
||||||
semaphore_ = xe::threading::Semaphore::Create(initial_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_);
|
assert_false(semaphore_);
|
||||||
|
|
||||||
auto semaphore = reinterpret_cast<X_KSEMAPHORE*>(native_ptr);
|
auto semaphore = reinterpret_cast<X_KSEMAPHORE*>(native_ptr);
|
||||||
maximum_count_ = semaphore->limit;
|
maximum_count_ = semaphore->limit;
|
||||||
semaphore_ = xe::threading::Semaphore::Create(semaphore->header.signal_state,
|
semaphore_ = xe::threading::Semaphore::Create(semaphore->header.signal_state,
|
||||||
semaphore->limit);
|
semaphore->limit);
|
||||||
|
return !!semaphore_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t XSemaphore::ReleaseSemaphore(int32_t release_count) {
|
int32_t XSemaphore::ReleaseSemaphore(int32_t release_count) {
|
||||||
|
@ -85,6 +87,7 @@ object_ref<XSemaphore> XSemaphore::Restore(KernelState* kernel_state,
|
||||||
|
|
||||||
sem->semaphore_ =
|
sem->semaphore_ =
|
||||||
threading::Semaphore::Create(free_count, sem->maximum_count_);
|
threading::Semaphore::Create(free_count, sem->maximum_count_);
|
||||||
|
assert_not_null(sem->semaphore_);
|
||||||
|
|
||||||
return object_ref<XSemaphore>(sem);
|
return object_ref<XSemaphore>(sem);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* 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);
|
explicit XSemaphore(KernelState* kernel_state);
|
||||||
~XSemaphore() override;
|
~XSemaphore() override;
|
||||||
|
|
||||||
void Initialize(int32_t initial_count, int32_t maximum_count);
|
[[nodiscard]] bool Initialize(int32_t initial_count, int32_t maximum_count);
|
||||||
void InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header);
|
[[nodiscard]] bool InitializeNative(void* native_ptr,
|
||||||
|
X_DISPATCH_HEADER* header);
|
||||||
|
|
||||||
int32_t ReleaseSemaphore(int32_t release_count);
|
int32_t ReleaseSemaphore(int32_t release_count);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
@ -1057,6 +1057,7 @@ object_ref<XThread> XThread::Restore(KernelState* kernel_state,
|
||||||
// Release the self-reference to the thread.
|
// Release the self-reference to the thread.
|
||||||
thread->ReleaseHandle();
|
thread->ReleaseHandle();
|
||||||
});
|
});
|
||||||
|
assert_not_null(thread->thread_);
|
||||||
|
|
||||||
// Notify processor we were recreated.
|
// Notify processor we were recreated.
|
||||||
thread->emulator()->processor()->OnThreadCreated(
|
thread->emulator()->processor()->OnThreadCreated(
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* 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. *
|
* 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();
|
assert_always();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
assert_not_null(timer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
X_STATUS XTimer::SetTimer(int64_t due_time, uint32_t period_ms,
|
X_STATUS XTimer::SetTimer(int64_t due_time, uint32_t period_ms,
|
||||||
|
|
Loading…
Reference in New Issue