[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:
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<char, 8> 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<int> wait_count(0);
|
||||
std::atomic<bool> 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();
|
||||
|
||||
@@ -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<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));
|
||||
|
||||
Reference in New Issue
Block a user